ScamVerify™
Integrations

Django

Integrate the ScamVerify™ API with your Django application using views and the requests library.

This guide shows you how to call the ScamVerify™ API from a Django application. You will create a reusable client class, Django views for phone and URL verification, and proper error handling.

Environment Setup

Add your API key to your Django settings. Never hardcode it in source files.

# settings.py
import os

SCAMVERIFY_API_KEY = os.environ.get('SCAMVERIFY_API_KEY')

Set the environment variable in your deployment configuration or .env file:

SCAMVERIFY_API_KEY=sv_live_your_key_here

Reusable Client

Create a client module that you can import in any view.

# verification/scamverify_client.py
import requests
from django.conf import settings


class ScamVerifyError(Exception):
    def __init__(self, message, status_code=0):
        super().__init__(message)
        self.status_code = status_code


class ScamVerifyClient:
    BASE_URL = 'https://scamverify.ai/api/v1'

    def __init__(self, api_key=None):
        self.api_key = api_key or settings.SCAMVERIFY_API_KEY
        if not self.api_key:
            raise ScamVerifyError('SCAMVERIFY_API_KEY not configured')
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {self.api_key}',
            'Content-Type': 'application/json',
        })

    def _handle_response(self, response):
        if response.status_code == 401:
            raise ScamVerifyError('Invalid or revoked API key', 401)
        if response.status_code == 402:
            raise ScamVerifyError('Quota exhausted', 402)
        if response.status_code == 429:
            retry_after = response.headers.get('Retry-After', '60')
            raise ScamVerifyError(f'Rate limited. Retry after {retry_after}s', 429)
        response.raise_for_status()
        return response.json()

    def lookup_phone(self, phone_number):
        response = self.session.post(
            f'{self.BASE_URL}/phone/lookup',
            json={'phone_number': phone_number},
        )
        return self._handle_response(response)

    def lookup_url(self, url, force_refresh=False):
        payload = {'url': url}
        if force_refresh:
            payload['force_refresh'] = True
        response = self.session.post(
            f'{self.BASE_URL}/url/lookup',
            json=payload,
        )
        return self._handle_response(response)

    def analyze_text(self, text, sender_number=None):
        payload = {'text': text}
        if sender_number:
            payload['sender_number'] = sender_number
        response = self.session.post(
            f'{self.BASE_URL}/text/analyze',
            json=payload,
        )
        return self._handle_response(response)

    def analyze_email(self, email_body, raw_headers=None):
        payload = {'email_body': email_body}
        if raw_headers:
            payload['raw_headers'] = raw_headers
        response = self.session.post(
            f'{self.BASE_URL}/email/analyze',
            json=payload,
        )
        return self._handle_response(response)

Django Views

# verification/views.py
import json
import logging
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from .scamverify_client import ScamVerifyClient, ScamVerifyError

logger = logging.getLogger(__name__)
client = ScamVerifyClient()


@csrf_exempt
@require_POST
def verify_phone(request):
    try:
        body = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse({'error': 'Invalid JSON'}, status=400)

    phone_number = body.get('phone_number')
    if not phone_number:
        return JsonResponse({'error': 'phone_number is required'}, status=400)

    try:
        result = client.lookup_phone(phone_number)
        return JsonResponse({
            'risk_score': result['risk_score'],
            'verdict': result['verdict'],
            'explanation': result['explanation'],
            'signals': result.get('signals', {}),
            'cached': result.get('cached', False),
        })
    except ScamVerifyError as e:
        logger.error(f'ScamVerify error: {e}')
        return JsonResponse({'error': str(e)}, status=e.status_code or 500)
    except Exception as e:
        logger.exception('Unexpected error during phone verification')
        return JsonResponse({'error': 'Verification unavailable'}, status=503)


