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.
Create an account
Sign up with email or Google. Free — no credit card required.
Get your API key
Go to your Profile and create an API key. Keys start with svd_ and are shown only once.
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.
X-API-Key: svd_4a7b3c2d9e1f5a6b8c0d3e4f5a6b7c8dKey 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | Text to scan (1–10,000 characters) |
| content_type | enum | No | "text" (default) or "image" |
| channel | enum | No | "sms" | "whatsapp" | "email" | "social_dm" | "website" | "other" |
| category | enum | No | "scam_check" (default) | "job_offer" | "rental_lease" | "investment" | "contract" | "auto" |
| locale | string | No | Language 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
{
"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.
multipart/form-data — not JSON.Request Fields
| Parameter | Type | Required | Description |
|---|---|---|---|
| file | file | Yes | Image file: JPEG, PNG, WebP, or GIF (max 10 MB) |
| channel | enum | No | "sms" | "whatsapp" | "email" | "social_dm" | "website" | "other" |
| category | enum | No | "scam_check" (default) | "job_offer" | "rental_lease" | "investment" | "contract" | "auto" |
| locale | string | No | Language 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| scan_id | UUID | Yes | The 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)
| # | Step | Description |
|---|---|---|
| 1 | dedup_check | Check if this content was already scanned |
| 2 | entity_extraction | Extract URLs, phones, emails, UPI IDs, crypto addresses |
| 3 | rule_engine | Run pattern-matching rules (14 signals) |
| 4 | threat_intel | Query 6+ threat databases in parallel |
| 5 | llm_classification | AI-powered scam classification |
| 6 | score_merge | Merge all evidence into final risk score |
| 7 | actions | Generate recommended actions |
| 8 | persist | Save results to database |
| 9 | scam_card | Generate 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 resultevent: error— Emitted if the scan failsExample
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| scan_id | UUID | Yes | ID of the scan to report on |
| feedback_type | enum | Yes | "confirmed_scam" | "false_positive" | "false_negative" | "helpful" | "not_helpful" |
| comment | string | No | Additional context (max 2,000 characters) |
| contact_email | string | No | Email 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
{
"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
| Level | Score Range | Meaning |
|---|---|---|
| critical | 80–100 | Almost certainly a scam — do not engage |
| high | 60–79 | Strong scam indicators detected |
| medium | 40–59 | Some suspicious patterns — proceed with caution |
| low | 20–39 | Minor signals — likely safe but verify |
| none | 0–19 | No scam indicators found |
Key Response Fields
| Parameter | Type | Required | Description |
|---|---|---|---|
| scan_id | UUID | Yes | Unique identifier for this scan |
| risk_score | integer | Yes | 0–100 risk score |
| risk_level | string | Yes | critical | high | medium | low | none |
| scam_type | string | No | Detected scam category (e.g. phishing, upi_fraud, lottery_prize) |
| explanation | string | Yes | AI-generated explanation of the risk assessment |
| evidence | array | Yes | List of specific threat signals found (source, detail, confidence) |
| actions | array | Yes | Recommended actions for the user |
| entities | object | Yes | Extracted entities: urls, phones, emails, crypto_addresses, upi_ids |
| scam_card | object | No | Shareable scam card (card_id, card_url, image_url) — generated when risk >= 40 |
| community | object | No | Community signals: total_similar_reports, entity_signals |
| processing_time_ms | integer | Yes | Total scan time in milliseconds |
Error Codes
When a request fails, the response includes an error object with a machine-readable code.
| HTTP | Code | Description | Recovery |
|---|---|---|---|
| 400 | INVALID_INPUT | Request validation failed | Check request body and fix errors |
| 401 | UNAUTHORIZED | Missing or invalid API key | Provide a valid X-API-Key header |
| 404 | NOT_FOUND | Scan or resource not found | Verify the ID is correct |
| 413 | PAYLOAD_TOO_LARGE | Image exceeds 10 MB | Reduce image size |
| 415 | UNSUPPORTED_MEDIA_TYPE | Image format not supported | Use JPEG, PNG, WebP, or GIF |
| 429 | RATE_LIMIT_EXCEEDED | Plan rate limit reached | Wait and retry, or upgrade plan |
| 500 | INTERNAL_ERROR | Unexpected server error | Retry with exponential backoff |
Example Error Response
{
"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.
| Plan | Scans / Hour | Price |
|---|---|---|
| Free | 10 | $0 |
| Premium | 100 | Coming 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.
Need help?
For technical assistance, API integration support, or bug reports, contact us at support@savdhaan.in