SMS_Analysis_V1 — SMS Financial Intelligence API
SMS_Analysis_V1 v1 live
Download as Markdownthe full page as a single .md file — for offline reading or as context for an AI assistantAuthentication
Every request must carry your API key in the X-API-Key header.
Your key is issued to you separately by ops and is never shown in this document.
X-API-Key: <your-key>Base URL
All endpoints are served through the gateway:
https://api.pehchaantech.comEndpoints
/sms/v1/ingest
| URL | https://api.pehchaantech.com/sms/v1/ingest |
|---|---|
| Timeout | 10000 ms |
| Rate limit | 60 req/min · 100000 req/day |
/sms/v1/report
| URL | https://api.pehchaantech.com/sms/v1/report |
|---|---|
| Timeout | 5000 ms |
| Rate limit | 60 req/min · 100000 req/day |
/sms/v1/summary
| URL | https://api.pehchaantech.com/sms/v1/summary |
|---|---|
| Timeout | 5000 ms |
| Rate limit | 60 req/min · 100000 req/day |
Overview
Turn a consented SMS inbox into a structured financial-identity profile: income, obligations, credit-seeking behaviour, cash-flow health and 25 more families of derived signal.
Analysis is ASYNCHRONOUS and takes three calls. POST /sms/v1/ingest with the raw messages and you immediately receive an sms_id — submission never waits on analysis, so uploading 50,000 messages is as fast as uploading 50. Then redeem that id at POST /sms/v1/summary (the decision-grade headline, ~2 KB) or POST /sms/v1/report (all 29 families with their underlying evidence, plus cross-family correlations and our own watchlist/registry data joined in). Poll the endpoint you actually want: while analysis is running it returns 202 with status "processing" and a Retry-After header — there is no separate status endpoint.
Two things to internalise before you integrate. First, null means NOT DETECTED, not zero — a null monthly income means we could not establish a salary, so gate your rules on the coverage map rather than on null checks. Second, the sms_id is a CREDENTIAL: anyone holding it can redeem the analysis, so keep it server-side and never put it in a browser URL or a client-side log. It expires after 7 days.
Request example
{
"messages": [
{
"body": "Rs.85,000 credited to a/c XX1234 by SALARY ACME PVT LTD",
"sender": "VK-HDFCBK",
"sentAtMs": 1751360400000
},
{
"body": "Rs 15000 debited via NACH EMI to PNB HOUSING FINANCE",
"sender": "AX-HDFCBK",
"sentAt": "2025-07-05T06:00:00Z"
}
]
}Response example
{
"sms_id": "sms_9dQ2mF7xK1pR4vT8zL0bN3sW",
"status": "processing",
"success": true,
"expires_at": "2026-07-28T11:04:12Z",
"description": "Inbox accepted and queued for analysis",
"messageCount": 4820
}Fields
| Field | Description |
|---|---|
messages | Required on /ingest. 1–50,000 items, 10 MB max. This is the ENTIRE request body — you do not send a reference number or idempotency key; the sms_id we return identifies the whole lifecycle. |
messages[].body | Required. The raw SMS text, 1–2000 characters. |
messages[].sender | Optional sender header, e.g. VK-HDFCBK. Used for bank and app attribution — supplying it materially improves detection. |
messages[].sentAtMs / sentAt | One is required. sentAtMs is epoch milliseconds and is preferred (no parsing); sentAt accepts any ISO-8601 timestamp. Rows with an empty body OR no parseable timestamp are silently dropped before analysis — you will see this as meta.analysed being lower than meta.messageCount. If those differ a lot, check your timestamp format. |
sms_id | Required on /summary and /report. Returned by /ingest in the body and the X-Sms-Id header. Treat it as a bearer credential; it is sent in the request BODY so it never lands in access logs or Referer headers. Valid for 7 days. |
result.coverage | Summary only. Per-family populated | empty | degraded. READ THIS FIRST: null means "not detected", not zero, and coverage is how you tell "we found no salary signal" apart from "the salary is zero". |
result (report) | All 29 families verbatim, including the evidence arrays behind every summary count. bureauChecks[].checks[].evidence carries up to 140 characters of the original SMS for each detected credit enquiry — the only place raw message text is returned. |
correlations | Report only. Cross-family analysis no single detector produces: affordability (total fixed commitment incl. subscriptions, utilities and rent), employerAgreement, creditHunger, stressComposite, lifestyleVsIncome, geoConsistency, wealthCorroboration, confidenceMap. Each carries {value, inputs, confidence}. |
referenceData | Report only. Our reference data joined to theirs: darkPatterns (predatory subscriptions they are actually paying for, with the reason each is flagged and the parent entities that appear on NACH lines), lenderExposure, appTaxonomy, and datasetVersions for reconciliation. |
Errors
| Code | Meaning |
|---|---|
processing (HTTP 202) | On /ingest: accepted and queued. On /summary or /report: analysis is still running — retry after Retry-After (1 s). Typical end-to-end is under a second, so the first or second poll usually succeeds. |
completed (HTTP 200) | Analysis ready — consume result. |
no_data (HTTP 200) | Processed, but nothing in the inbox was analysable. Check your timestamp format and meta.analysed. Do not retry the read. |
failed (HTTP 200) | Analysis failed permanently. Deliberately a 200, not a 5xx: the read itself worked, so retrying it will never help — submit the inbox again. |
not_found (HTTP 404) | Unknown sms_id. Check the value you sent. |
expired (HTTP 410) | The sms_id existed but passed its 7-day retention window. Distinct from 404 on purpose. Submit the inbox again. |
422 | Validation failed — empty messages array, over 50,000 messages, a body longer than 2000 chars, or a malformed sms_id. |
503 (ingest) | The ingest queue is at capacity. Retry after Retry-After (2 s) — this is backpressure, not breakage. |
401 / 403 | Missing or invalid API key, or the key is not granted this API. Note a uat key on a prod route returns 404, not 403. |
429 | Rate limited — respect the Retry-After header. |
502 / 504 | Storage or gateway problem — retry with exponential backoff. |
Changelog
- 2026-07-21 Initial release: asynchronous three-call flow (ingest → summary / report), 29-family profile, cross-family correlations, dark-pattern and lender reference data, 7-day sms_id retention.