Documentation

Protect Your Signup Flow

SignGuard is a single API call you put before your database write to block free-trial abuse, burner emails, and bots. It takes 3 lines of code and evaluates the email using a fast in-memory lookup.


Authentication & Base URL

All API requests must be made over HTTPS. The base URL for all endpoints is:

bash
https://api.signguard.co

Authenticate your API requests by including your API key in the Authorization header as a Bearer token. You can generate an API key from the Dashboard.

bash
Authorization: Bearer dsk_live_your_api_key_here

Quickstart: API Request

Get your API key from the dashboard and pass it as a Bearer token. We recommend using mode="fast" on signup forms to skip the physical SMTP ping and keep latency low.

How it works:

01
User Inputs Email
A user signs up on your landing page or free trial form.
02
Call /v1/check
Query SignGuard before you execute your auth hook or write to your DB.
03
Check Decision
If the API returns "block", interrupt the flow and prompt for a work email.
04
Onboard User
If "allow", safely generate their user records and award trial credits.
javascript
// Example usage in Javascript/Typescript const response = await fetch('https://api.signguard.co/v1/check', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ email: 'spammer@tempmail.xyz', mode: 'fast' }), }); const result = await response.json(); console.log(result.decision); // "block" console.log(result.reasons); // ["disposable_email"]

Python SDK & Node.js HTTP Integration

Our open-source Python SDK automatically falls back to local offline evaluation if the API is unreachable. For Node.js and other environments, we recommend a fail-open try/catch wrapper.

Python SDK (Built-in Offline Fallback)

python
# 1. Install package pip install disposable-email-score[api] # 2. Set environment variable export SIGNGUARD_API_KEY="dsk_live_your_key_here" # 3. Perform check in Python (falls back to local offline engine if API is unreachable) from disposable_email_score import configure, evaluate_email configure() # Reads SIGNGUARD_API_KEY from environment result = evaluate_email("user@tempmail.xyz") if result.decision == "block": print("❌ Blocked disposable email!")

Node.js / TypeScript (Fail-Open HTTP API)

Use native fetch() with a 3-second timeout. If the request fails or times out, fail-open to allow the signup.

javascript
async function checkEmail(email) { try { const response = await fetch("https://api.signguard.co/v1/check", { method: "POST", headers: { "Authorization": `Bearer ${process.env.SIGNGUARD_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ email, mode: "fast" }), signal: AbortSignal.timeout(3000) // 3s timeout }); if (!response.ok) throw new Error(`API returned status ${response.status}`); const data = await response.json(); return data.decision; // "allow", "review", or "block" } catch (err) { console.warn("SignGuard API unreachable, failing open:", err.message); return "allow"; // Fail-open: allow signup on network timeout or error } }

Integration Recipes

Copy and paste these snippets into your favorite framework.

Next.js App Router (Server Action)

javascript
"use server"; export async function signUpUser(formData: FormData) { const email = formData.get("email"); // 1. Check risk const response = await fetch('https://api.signguard.co/v1/check', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.SIGNGUARD_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ email, mode: 'fast' }), }); const check = await response.json(); if (check.decision === "block") { return { error: "Please use a legitimate email address." }; } // 2. Safe to create user in DB await db.users.create({ email }); }

Supabase / Clerk Webhook

javascript
app.post("/webhook/user.created", async (req, res) => { const email = req.body.data.email_address; const response = await fetch('https://api.signguard.co/v1/check', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.SIGNGUARD_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ email, mode: 'fast' }), }); const check = await response.json(); if (check.decision === "block") { // Optionally delete the user instantly if they bypassed the frontend await supabase.auth.admin.deleteUser(req.body.data.id); return res.status(403).send("User deleted - fraud detected."); } res.send("OK"); });

Response Schema & Decisions

Our API returns clear decisions and rich signals so you never have to guess why a user was blocked.

json
{ "email": "spammer@gmaiil.com", "decision": "block", // "allow", "review", or "block" "score": 1.0, // 0.0 (safe) to 1.0 (fraudulent) "thresholds": { "allow": 0.3, "block": 0.7 }, "is_disposable": false, "has_mx_records": true, "mailbox_exists": false, "domain_age_days": 2, "is_catch_all": false, "signals": { "typosquatting": 0.6, "role_account": 0.2 }, "reasons": [ "typosquatting_detected:gmail.com", "role_account_detected" ] }

Error Reference

SignGuard uses conventional HTTP response codes to indicate the success or failure of an API request.

StatusError TypeDescription
400bad_requestInvalid email format or request body.
401unauthorizedMissing or invalid API key.
429rate_limit_exceededPer-minute rate limit or monthly quota exceeded.
500internal_errorSomething went wrong on our end. Fail open!

Rate Limits & Quotas

We enforce two types of limits to protect our infrastructure and your billing plan:

  • Per-minute:600 requests/minute (Sliding window) for Free, Starter, and Pro plans. Enterprise plan allows 3000+ requests/minute.
  • Monthly Quota:Based on your plan (Free: 200, Starter: 20K, Pro: 100K, Enterprise: 250K+).

If you exceed these limits, the API will return a 429 Too Many Requests error. We strongly recommend configuring your application to fail open (allow the signup) if a 429 occurs.


Idempotency & Safe Retries

SignGuard automatically detects exact duplicate API requests using a built-in idempotency engine.

How it works

If your application accidentally sends the exact same payload multiple times in a row (e.g., a user double-clicking a submit button, or a network timeout triggering an automatic retry), we serve the response from cache instantly.

Zero Cost for Duplicates: Cached idempotent responses do not charge your monthly quota and do not increment your usage counter.


Production Checklist

Before going live with real signups, ensure you've handled these edge cases to guarantee high availability.

  • 1. Handle All Decisions

    Don't blindly trust or block. Map the 3 decision states to UX:

    • "allow": Let them through immediately.
    • "review": (Optional) Challenge with an OTP, CAPTCHA, or push to manual review. Treat as "allow" if you prefer low friction.
    • "block": Hard stop. Reject the signup and ask for a work email.
  • 2. Fail Open on Errors (Timeouts & 5xx)

    If our API times out or returns a 5xx error, wrap it in a try/catch and allow the signup. Do not block a legitimate customer because of a network flake.

  • 3. Respect Quota Limits (429 / 401)

    If you hit your Free quota limit, the API returns a 429 Too Many Requests. You should fail open (allow the user) and upgrade your plan in the dashboard.

  • 4. False Positives? Use the Allowlist

    If a real customer is accidentally blocked by a strict rule, go to the Dashboard → API Keys → Settings and add their domain to the Custom Allowlist. It applies instantly.


Estimated Cost Avoided (Dashboard ROI)

The dashboard multiplies blocked risky signups by your cost per fake signup. Default is $0.50 (a rough estimate for free-trial or LLM-credit costs). Change it under the Signup Protection card to match your actual infrastructure cost. This is an internal estimate for ROI tracking, not a real billing number.


Modes: fast vs deep

The mode parameter controls how aggressively we verify the email. Default is deep if omitted.

mode: "fast" (Recommended)

Best for inline signup forms. Completes quickly with no external SMTP round-trip.

  • Disposable/Burner blocklists
  • Custom Allow/Block lists
  • DNS MX Record check
  • Domain Age verification
  • Typosquatting engine

mode: "deep"

Best for background jobs or async cleaning. Completes in 1-3s.

  • Everything in "fast" mode
  • Active SMTP mailbox ping
  • Catch-all domain detection

Advanced: Batch Endpoint (/v1/check/batch)

For cleaning historical users from your database, you can pass up to 100 emails at once.

json
POST /v1/check/batch { "emails": [ "user1@gmail.com", "spammer@tempmail.com" ], "mode": "fast" }

Email Finder Endpoint (/v1/find)

Find anyone's verified work email address from their name and company domain. Generates 15 permutation patterns and performs real-time SMTP verification against the domain's mail server.

json
curl -X POST https://api.signguard.co/v1/find \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "first_name": "John", "last_name": "Doe", "domain": "stripe.com" }' # NOTE: This endpoint charges 5 request credits per call due to heavy SMTP validation. # Response { "status": "found", // "found", "not_found", "catch_all", or "error" "email": "john.doe@stripe.com", "message": "Verified email found.", "permutations_tested": 15 }

Advanced: MCP Server for AI Agents

For developers orchestrating Claude Desktop or Cursor, we provide a native Model Context Protocol (MCP) server so your agents can validate emails natively without writing HTTP wrappers.

json
"mcpServers": { "signguard": { "command": "uvx", "args": ["signguard-mcp-server"], "env": { "SIGNGUARD_API_KEY": "YOUR_KEY" } } }