Conure API

Express bot detection and email validation

A factory-style middleware with an explicit timeout and fail-open behaviour, mountable per route.

1. Install

npm install express

2. Add the file

middleware/conure.js

const CONURE = "https://uat.conureapi.com";

/**
 * @param {{ key: string, timeoutMs?: number }} options
 */
export function blockBots({ key, timeoutMs = 3000 }) {
  if (!key) throw new Error("blockBots: missing API key");

  return async function (request, response, next) {
    const ip = request.ip;
    if (!ip) return next();

    try {
      const upstream = await fetch(CONURE + "/v1/bot-check", {
        method: "POST",
        headers: { Authorization: "Bearer " + key, "Content-Type": "application/json" },
        body: JSON.stringify({ ip, user_agent: request.get("user-agent") || "" }),
        signal: AbortSignal.timeout(timeoutMs),
      });

      // A 4xx or 5xx from us is not a verdict.
      if (!upstream.ok) return next();

      const verdict = await upstream.json();
      if (verdict.is_bot === true) {
        return response.status(403).json({
          error: "Automated traffic is not permitted.",
          reasons: verdict.reasons ?? [],
        });
      }
    } catch (error) {
      request.log?.warn?.({ error }, "conure unreachable");
    }
    return next();
  };
}

3. Wire it up

import express from "express";
import { blockBots } from "./middleware/conure.js";

const app = express();
app.set("trust proxy", 1); // required for request.ip to be the real client
app.use(express.json());

app.post("/signup", blockBots({ key: process.env.CONURE_API_KEY }), signupHandler);

4. Verify

Confirm the API answers before you debug your Express wiring. The sample address sits inside a published AWS range, so a correct setup returns is_bot: true.

Notes

Other frameworks