@csrf_exempt
@require_POST
def verify_url(request):
    try:
        body = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse({'error': 'Invalid JSON'}, status=400)

    url = body.get('url')
    if not url:
        return JsonResponse({'error': 'url is required'}, status=400)

    try:
        result = client.lookup_url(url)
        return JsonResponse({
            'risk_score': result['risk_score'],
            'verdict': result['verdict'],
            'explanation': result['explanation'],
            'signals': result.get('signals', {}),
            'cached': result.get('cached', False),
        })
    except ScamVerifyError as e:
        logger.error(f'ScamVerify error: {e}')
        return JsonResponse({'error': str(e)}, status=e.status_code or 500)
    except Exception as e:
        logger.exception('Unexpected error during URL verification')
        return JsonResponse({'error': 'Verification unavailable'}, status=503)
# verification/views.py
import json
import logging
from django.http import JsonResponse
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from .scamverify_client import ScamVerifyClient, ScamVerifyError

logger = logging.getLogger(__name__)


@method_decorator(csrf_exempt, name='dispatch')
class PhoneVerificationView(View):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.client = ScamVerifyClient()

    def post(self, request):
        try:
            body = json.loads(request.body)
        except json.JSONDecodeError:
            return JsonResponse({'error': 'Invalid JSON'}, status=400)

        phone_number = body.get('phone_number')
        if not phone_number:
            return JsonResponse({'error': 'phone_number is required'}, status=400)

        try:
            result = self.client.lookup_phone(phone_number)
            return JsonResponse(result)
        except ScamVerifyError as e:
            logger.error(f'ScamVerify error: {e}')
            return JsonResponse({'error': str(e)}, status=e.status_code or 500)


@method_decorator(csrf_exempt, name='dispatch')
class UrlVerificationView(View):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.client = ScamVerifyClient()

    def post(self, request):
        try:
            body = json.loads(request.body)
        except json.JSONDecodeError:
            return JsonResponse({'error': 'Invalid JSON'}, status=400)

        url = body.get('url')
        if not url:
            return JsonResponse({'error': 'url is required'}, status=400)

        try:
            result = self.client.lookup_url(url)
            return JsonResponse(result)
        except ScamVerifyError as e:
            logger.error(f'ScamVerify error: {e}')
            return JsonResponse({'error': str(e)}, status=e.status_code or 500)

URL Configuration

# verification/urls.py
from django.urls import path
from . import views

# For function-based views:
urlpatterns = [
    path('api/verify-phone/', views.verify_phone, name='verify_phone'),
    path('api/verify-url/', views.verify_url, name='verify_url'),
]

# For class-based views:
# urlpatterns = [
#     path('api/verify-phone/', views.PhoneVerificationView.as_view(), name='verify_phone'),
#     path('api/verify-url/', views.UrlVerificationView.as_view(), name='verify_url'),
# ]

Caching with Django Cache Framework

Add a caching layer on top of the ScamVerify™ built-in cache to reduce API calls.

from django.core.cache import cache

def lookup_phone_cached(client, phone_number):
    cache_key = f'scamverify:phone:{phone_number}'
    result = cache.get(cache_key)

    if result is not None:
        return result

    result = client.lookup_phone(phone_number)

    # Cache for 1 hour on your side (ScamVerify caches for 24h on its end)
    cache.set(cache_key, result, timeout=3600)
    return result

Error Handling Middleware

For apps making many ScamVerify™ calls, you can add middleware to handle common errors consistently.

# verification/middleware.py
import logging
from django.http import JsonResponse
from .scamverify_client import ScamVerifyError

logger = logging.getLogger(__name__)


class ScamVerifyErrorMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

    def process_exception(self, request, exception):
        if isinstance(exception, ScamVerifyError):
            logger.error(f'ScamVerify API error: {exception}')
            return JsonResponse(
                {'error': str(exception)},
                status=exception.status_code or 500,
            )
        return None

Django REST Framework users: The same ScamVerifyClient works with DRF serializers and API views. Replace JsonResponse with DRF's Response and add your authentication/permission classes as needed.

On this page