Skip to content

JavaScript (Fetch)

View as Markdown

No package to install — the native fetch API works in all modern browsers and Node.js 18+.

Basic check

async function checkEmail(email) {
try {
const res = await fetch(
`https://api.syvel.io/v1/check/${encodeURIComponent(email)}`,
{
headers: { Authorization: 'Bearer sv_your_key' },
signal: AbortSignal.timeout(3000),
}
);
if (!res.ok) return null; // quota exceeded or server error → fail open
return await res.json();
} catch {
return null; // network error or timeout → fail open
}
}
// In a form submit handler:
const result = await checkEmail(email);
if (result?.is_risky) {
// block the user
}
// if result is null → API unavailable, let the user through

HTML form with real-time validation

<form id="signup-form">
<input type="email" id="email" name="email" placeholder="[email protected]" />
<p id="email-error" style="color: red; display: none;"></p>
<button type="submit">Sign up</button>
</form>
<script>
const emailInput = document.getElementById('email');
const emailError = document.getElementById('email-error');
let debounce;
emailInput.addEventListener('input', () => {
clearTimeout(debounce);
debounce = setTimeout(async () => {
const email = emailInput.value;
if (!email.includes('@')) return;
try {
const res = await fetch(
`https://api.syvel.io/v1/check/${encodeURIComponent(email)}`,
{
headers: { Authorization: 'Bearer sv_your_key' },
signal: AbortSignal.timeout(3000),
}
);
const result = res.ok ? await res.json() : null;
if (result?.is_risky) {
emailError.textContent = 'Please use a real email address.';
emailError.style.display = 'block';
} else {
emailError.style.display = 'none';
}
} catch {
emailError.style.display = 'none'; // fail open
}
}, 500);
});
</script>

React hook

import { useState, useCallback } from 'react';
const API_KEY = import.meta.env.VITE_SYVEL_API_KEY;
export function useEmailCheck() {
const [isRisky, setIsRisky] = useState<boolean | null>(null);
const [loading, setLoading] = useState(false);
const check = useCallback(async (email: string) => {
if (!email.includes('@')) return;
setLoading(true);
try {
const res = await fetch(
`https://api.syvel.io/v1/check/${encodeURIComponent(email)}`,
{
headers: { Authorization: `Bearer ${API_KEY}` },
signal: AbortSignal.timeout(3000),
}
);
const data = res.ok ? await res.json() : null;
setIsRisky(data?.is_risky ?? null);
} catch {
setIsRisky(null); // fail open
} finally {
setLoading(false);
}
}, []);
return { isRisky, loading, check };
}
// Usage in a component:
function SignupForm() {
const { isRisky, loading, check } = useEmailCheck();
return (
<div>
<input
type="email"
onChange={(e) => check(e.target.value)}
placeholder="[email protected]"
/>
{loading && <span>Checking…</span>}
{isRisky && (
<p style={{ color: 'red' }}>
Disposable email detected. Please use a professional address.
</p>
)}
</div>
);
}

Node.js 18+ (Express)

async function checkEmail(email) {
try {
const res = await fetch(
`https://api.syvel.io/v1/check/${encodeURIComponent(email)}`,
{
headers: { Authorization: `Bearer ${process.env.SYVEL_API_KEY}` },
signal: AbortSignal.timeout(3000),
}
);
if (!res.ok) return null;
return await res.json();
} catch {
return null;
}
}
app.post('/register', async (req, res) => {
const result = await checkEmail(req.body.email);
if (result?.is_risky) {
return res.status(422).json({ error: 'Please use a professional email address.' });
}
// continue with registration…
});

Resources

Last updated: