ScamVerify™
Integrations

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_here

Never 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 }
  );
}

On this page