e-Sign — Request Status & Signed Document
esignFetch the current status of a signing request created with esign-create-v1, and once signed, the signed PDF plus the signer verification details. PASS THE PER-SIGNER `request_id`, NOT THE GROUP ID. esign-create-v1 returns one `request_id` per signer inside `requests[]`, plus a single `group_id` for the envelope. This endpoint takes the per-signer id; the group id returns 404. For a two-party document you poll twice, once per signer. THE SIGNED URL EXPIRES IN 24 HOURS. `signed_url` is a time-limited link, not permanent storage. Download the PDF and store it in your own system as soon as `signed` is true — do not persist the URL and expect it to work tomorrow. EVIDENCE ARTEFACT: for an Aadhaar signature the response carries `verified_name` (the name held against the Aadhaar record), `name_match_score` (0-1, how closely it matches the name you supplied) and `certifying_authority` (the licensed CA that issued the signature). Together with the signed PDF these are what make the signature defensible under §3A of the IT Act. A low `name_match_score` on an otherwise SUCCESSful signature is worth reviewing before you rely on the document. Polling: signing happens after esign-create-v1 returns, so poll this until `signed` is true or the request expires (`expires_at`, 7 days by default). Priced at a nominal rate so polling is cheap, but poll sensibly — every few seconds, not in a tight loop.
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/esign-status-v1/
The trailing slash is required. /v1/esign-status-v1/ works; /v1/esign-status-v1 returns 404 Not Found. This applies to every product.
| Field | Type | Required | Constraints |
|---|---|---|---|
| request_id | string | required | The per-signer request_id from esign-create-v1 `requests[].request_id`. NOT the group_id. |
Code snippets
curl -X POST https://apisathi.in/gw/v1/esign-status-v1/ \
-H "X-API-Key: $API_SATHI_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"request_id":"6a79b62d04efdfca72af83b8"}'Response
| Field | Type | Required | Constraints |
|---|---|---|---|
| status | string | optional | Upstream transaction state, e.g. GATEWAY_OPENED (link opened, not yet signed), PAUSED (waiting on an earlier signer in the order), SUCCESS (signed). |
| signed | boolean | optional | True only when the signature is complete. |
| signed_url | string | optional | Time-limited link to the signed PDF. EXPIRES IN 24 HOURS — download it. |
| signed_at | string | optional | — |
| signer_name | string | optional | The name you supplied. |
| verified_name | string | optional | The name held against the Aadhaar record. |
| name_match_score | number | optional | 0-1 similarity between signer_name and verified_name. |
| certifying_authority | string | optional | The licensed CA that issued the signature. |
| expires_at | string | optional | When the signing request lapses. |
Sample response
{
"status": "SUCCESS",
"signed": true,
"signed_url": "https://storage.example.com/…_signed?…expires…",
"signed_at": "2026-08-10T11:33:27.851Z",
"signer_name": "Rahul Verma",
"verified_name": "Rahul K Verma",
"name_match_score": 0.93,
"certifying_authority": "EMUDHRA",
"expires_at": "2026-08-17T11:29:49.065Z"
}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. |
| NOT_FOUND | 404 | No signing request exists for that request_id. Definitive — check you sent the per-signer request_id and not the group_id. Do not retry the same value. |
OpenAPI 3.1
Generated from this product's request/response JSON Schemas.
{
"openapi": "3.1.0",
"info": {
"title": "API Sathi — e-Sign — Request Status & Signed Document",
"version": "1.0.0",
"description": "Fetch the current status of a signing request created with esign-create-v1, and once signed, the signed PDF plus the signer verification details.\n\nPASS THE PER-SIGNER `request_id`, NOT THE GROUP ID. esign-create-v1 returns one `request_id` per signer inside `requests[]`, plus a single `group_id` for the envelope. This endpoint takes the per-signer id; the group id returns 404. For a two-party document you poll twice, once per signer.\n\nTHE SIGNED URL EXPIRES IN 24 HOURS. `signed_url` is a time-limited link, not permanent storage. Download the PDF and store it in your own system as soon as `signed` is true — do not persist the URL and expect it to work tomorrow.\n\nEVIDENCE ARTEFACT: for an Aadhaar signature the response carries `verified_name` (the name held against the Aadhaar record), `name_match_score` (0-1, how closely it matches the name you supplied) and `certifying_authority` (the licensed CA that issued the signature). Together with the signed PDF these are what make the signature defensible under §3A of the IT Act. A low `name_match_score` on an otherwise SUCCESSful signature is worth reviewing before you rely on the document.\n\nPolling: signing happens after esign-create-v1 returns, so poll this until `signed` is true or the request expires (`expires_at`, 7 days by default). Priced at a nominal rate so polling is cheap, but poll sensibly — every few seconds, not in a tight loop."
},
"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": {
"/esign-status-v1": {
"post": {
"operationId": "esignStatusV1",
"tags": [
"esign"
],
"summary": "e-Sign — Request Status & Signed Document",
"description": "Fetch the current status of a signing request created with esign-create-v1, and once signed, the signed PDF plus the signer verification details.\n\nPASS THE PER-SIGNER `request_id`, NOT THE GROUP ID. esign-create-v1 returns one `request_id` per signer inside `requests[]`, plus a single `group_id` for the envelope. This endpoint takes the per-signer id; the group id returns 404. For a two-party document you poll twice, once per signer.\n\nTHE SIGNED URL EXPIRES IN 24 HOURS. `signed_url` is a time-limited link, not permanent storage. Download the PDF and store it in your own system as soon as `signed` is true — do not persist the URL and expect it to work tomorrow.\n\nEVIDENCE ARTEFACT: for an Aadhaar signature the response carries `verified_name` (the name held against the Aadhaar record), `name_match_score` (0-1, how closely it matches the name you supplied) and `certifying_authority` (the licensed CA that issued the signature). Together with the signed PDF these are what make the signature defensible under §3A of the IT Act. A low `name_match_score` on an otherwise SUCCESSful signature is worth reviewing before you rely on the document.\n\nPolling: signing happens after esign-create-v1 returns, so poll this until `signed` is true or the request expires (`expires_at`, 7 days by default). Priced at a nominal rate so polling is cheap, but poll sensibly — every few seconds, not in a tight loop.",
"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": [
"request_id"
],
"properties": {
"request_id": {
"type": "string",
"description": "The per-signer request_id from esign-create-v1 `requests[].request_id`. NOT the group_id."
}
},
"additionalProperties": false
},
"example": {
"request_id": "6a79b62d04efdfca72af83b8"
}
}
}
},
"responses": {
"200": {
"description": "Successful, normalized response.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "Upstream transaction state, e.g. GATEWAY_OPENED (link opened, not yet signed), PAUSED (waiting on an earlier signer in the order), SUCCESS (signed)."
},
"signed": {
"type": "boolean",
"description": "True only when the signature is complete."
},
"signed_url": {
"type": "string",
"description": "Time-limited link to the signed PDF. EXPIRES IN 24 HOURS — download it."
},
"signed_at": {
"type": "string"
},
"signer_name": {
"type": "string",
"description": "The name you supplied."
},
"verified_name": {
"type": "string",
"description": "The name held against the Aadhaar record."
},
"name_match_score": {
"type": "number",
"description": "0-1 similarity between signer_name and verified_name."
},
"certifying_authority": {
"type": "string",
"description": "The licensed CA that issued the signature."
},
"expires_at": {
"type": "string",
"description": "When the signing request lapses."
}
},
"additionalProperties": true
},
"example": {
"status": "SUCCESS",
"signed": true,
"signed_url": "https://storage.example.com/…_signed?…expires…",
"signed_at": "2026-08-10T11:33:27.851Z",
"signer_name": "Rahul Verma",
"verified_name": "Rahul K Verma",
"name_match_score": 0.93,
"certifying_authority": "EMUDHRA",
"expires_at": "2026-08-17T11:29:49.065Z"
}
}
}
},
"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"
}
}
}
}
}
}
}
},
"404": {
"description": "No signing request exists for that request_id. Definitive — check you sent the per-signer request_id and not the group_id. Do not retry the same value.",
"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"
}
}
}
}
}
}
}
}
}
}
}
}
}