Savdhaan.in
API Reference

Savdhaan API Documentation

Integrate real-time scam detection into your app. Analyze text, images, and URLs against 6+ threat intelligence sources.

Quickstart

Get started with the Savdhaan API in 3 steps. Scan any suspicious text or image and get an evidence-based risk score.

1

Create an account

Sign up with email or Google. Free — no credit card required.

2

Get your API key

Go to your Profile and create an API key. Keys start with svd_ and are shown only once.

3

Make your first scan

Send a POST request with the suspicious content. You'll get a risk score, evidence, and recommended actions.

curl -X POST https://api.savdhaan.in/api/v1/scan \
  -H "X-API-Key: svd_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Congratulations! You won Rs 50,000. Click http://prize.xyz to claim.",
    "content_type": "text"
  }'

Free tier includes 10 scans/hour — enough to get started and test your integration.

Authentication

All API requests require an API key passed via the X-API-Key header.

Request Header
X-API-Key: svd_4a7b3c2d9e1f5a6b8c0d3e4f5a6b7c8d

Key details

  • Format: svd_ prefix + 32 alphanumeric characters
  • Create keys at your Profile page (max 5 active keys)
  • Keys are shown only once at creation — store them securely
  • Never expose your API key in client-side code — always call from your server

POST /api/v1/scan

Scan text content for scam indicators. Returns a risk score, evidence, and recommended actions.

Request Body

ParameterTypeRequiredDescription
contentstringYesText to scan (1–10,000 characters)
content_typeenumNo"text" (default) or "image"
channelenumNo"sms" | "whatsapp" | "email" | "social_dm" | "website" | "other"
categoryenumNo"scam_check" (default) | "job_offer" | "rental_lease" | "investment" | "contract" | "auto"
localestringNoLanguage hint, e.g. "en" (default), "hi"

Example

curl -X POST https://api.savdhaan.in/api/v1/scan \
  -H "X-API-Key: svd_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Congratulations! You won Rs 50,000. Click http://prize.xyz to claim.",
    "content_type": "text"
  }'

Response

200 OK
{
  "ok": true,
  "data": {
    "scan_id": "e7b26d9c-5a2b-4e1a-8f3c-9d2e1c5b7a4f",
    "risk_score": 92,
    "risk_level": "critical",
    "scam_type": "lottery_prize",
    "explanation": "This message exhibits multiple lottery scam indicators...",
    "evidence": [
      {
        "source": "Pattern Detection",
        "detail": "Contains lottery/prize scam phrases",
        "is_threat": true,
        "confidence": 0.99
      },
      {
        "source": "URL Reputation",
        "detail": "Domain prize.xyz registered 3 days ago",
        "is_threat": true,
        "confidence": 0.95
      }
    ],
    "actions": [
      "Do not click any links",
      "Delete the message immediately",
      "Report to your mobile provider"
    ],
    "entities": {
      "urls": ["http://prize.xyz"],
      "phones": [],
      "emails": [],
      "crypto_addresses": [],
      "upi_ids": []
    },
    "checks_performed": [
      "entity_extraction",
      "rule_based_pattern_detection",
      "url_reputation (Google Safe Browsing, PhishTank, URLhaus, VirusTotal)",
      "domain_age_verification (WHOIS)",
      "llm_classification"
    ],
    "checks_not_available": [],
    "confidence_note": "High confidence based on multiple threat signals",
    "content_snippet": "Congratulations! You won Rs 50,000...",
    "scam_card": {
      "card_id": "lty7x9k2",
      "card_url": "https://savdhaan.in/card/lty7x9k2",
      "image_url": "https://savdhaan.in/static/cards/lty7x9k2.png"
    },
    "community": {
      "total_similar_reports": 42,
      "entity_signals": [],
      "first_reported_at": "2025-12-15T10:30:00Z"
    },
    "processing_time_ms": 2156,
    "created_at": "2026-02-22T16:30:45Z"
  }
}

POST /api/v1/scan/image

Scan an image (screenshot) for scam indicators. OCR extracts text automatically, then runs the same analysis pipeline as text scans.

Content-Type must be multipart/form-data — not JSON.

Request Fields

ParameterTypeRequiredDescription
filefileYesImage file: JPEG, PNG, WebP, or GIF (max 10 MB)
channelenumNo"sms" | "whatsapp" | "email" | "social_dm" | "website" | "other"
categoryenumNo"scam_check" (default) | "job_offer" | "rental_lease" | "investment" | "contract" | "auto"
localestringNoLanguage hint, default: "en"

Example

curl -X POST https://api.savdhaan.in/api/v1/scan/image \
  -H "X-API-Key: svd_your_key_here" \
  -F "file=@screenshot.png" \
  -F "channel=whatsapp"

Response format is identical to POST /scan.

GET /api/v1/scan/{scan_id}

Retrieve a previous scan result by its ID. Only returns scans created with your API key.

Path Parameters

ParameterTypeRequiredDescription
scan_idUUIDYesThe scan ID returned from POST /scan

Example

