Code examples
JavaScript (Node.js 18+ or browser backend)
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
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
$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.
// 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.
// 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.
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
POST /v1/check
{ "email": "qwerty1234@yahoo.com", "ip": "3.5.140.10" }
{
"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
POST /v1/check
{ "email": "j.o.hn+promo7@gmial.com" }
{
"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 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 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 above.
All three fail open: if the API is slow or unreachable, the signup still goes through.