---
title: "Code Examples"
description: "Copy-paste SignupSieve integrations for Node.js, Python, PHP, Next.js, Express and Laravel."
canonical_url: "https://signupsieve.pages.dev/docs/examples"
---

> Index of every page on this site: [llms.txt](https://signupsieve.pages.dev/llms.txt)

# Code examples

## JavaScript (Node.js 18+ or browser backend)

```js
const res = await fetch("https://signupsieve.p.rapidapi.com/v1/check", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-RapidAPI-Key": process.env.RAPIDAPI_KEY,
    "X-RapidAPI-Host": "signupsieve.p.rapidapi.com",
  },
  body: JSON.stringify({ email, ip: req.ip }),
});
const result = await res.json();

if (result.did_you_mean) {
  return showHint(`Did you mean ${result.did_you_mean}?`);
}
if (result.verdict === "block") {
  return reject("Please use a valid, personal email address.");
}
const user = await createUser({
  email,
  canonical: result.canonical, // unique index on this stops duplicate accounts
  needsVerification: result.verdict === "review",
});
```

## Python

```python
import os, requests

HEADERS = {
    "X-RapidAPI-Key": os.environ["RAPIDAPI_KEY"],
    "X-RapidAPI-Host": "signupsieve.p.rapidapi.com",
}
URL = "https://signupsieve.p.rapidapi.com"

result = requests.post(f"{URL}/v1/check", headers=HEADERS,
                       json={"email": email, "ip": ip}, timeout=10).json()

if result["verdict"] == "block":
    raise ValueError("Please use a valid email address.")

# Later, once the user verifies their email:
requests.post(f"{URL}/v1/feedback", headers=HEADERS,
              json={"email": email, "outcome": "confirmed"}, timeout=10)
```

## PHP

```php
$ch = curl_init("https://signupsieve.p.rapidapi.com/v1/check");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Content-Type: application/json",
        "X-RapidAPI-Key: " . getenv("RAPIDAPI_KEY"),
        "X-RapidAPI-Host: signupsieve.p.rapidapi.com",
    ],
    CURLOPT_POSTFIELDS => json_encode(["email" => $email, "ip" => $_SERVER["REMOTE_ADDR"]]),
]);
$result = json_decode(curl_exec($ch), true);
```

> **Keep your RapidAPI key on your server.** Never put it in browser or mobile app code.

## Next.js (App Router)

A route handler for your signup form. It fails open: if the check times out, the signup goes through.

```ts
// app/api/signup/route.ts
export async function POST(req: Request) {
  const { email } = await req.json();
  const ip = req.headers.get("x-forwarded-for")?.split(",")[0]?.trim();

  let result: { verdict?: string; canonical?: string; did_you_mean?: string } = {};
  try {
    const res = await fetch("https://signupsieve.p.rapidapi.com/v1/check", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-RapidAPI-Key": process.env.RAPIDAPI_KEY!,
        "X-RapidAPI-Host": "signupsieve.p.rapidapi.com",
      },
      body: JSON.stringify({ email, ip }),
      signal: AbortSignal.timeout(3000),
    });
    if (res.ok) result = await res.json();
  } catch {
    // Network problem: let the signup through and check it later.
  }

  if (result.did_you_mean) {
    return Response.json({ error: `Did you mean ${result.did_you_mean}?` }, { status: 422 });
  }
  if (result.verdict === "block") {
    return Response.json({ error: "Please use a valid, personal email address." }, { status: 422 });
  }
  // Save result.canonical with a unique index to stop duplicate accounts.
  return Response.json({ ok: true, needsVerification: result.verdict === "review" });
}
```

## Express

A middleware you can put in front of any signup route.

```js
// Behind a load balancer, set app.set("trust proxy", 1) so req.ip is the user's IP.
async function signupSieve(req, res, next) {
  try {
    const r = await fetch("https://signupsieve.p.rapidapi.com/v1/check", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-RapidAPI-Key": process.env.RAPIDAPI_KEY,
        "X-RapidAPI-Host": "signupsieve.p.rapidapi.com",
      },
      body: JSON.stringify({ email: req.body.email, ip: req.ip }),
      signal: AbortSignal.timeout(3000),
    });
    if (r.ok) req.signupCheck = await r.json();
  } catch {
    // Fail open on network problems.
  }
  if (req.signupCheck?.verdict === "block") {
    return res.status(422).json({
      error: "Please use a valid, personal email address.",
      did_you_mean: req.signupCheck.did_you_mean,
    });
  }
  next();
}

app.post("/signup", express.json(), signupSieve, createUser);
```

## Laravel

A validation rule. Put your key in `config/services.php` as `signupsieve.key`.

```php
use Closure;
use Illuminate\Support\Facades\Http;

$request->validate([
    'email' => ['required', 'email', function (string $attribute, mixed $value, Closure $fail) use ($request) {
        // rescue() returns null on network errors, so the signup goes through.
        $result = rescue(fn () => Http::withHeaders([
            'X-RapidAPI-Key' => config('services.signupsieve.key'),
            'X-RapidAPI-Host' => 'signupsieve.p.rapidapi.com',
        ])->timeout(3)->post('https://signupsieve.p.rapidapi.com/v1/check', [
            'email' => $value,
            'ip' => $request->ip(),
        ])->throw()->json(), null, false);

        if (isset($result['did_you_mean'])) {
            $fail("Did you mean {$result['did_you_mean']}?");
        } elseif (($result['verdict'] ?? null) === 'block') {
            $fail('Please use a valid, personal email address.');
        }
    }],
]);
```

## Example: catching a fake signup

```json
POST /v1/check
{ "email": "qwerty1234@yahoo.com", "ip": "3.5.140.10" }
```

```json
{
  "email": "qwerty1234@yahoo.com",
  "canonical": "qwerty1234@yahoo.com",
  "account_type": "free",
  "deliverable_domain": true,
  "mail_provider": "yahoo",
  "human_score": 3,
  "verdict": "block",
  "reasons": ["keyboard_pattern", "datacenter_ip", "unnatural_name", "long_digit_run"],
  "ip": { "datacenter": "aws", "tor": false, "signups_from_ip": 1 },
  "check_id": "chk_AbQY_Yyt0JRL1mpGtCtC...",
  "model": "baseline"
}
```

## Example: catching a typo

```json
POST /v1/check
{ "email": "j.o.hn+promo7@gmial.com" }
```

```json
{
  "canonical": "j.o.hn@gmial.com",
  "did_you_mean": "j.o.hn+promo7@gmail.com",
  "human_score": 9,
  "verdict": "block",
  "reasons": ["domain_typo", "unnatural_name"]
}
```

Show `did_you_mean` to the user instead of rejecting them outright.

## Block disposable emails by framework

### Block disposable emails in Next.js

Call the API from a route handler before you create the user, and reject a `block` verdict. See the [Next.js example](#nextjs-app-router) above.

### Block disposable emails in Express

Add a small middleware in front of your signup route that rejects `block` and passes everything else through. See the [Express example](#express) above.

### Block disposable emails in Laravel

Use a validation rule on the email field, so a throwaway address fails like any other invalid input. See the [Laravel example](#laravel) above.

All three fail open: if the API is slow or unreachable, the signup still goes through.

## Sitemap

See the full [sitemap](https://signupsieve.pages.dev/sitemap.md) for all pages.