curl https://api.savdhaan.in/api/v1/scan/550e8400-e29b-41d4-a716-446655440000 \
  -H "X-API-Key: svd_your_key_here"

POST /api/v1/scan/streamSSE

Stream scan progress as Server-Sent Events. Same request body as POST /scan. Emits real-time progress events as each pipeline step completes, then a final result event.

Pipeline Steps (9 total)

#StepDescription
1dedup_checkCheck if this content was already scanned
2entity_extractionExtract URLs, phones, emails, UPI IDs, crypto addresses
3rule_engineRun pattern-matching rules (14 signals)
4threat_intelQuery 6+ threat databases in parallel
5llm_classificationAI-powered scam classification
6score_mergeMerge all evidence into final risk score
7actionsGenerate recommended actions
8persistSave results to database
9scam_cardGenerate shareable scam card (if risk >= 40)

Event Types

event: progress— Emitted after each pipeline step
{
  "scan_step": "threat_intel",
  "step_number": 4,
  "total_steps": 9,
  "message": "Checking threat intelligence databases...",
  "elapsed_ms": 1200
}
event: result— Final event with the full scan result
event: error— Emitted if the scan fails

Example

curl -N -X POST https://api.savdhaan.in/api/v1/scan/stream \
  -H "X-API-Key: svd_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"content": "Your account is blocked. Call +91-9999999999 to verify.", "content_type": "text"}'

POST /api/v1/report

Submit feedback on a scan result. Helps improve our detection accuracy.

Request Body

ParameterTypeRequiredDescription
scan_idUUIDYesID of the scan to report on
feedback_typeenumYes"confirmed_scam" | "false_positive" | "false_negative" | "helpful" | "not_helpful"
commentstringNoAdditional context (max 2,000 characters)
contact_emailstringNoEmail for follow-up (max 255 characters)

Example

curl -X POST https://api.savdhaan.in/api/v1/report \
  -H "X-API-Key: svd_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "scan_id": "550e8400-e29b-41d4-a716-446655440000",
    "feedback_type": "confirmed_scam",
    "comment": "This was a real phishing attempt"
  }'

Response

200 OK
{
  "ok": true,
  "data": {
    "report_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "scan_id": "550e8400-e29b-41d4-a716-446655440000",
    "feedback_type": "confirmed_scam",
    "status": "pending",
    "message": "Thank you for your feedback. It helps us improve."
  }
}

Response Format

All API responses use a consistent envelope format.

Success

{
  "ok": true,
  "data": { ... },
  "error": null,
  "meta": {
    "request_id": "550e8400-..."
  }
}

Error

{
  "ok": false,
  "data": null,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded."
  },
  "meta": {
    "request_id": "550e8400-..."
  }
}

Risk Level Scale

LevelScore RangeMeaning
critical80–100Almost certainly a scam — do not engage
high60–79Strong scam indicators detected
medium40–59Some suspicious patterns — proceed with caution
low20–39Minor signals — likely safe but verify
none0–19No scam indicators found

Key Response Fields

ParameterTypeRequiredDescription
scan_idUUIDYesUnique identifier for this scan
risk_scoreintegerYes0–100 risk score
risk_levelstringYescritical | high | medium | low | none
scam_typestringNoDetected scam category (e.g. phishing, upi_fraud, lottery_prize)
explanationstringYesAI-generated explanation of the risk assessment
evidencearrayYesList of specific threat signals found (source, detail, confidence)
actionsarrayYesRecommended actions for the user
entitiesobjectYesExtracted entities: urls, phones, emails, crypto_addresses, upi_ids
scam_cardobjectNoShareable scam card (card_id, card_url, image_url) — generated when risk >= 40
communityobjectNoCommunity signals: total_similar_reports, entity_signals
processing_time_msintegerYesTotal scan time in milliseconds

Error Codes

When a request fails, the response includes an error object with a machine-readable code.

HTTPCodeDescriptionRecovery
400INVALID_INPUTRequest validation failedCheck request body and fix errors
401UNAUTHORIZEDMissing or invalid API keyProvide a valid X-API-Key header
404NOT_FOUNDScan or resource not foundVerify the ID is correct
413PAYLOAD_TOO_LARGEImage exceeds 10 MBReduce image size
415UNSUPPORTED_MEDIA_TYPEImage format not supportedUse JPEG, PNG, WebP, or GIF
429RATE_LIMIT_EXCEEDEDPlan rate limit reachedWait and retry, or upgrade plan
500INTERNAL_ERRORUnexpected server errorRetry with exponential backoff

Example Error Response

429 Too Many Requests
{
  "ok": false,
  "data": null,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Limit: 10 requests per hour."
  },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}

Rate Limits

Rate limits are enforced per API key using a sliding window.

PlanScans / HourPrice
Free10$0
Premium100Coming soon

When you hit the rate limit, the API returns 429 Too Many Requests.

The response includes a Retry-After header indicating how many seconds to wait before retrying.

Need higher limits? Contact us for enterprise plans with custom rate limits.