Code Examples

Working code for the common integration points, with every example available in cURL, JavaScript/Node.js, Python, PHP, and Go where it applies — switch languages using the tabs on each code block rather than hunting through separate per-language pages.

A minimal client

No SDK is required for any of these — each is a small, dependency-free wrapper worth copying into a project as-is.

email-risk-client.js
const BASE_URL = "https://api.emailriskradar.com";

class EmailRiskApiError extends Error {
  constructor(code, message, status) {
    super(message);
    this.code = code;
    this.status = status;
  }
}

export function createClient(apiKey) {
  async function request(path, options = {}) {
    const res = await fetch(`${BASE_URL}${path}`, {
      ...options,
      headers: {
        Authorization: `Bearer ${apiKey}`,
        "Content-Type": "application/json",
        ...options.headers,
      },
    });

    const data = await res.json();
    if (!res.ok) throw new EmailRiskApiError(data.error.code, data.error.message, res.status);
    return data;
  }

  return {
    checkEmail: (email, { mode = "standard", context = "generic" } = {}) =>
      request("/v1/email/check", { method: "POST", body: JSON.stringify({ email, mode, context }) }),

    submitBulk: (emails, { mode = "standard", context = "generic" } = {}) =>
      request("/v1/email/bulk", { method: "POST", body: JSON.stringify({ emails, mode, context }) }),

    getBulkStatus: (jobId) => request(`/v1/email/bulk/${jobId}`),

    getBulkResults: (jobId, page = 1) => request(`/v1/email/bulk/${jobId}/results?page=${page}`),
  };
}

Using it

usage.js
import { createClient } from "./email-risk-client.js";

const client = createClient(process.env.EMAIL_RISK_API_KEY);

const result = await client.checkEmail("user@example.com", { context: "signup" });
console.log(result.decision, result.risk.score);

Bulk submission and polling

For anything beyond a quick script, prefer a webhook over polling — see Error Handling & Webhook Security for signature verification, and register the endpoint from the dashboard.

bulk.sh
JOB_ID=$(curl -s https://api.emailriskradar.com/v1/email/bulk \
  -H "Authorization: Bearer $EMAIL_RISK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["a@example.com", "b@example.com"], "context": "crm"}' \
  | jq -r '.job_id')

until [ "$(curl -s "https://api.emailriskradar.com/v1/email/bulk/$JOB_ID" \
  -H "Authorization: Bearer $EMAIL_RISK_API_KEY" | jq -r '.status')" = "completed" ]; do
  sleep 2
done

curl -s "https://api.emailriskradar.com/v1/email/bulk/$JOB_ID/results?page=1" \
  -H "Authorization: Bearer $EMAIL_RISK_API_KEY" | jq '.data'

Framework integration examples

The signup-time check pattern described in Checking at Signup Without Blocking the Flow, implemented in a few common frameworks:

app/actions/signup.ts
"use server";
import { createClient } from "@/lib/email-risk-client";

export async function signupAction(formData: FormData) {
  const email = formData.get("email") as string;
  const client = createClient(process.env.EMAIL_RISK_API_KEY!);

  const result = await client.checkEmail(email, { context: "signup" });
  if (result.decision === "block") {
    return { error: "This email address can't be used to sign up." };
  }

  // create the account...
}

As always: never expose EMAIL_RISK_API_KEY to the browser, and for anything beyond a single-instance service, push background checks onto a real job queue instead of a bare goroutine or dangling promise — those don't survive the process restarting mid-check.

We use Google Analytics to understand site traffic, and only load it if you accept — nothing runs before you choose. Signing in still stores a strictly necessary session token regardless. See the Privacy Policy for details.