CIBIL Credit Report
creditConsent-based CIBIL (TransUnion) credit report and score for an individual, looked up by PAN + mobile. Returns the bureau score plus the structured credit report (accounts, enquiries). CONSENT OTP REQUIRED. Before pulling, capture the borrower’s consent via OTP: send an OTP to their mobile (see the Credit Consent OTP SMS API), have them confirm it, then pass that same OTP in the `otp` field as proof of consent. All six fields are mandatory: `mobile` (the number linked to the person’s credit record), `pan`, `name`, `gender` (`male`/`female`), `consent` (must be `"Y"`), and `otp`. The OTP must be UNIQUE per request — reusing an OTP for the same mobile is rejected upstream as an invalid OTP (422 INVALID_INPUT), which is the most common cause of failures on this endpoint. Billed on SUCCESS only. (A downloadable-PDF variant is available separately as CIBIL Credit Report (PDF).) TIMING: bureau pulls are slow — typical 4-9s, p95 ~8.5s. Our upstream timeout is 15s, so set your client timeout to at least 20s. A client timeout below ~10s will surface as a failure on your side for calls we complete successfully. Timeouts are never charged.
Authentication
Pass your key in the X-API-Key header. Use a test_ key against the sandbox and a live_ key in production. Send an optional Idempotency-Key header to safely retry — the same key returns the same response for 24h.
Request
Endpoint: POST https://apisathi.in/gw/v1/credit-report-cibil-v1/
The trailing slash is required. /v1/credit-report-cibil-v1/ works; /v1/credit-report-cibil-v1 returns 404 Not Found. This applies to every product.
| Field | Type | Required | Constraints |
|---|---|---|---|
| mobile | string | required | pattern: ^[6-9][0-9]{9}$ · The mobile number the person has REGISTERED with the credit bureau — not just any number they own. If it is not the credit-linked mobile, the call returns 422 "invalid_mobile_number" with no report (and no charge). This is the most common cause of a failed pull. |
| pan | string | required | pattern: ^[A-Z]{5}[0-9]{4}[A-Z]$ |
| name | string | required | Full name of the individual as per PAN |
| gender | string | required | Required by the bureau — the individual’s gender |
| consent | string | required | Must be "Y" — explicit end-user consent for the bureau pull |
| otp | string | required | pattern: ^[0-9]{4,6}$ · Borrower consent OTP — captured + verified with them at your end (e.g. via the Credit Consent OTP SMS API). Proof that the borrower authorised the credit pull. |
Code snippets
curl -X POST https://apisathi.in/gw/v1/credit-report-cibil-v1/ \
-H "X-API-Key: $API_SATHI_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"mobile":"9988776655","pan":"EKRPR1234F","name":"Vishal Rathore","gender":"male","consent":"Y","otp":"534216"}'Response
| Field | Type | Required | Constraints |
|---|---|---|---|
| verified | boolean | optional | — |
| credit_score | string | optional | CIBIL score, e.g. "744" |
| name | string | optional | — |
| mobile | string | optional | — |
| pan | string | optional | — |
| gender | string | optional | — |
| string | optional | Email on the bureau record, if any (often null) | |
| credit_report | object | optional | Full structured report — score, accounts/tradelines, and enquiries. |
| credit_report_link | string | optional | Signed URL to the full PDF credit report (valid for a limited time) |
| client_id | string | optional | — |
Sample response
{
"verified": true,
"credit_score": "744",
"name": "VISHAL RATHORE",
"mobile": "9988776655",
"pan": "EKRPR1234F",
"gender": "male",
"email": null,
"credit_report": {
"score": {
"score": "744",
"scoreName": "CIBILTUSCORE"
},
"accounts": [
"… structured account list …"
],
"enquiries": [
"… structured enquiry list …"
]
},
"credit_report_link": "https://…/credit_report_cibil_xxx.pdf",
"client_id": "credit_report_cibil_xxx"
}Reading a 400
A schema rejection returns INVALID_REQUEST with a details array naming the exact field. Read it before guessing — it gives you the JSON path and what was wrong with it.
{
"error": {
"code": "INVALID_REQUEST",
"message": "Request body failed schema validation",
"details": [
{ "path": "/callback_url",
"message": "unexpected property 'callback_url' — this endpoint does not accept unknown fields" }
]
}
}Most endpoints reject unknown top-level fields outright, so an extra key you added for your own bookkeeping will fail the call. Enum errors list the accepted values, and a missing required field is named with its full path.
Error codes
| Code | HTTP | When |
|---|---|---|
| INVALID_INPUT | 422 | The request was rejected as invalid — either it failed OUR schema validation (malformed input; not charged), or the upstream source rejected the value you sent. NOTE: an identifier that is well-formed but simply has NO RECORD is no longer an error — it returns 200 with `verified: false` and is charged (see the result-code table below). FIX the input before retrying; retrying the same value will fail again. |
| INVALID_API_KEY | 401 | Missing, malformed, or revoked X-API-Key. |
| OUT_OF_SCOPE | 403 | API key is not scoped for this product. |
| INSUFFICIENT_BALANCE | 402 | Wallet balance is below the per-call sale price. Recharge and retry. |
| RATE_LIMITED | 429 | Per-key RPS or RPM limit exceeded. Back off and retry after the Retry-After header. |
| PRODUCT_DEPRECATED | 410 | This API has been retired and is no longer available. Stop calling it — it will not return. Check the catalog for the current equivalent. |
| ROUTER_NO_VENDOR | 503 | No healthy vendor is currently available for this product. Transient — safe to retry after a short backoff. Not charged. |
| VENDOR_AUTH_FAILED | 502 | Upstream vendor rejected our credentials (our config issue). Not charged. |
| VENDOR_ERROR | 502 | A genuine transient upstream error (the source was briefly unavailable). Safe to RETRY after a short backoff. Not charged. NOTE: this is NOT for bad input — invalid values return 422 INVALID_INPUT, not 502. |
| TIMEOUT | 504 | Upstream vendor did not respond within the SLA window. Safe to retry after a short backoff. Not charged. |
OpenAPI 3.1
Generated from this product's request/response JSON Schemas.
{
"openapi": "3.1.0",
"info": {
"title": "API Sathi — CIBIL Credit Report",
"version": "1.0.0",
"description": "Consent-based CIBIL (TransUnion) credit report and score for an individual, looked up by PAN + mobile. Returns the bureau score plus the structured credit report (accounts, enquiries).\n\nCONSENT OTP REQUIRED. Before pulling, capture the borrower’s consent via OTP: send an OTP to their mobile (see the Credit Consent OTP SMS API), have them confirm it, then pass that same OTP in the `otp` field as proof of consent. All six fields are mandatory: `mobile` (the number linked to the person’s credit record), `pan`, `name`, `gender` (`male`/`female`), `consent` (must be `\"Y\"`), and `otp`. The OTP must be UNIQUE per request — reusing an OTP for the same mobile is rejected upstream as an invalid OTP (422 INVALID_INPUT), which is the most common cause of failures on this endpoint. Billed on SUCCESS only. (A downloadable-PDF variant is available separately as CIBIL Credit Report (PDF).) \n\nTIMING: bureau pulls are slow — typical 4-9s, p95 ~8.5s. Our upstream timeout is 15s, so set your client timeout to at least 20s. A client timeout below ~10s will surface as a failure on your side for calls we complete successfully. Timeouts are never charged."
},
"servers": [
{
"url": "https://apisathi.in/gw/v1"
}
],
"components": {
"securitySchemes": {
"ApiKeyAuth": {
"type": "apiKey",
"in": "header",
"name": "X-API-Key",
"description": "Your live or test key, e.g. `live_xxxxxxxxxxxx`."
}
}
},
"paths": {
"/credit-report-cibil-v1": {
"post": {
"operationId": "creditReportCibilV1",
"tags": [
"credit"
],
"summary": "CIBIL Credit Report",
"description": "Consent-based CIBIL (TransUnion) credit report and score for an individual, looked up by PAN + mobile. Returns the bureau score plus the structured credit report (accounts, enquiries).\n\nCONSENT OTP REQUIRED. Before pulling, capture the borrower’s consent via OTP: send an OTP to their mobile (see the Credit Consent OTP SMS API), have them confirm it, then pass that same OTP in the `otp` field as proof of consent. All six fields are mandatory: `mobile` (the number linked to the person’s credit record), `pan`, `name`, `gender` (`male`/`female`), `consent` (must be `\"Y\"`), and `otp`. The OTP must be UNIQUE per request — reusing an OTP for the same mobile is rejected upstream as an invalid OTP (422 INVALID_INPUT), which is the most common cause of failures on this endpoint. Billed on SUCCESS only. (A downloadable-PDF variant is available separately as CIBIL Credit Report (PDF).) \n\nTIMING: bureau pulls are slow — typical 4-9s, p95 ~8.5s. Our upstream timeout is 15s, so set your client timeout to at least 20s. A client timeout below ~10s will surface as a failure on your side for calls we complete successfully. Timeouts are never charged.",
"security": [
{
"ApiKeyAuth": []
}
],
"parameters": [
{
"name": "Idempotency-Key",
"in": "header",
"required": false,
"schema": {
"type": "string"
},
"description": "Optional. Same key returns the same response for 24h."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"mobile",
"pan",
"name",
"gender",
"consent",
"otp"
],
"properties": {
"mobile": {
"type": "string",
"description": "The mobile number the person has REGISTERED with the credit bureau — not just any number they own. If it is not the credit-linked mobile, the call returns 422 \"invalid_mobile_number\" with no report (and no charge). This is the most common cause of a failed pull.",
"pattern": "^[6-9][0-9]{9}$"
},
"pan": {
"type": "string",
"pattern": "^[A-Z]{5}[0-9]{4}[A-Z]$"
},
"name": {
"type": "string",
"description": "Full name of the individual as per PAN"
},
"gender": {
"type": "string",
"enum": [
"male",
"female"
],
"description": "Required by the bureau — the individual’s gender"
},
"consent": {
"type": "string",
"enum": [
"Y"
],
"description": "Must be \"Y\" — explicit end-user consent for the bureau pull"
},
"otp": {
"type": "string",
"pattern": "^[0-9]{4,6}$",
"description": "Borrower consent OTP — captured + verified with them at your end (e.g. via the Credit Consent OTP SMS API). Proof that the borrower authorised the credit pull."
}
}
},
"example": {
"mobile": "9988776655",
"pan": "EKRPR1234F",
"name": "Vishal Rathore",
"gender": "male",
"consent": "Y",
"otp": "534216"
}
}
}
},
"responses": {
"200": {
"description": "Successful, normalized response.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"verified": {
"type": "boolean"
},
"credit_score": {
"type": "string",
"description": "CIBIL score, e.g. \"744\""
},
"name": {
"type": "string"
},
"mobile": {
"type": "string"
},
"pan": {
"type": "string"
},
"gender": {
"type": "string"
},
"email": {
"type": "string",
"description": "Email on the bureau record, if any (often null)"
},
"credit_report": {
"type": "object",
"additionalProperties": true,
"description": "Full structured report — score, accounts/tradelines, and enquiries."
},
"credit_report_link": {
"type": "string",
"description": "Signed URL to the full PDF credit report (valid for a limited time)"
},
"client_id": {
"type": "string"
}
}
},
"example": {
"verified": true,
"credit_score": "744",
"name": "VISHAL RATHORE",
"mobile": "9988776655",
"pan": "EKRPR1234F",
"gender": "male",
"email": null,
"credit_report": {
"score": {
"score": "744",
"scoreName": "CIBILTUSCORE"
},
"accounts": [
"… structured account list …"
],
"enquiries": [
"… structured enquiry list …"
]
},
"credit_report_link": "https://…/credit_report_cibil_xxx.pdf",
"client_id": "credit_report_cibil_xxx"
}
}
}
},
"401": {
"description": "Missing, malformed, or revoked X-API-Key.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
},
"402": {
"description": "Wallet balance is below the per-call sale price. Recharge and retry.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
},
"403": {
"description": "API key is not scoped for this product.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
},
"410": {
"description": "This API has been retired and is no longer available. Stop calling it — it will not return. Check the catalog for the current equivalent.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
},
"422": {
"description": "The request was rejected as invalid — either it failed OUR schema validation (malformed input; not charged), or the upstream source rejected the value you sent. NOTE: an identifier that is well-formed but simply has NO RECORD is no longer an error — it returns 200 with `verified: false` and is charged (see the result-code table below). FIX the input before retrying; retrying the same value will fail again.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
},
"429": {
"description": "Per-key RPS or RPM limit exceeded. Back off and retry after the Retry-After header.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
},
"502": {
"description": "Upstream vendor rejected our credentials (our config issue). Not charged.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
},
"503": {
"description": "No healthy vendor is currently available for this product. Transient — safe to retry after a short backoff. Not charged.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
},
"504": {
"description": "Upstream vendor did not respond within the SLA window. Safe to retry after a short backoff. Not charged.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"call_id": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
}