Next.js
Integrate the ScamVerify™ API with your Next.js application using server-side route handlers.
This guide shows you how to call the ScamVerify™ API from a Next.js application using App Router route handlers. All API calls happen server-side so your API key is never exposed to the browser.
Environment Setup
Add your API key to .env.local:
SCAMVERIFY_API_KEY=sv_live_your_key_hereNever prefix your API key with NEXT_PUBLIC_. ScamVerify™ API keys must stay server-side only. Using NEXT_PUBLIC_ would expose your key in the browser bundle.
Route Handler
Create a route handler that proxies requests to the ScamVerify™ API.
// app/api/verify-phone/route.ts
import { NextRequest, NextResponse } from 'next/server';
const SCAMVERIFY_API_KEY = process.env.SCAMVERIFY_API_KEY;
export async function POST(request: NextRequest) {
const { phoneNumber } = await request.json();
if (!phoneNumber) {
return NextResponse.json(
{ error: 'Phone number is required' },
{ status: 400 }
);
}
try {
const response = await fetch('https://scamverify.ai/api/v1/phone/lookup', {
method: 'POST',
headers: {
'Authorization': `Bearer ${SCAMVERIFY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ phone_number: phoneNumber }),
});
if (!response.ok) {
return NextResponse.json(
{ error: `Verification failed: ${response.status}` },
{ status: response.status }
);
}
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
console.error('ScamVerify API error:', error);
return NextResponse.json(
{ error: 'Verification service unavailable' },
{ status: 503 }
);
}
}// app/api/verify-url/route.ts
import { NextRequest, NextResponse } from 'next/server';
const SCAMVERIFY_API_KEY = process.env.SCAMVERIFY_API_KEY;
export async function POST(request: NextRequest) {
const { url } = await request.json();
if (!url) {
return NextResponse.json(
{ error: 'URL is required' },
{ status: 400 }
);
}
try {
const response = await fetch('https://scamverify.ai/api/v1/url/lookup', {
method: 'POST',
headers: {
'Authorization': `Bearer ${SCAMVERIFY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ url }),
});
if (!response.ok) {
return NextResponse.json(
{ error: `Verification failed: ${response.status}` },
{ status: response.status }
);
}
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
console.error('ScamVerify API error:', error);
return NextResponse.json(
{ error: 'Verification service unavailable' },
{ status: 503 }
);
}
}// app/api/screen-email/route.ts
import { NextRequest, NextResponse } from 'next/server';
const SCAMVERIFY_API_KEY = process.env.SCAMVERIFY_API_KEY;
export async function POST(request: NextRequest) {
const { emailBody, rawHeaders } = await request.json();
if (!emailBody) {
return NextResponse.json(
{ error: 'Email body is required' },
{ status: 400 }
);
}
const payload: Record<string, string> = { email_body: emailBody };
if (rawHeaders) {
payload.raw_headers = rawHeaders;
}
try {
const response = await fetch('https://scamverify.ai/api/v1/email/analyze', {
method: 'POST',
headers: {
'Authorization': `Bearer ${SCAMVERIFY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (!response.ok) {
return NextResponse.json(
{ error: `Analysis failed: ${response.status}` },
{ status: response.status }
);
}
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
console.error('ScamVerify API error:', error);
return NextResponse.json(
{ error: 'Analysis service unavailable' },
{ status: 503 }
);
}
}Client-Side Usage
Call your route handler from a client component. Your API key stays on the server.
'use client';
import { useState } from 'react';
export function PhoneVerifier() {
const [phone, setPhone] = useState('');
const [result, setResult] = useState<any>(null);
const [loading, setLoading] = useState(false);
async function handleVerify() {
setLoading(true);
try {
const response = await fetch('/api/verify-phone', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phoneNumber: phone }),
});
const data = await response.json();
setResult(data);
} catch {
setResult({ error: 'Verification failed' });
} finally {
setLoading(false);
}
}
return (
<div>
<input
type="tel"
value={phone}
onChange={(e) => setPhone(e.target.value)}
placeholder="(555) 123-4567"
/>
<button onClick={handleVerify} disabled={loading}>
{loading ? 'Checking...' : 'Verify'}
</button>
{result && (
<div>
<p>Score: {result.risk_score}/100</p>
<p>Verdict: {result.verdict}</p>
<p>{result.explanation}</p>
</div>
)}
</div>
);
}Caching Strategy
ScamVerify™ caches results for 24 hours on its end. You can add a second layer of caching in your Next.js app using the next fetch option or a data cache.
// Server-side caching with Next.js revalidation
const response = await fetch('https://scamverify.ai/api/v1/phone/lookup', {
method: 'POST',
headers: {
'Authorization': `Bearer ${SCAMVERIFY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ phone_number: phoneNumber }),
next: { revalidate: 3600 }, // Cache for 1 hour on your side
});Cached lookups from the ScamVerify™ API do not consume your quota. The cached: true field in the response tells you when a result was served from cache.
Error Handling
Handle the three most common error responses in your route handler:
if (response.status === 401) {
// API key is invalid or has been revoked
console.error('ScamVerify: Invalid API key');
return NextResponse.json({ error: 'Service configuration error' }, { status: 500 });
}
if (response.status === 402) {
// Quota exhausted for this billing period
return NextResponse.json({ error: 'Verification quota reached' }, { status: 503 });
}
if (response.status === 429) {
// Rate limit exceeded, check Retry-After header
const retryAfter = response.headers.get('Retry-After');
return NextResponse.json(
{ error: 'Too many requests', retryAfter },
{ status: 429 }
);
}Related
- Quickstart for initial API key setup
- Build a Phone Verification Flow for a complete tutorial
- Common Issues for troubleshooting