e-Stamp — Create Order
esignCreate an electronic stamp-paper order. Returns an `order_id` you then poll with estamp-status-v1 for the stamped document. BILLING — read this before integrating. Two separate amounts are charged for one call: 1. A flat service fee per order (the price shown for this product). 2. The STAMP DUTY itself, which is passed through to the state at cost — the total of every `stampDutyAmount` in `series`. For a Rajasthan stamp (`stateCode: "RJ"`) the state levies a 30% surcharge on the duty, which is added automatically. The surcharge follows the STAMP, not your billing address: a Maharashtra-registered company stamping in Rajasthan pays it. So a Rajasthan order with 5000 duty is charged: service fee + 6500 duty. Make sure your wallet covers both, or the call returns 402 INSUFFICIENT_BALANCE before anything is created. `refId` must be unique per order (use your loan account number or similar) — a repeat is rejected, which makes retries safe. `articleId` comes from estamp-articles-v1 and must be valid for your `stateCode`.
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/estamp-create-v1/
The trailing slash is required. /v1/estamp-create-v1/ works; /v1/estamp-create-v1 returns 404 Not Found. This applies to every product.
| Field | Type | Required | Constraints |
|---|---|---|---|
| stateCode | string | required | Two-letter state code the stamp is issued under, e.g. "RJ". Drives both the valid articleIds and the 30% Rajasthan surcharge. |
| firstPartyName | string | required | First party to the instrument. |
| secondPartyName | string | required | Second party to the instrument. |
| stampDutyPaidBy | string | required | Which party bears the duty — normally the first party. |
| refId | string | required | Your unique reference (e.g. loan account no.). Must be unique per order — a repeat is rejected, so retries are safe. |
| series | object[] | required | One entry per stamp. stampDutyAmount is in RUPEES and is passed through to the state at cost. |
Code snippets
curl -X POST https://apisathi.in/gw/v1/estamp-create-v1/ \
-H "X-API-Key: $API_SATHI_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"stateCode":"RJ","firstPartyName":"Pravaha Infinity Private Limited","secondPartyName":"Rahul Verma","stampDutyPaidBy":"Pravaha Infinity Private Limited","refId":"LOAN-2026-000123","series":[{"stampDutyAmount":500,"stampType":"ESTAMP","articleId":3312,"purpose":"Loan agreement","considerationPrice":250000}]}'Response
| Field | Type | Required | Constraints |
|---|---|---|---|
| order_id | string | optional | Poll this with estamp-status-v1 to collect the stamped document. |
| message | string | optional | — |
Sample response
{
"order_id": "SPRAV000001",
"message": "Order created successfully."
}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 — e-Stamp — Create Order",
"version": "1.0.0",
"description": "Create an electronic stamp-paper order. Returns an `order_id` you then poll with estamp-status-v1 for the stamped document.\n\nBILLING — read this before integrating. Two separate amounts are charged for one call:\n1. A flat service fee per order (the price shown for this product).\n2. The STAMP DUTY itself, which is passed through to the state at cost — the total of every `stampDutyAmount` in `series`.\nFor a Rajasthan stamp (`stateCode: \"RJ\"`) the state levies a 30% surcharge on the duty, which is added automatically. The surcharge follows the STAMP, not your billing address: a Maharashtra-registered company stamping in Rajasthan pays it.\n\nSo a Rajasthan order with 5000 duty is charged: service fee + 6500 duty. Make sure your wallet covers both, or the call returns 402 INSUFFICIENT_BALANCE before anything is created.\n\n`refId` must be unique per order (use your loan account number or similar) — a repeat is rejected, which makes retries safe. `articleId` comes from estamp-articles-v1 and must be valid for your `stateCode`."
},
"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": {
"/estamp-create-v1": {
"post": {
"operationId": "estampCreateV1",
"tags": [
"esign"
],
"summary": "e-Stamp — Create Order",
"description": "Create an electronic stamp-paper order. Returns an `order_id` you then poll with estamp-status-v1 for the stamped document.\n\nBILLING — read this before integrating. Two separate amounts are charged for one call:\n1. A flat service fee per order (the price shown for this product).\n2. The STAMP DUTY itself, which is passed through to the state at cost — the total of every `stampDutyAmount` in `series`.\nFor a Rajasthan stamp (`stateCode: \"RJ\"`) the state levies a 30% surcharge on the duty, which is added automatically. The surcharge follows the STAMP, not your billing address: a Maharashtra-registered company stamping in Rajasthan pays it.\n\nSo a Rajasthan order with 5000 duty is charged: service fee + 6500 duty. Make sure your wallet covers both, or the call returns 402 INSUFFICIENT_BALANCE before anything is created.\n\n`refId` must be unique per order (use your loan account number or similar) — a repeat is rejected, which makes retries safe. `articleId` comes from estamp-articles-v1 and must be valid for your `stateCode`.",
"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": [
"stateCode",
"firstPartyName",
"secondPartyName",
"stampDutyPaidBy",
"refId",
"series"
],
"properties": {
"stateCode": {
"type": "string",
"description": "Two-letter state code the stamp is issued under, e.g. \"RJ\". Drives both the valid articleIds and the 30% Rajasthan surcharge."
},
"firstPartyName": {
"type": "string",
"description": "First party to the instrument."
},
"secondPartyName": {
"type": "string",
"description": "Second party to the instrument."
},
"stampDutyPaidBy": {
"type": "string",
"description": "Which party bears the duty — normally the first party."
},
"refId": {
"type": "string",
"description": "Your unique reference (e.g. loan account no.). Must be unique per order — a repeat is rejected, so retries are safe."
},
"series": {
"type": "array",
"description": "One entry per stamp. stampDutyAmount is in RUPEES and is passed through to the state at cost.",
"items": {
"type": "object",
"required": [
"stampDutyAmount",
"stampType",
"articleId",
"purpose",
"considerationPrice"
],
"properties": {
"stampDutyAmount": {
"type": "number",
"description": "Duty in rupees for this stamp."
},
"stampType": {
"type": "string",
"enum": [
"ESTAMP"
]
},
"articleId": {
"type": "number",
"description": "From estamp-articles-v1, valid for your stateCode."
},
"purpose": {
"type": "string",
"minLength": 1,
"maxLength": 150
},
"considerationPrice": {
"type": "number",
"description": "Value of the underlying transaction, in rupees."
}
}
}
}
}
},
"example": {
"stateCode": "RJ",
"firstPartyName": "Pravaha Infinity Private Limited",
"secondPartyName": "Rahul Verma",
"stampDutyPaidBy": "Pravaha Infinity Private Limited",
"refId": "LOAN-2026-000123",
"series": [
{
"stampDutyAmount": 500,
"stampType": "ESTAMP",
"articleId": 3312,
"purpose": "Loan agreement",
"considerationPrice": 250000
}
]
}
}
}
},
"responses": {
"200": {
"description": "Successful, normalized response.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "Poll this with estamp-status-v1 to collect the stamped document."
},
"message": {
"type": "string"
}
},
"additionalProperties": true
},
"example": {
"order_id": "SPRAV000001",
"message": "Order created successfully."
}
}
}
},
"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"
}
}
}
}
}
}
}
}
}
}
}
}
}