REST API Quick Reference¶
Quick reference for the eSign REST API used by JavaScript SDK and Android SDK.
Base URL: https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign
Port: 8081 (esign-api)
Authentication¶
The signing endpoint (/api/java/v1/esign) and secure lookup (/api/java/v1/esign/transaction) require authentication in the request body:
Endpoints Summary¶
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/java/v1/esign/upload-pdf |
Upload a PDF file and retrieve its Base64 value |
POST |
/api/java/v1/esign |
Initiate the signing process |
POST |
/api/java/v1/esign/json |
Explicit JSON signing endpoint |
POST |
/api/java/v1/esign/xml |
Explicit XML signing endpoint |
POST |
/api/java/v1/esign/transaction |
Secure lookup by reference/transactionid/internaltxn |
GET |
/api/java/v1/esign/signed/{reference} |
Signed PDF as Base64 + pdfurl (token or auth required) |
GET |
/api/java/v1/esign/signed/{reference}/json |
Signed PDF as Base64 (JSON) |
GET |
/api/java/v1/esign/signed/{reference}/xml |
Signed PDF as Base64 (XML) |
GET |
/api/java/v1/esign/document/{reference} |
Download signed PDF (token or auth required) |
GET |
/api/java/v1/esign/health |
Health check |
1. Upload PDF and Get Base64 (Utility Endpoint)¶
POST /api/java/v1/esign/upload-pdf¶
A utility endpoint that accepts a PDF file via form-data and returns its Base64 encoding.
This is a utility endpoint
This endpoint does NOT initiate signing. It only converts a PDF file to Base64 format. To sign a document, use the /api/java/v1/esign endpoint.
Request¶
| Field | Type | Description |
|---|---|---|
file |
File (form-data) | PDF file to upload |
Success Response¶
{
"success": true,
"filename": "FDE68A84BE466467344F7D97B6907563D759031C_signed.pdf",
"size": 133704,
"pdf64": "JVBERi0xLjQK..."
}
Response Fields¶
| Field | Type | Description |
|---|---|---|
success |
Boolean | true if upload succeeded |
filename |
String | Generated filename |
size |
Number | File size in bytes |
pdf64 |
String | Base64 encoded PDF content |
2. Sign PDF (Main Signing Endpoint)¶
POST /api/java/v1/esign¶
Initiates the signing process. This is the main endpoint for document signing.
{
"auth": {
"command": "esign",
"token": "YOUR_TOKEN",
"key": "YOUR_KEY"
},
"parameter": {
"uploadpdf": {
"pdf64": "BASE64_ENCODED_PDF",
"title": "Document Title",
"mode": "online-aadhaar-otp",
"txn": "YOUR_TRANSACTION_ID",
"signername": "Signer Name",
"callbackurl": "https://your-server.com/callback",
"option": {
"cood": "350,50,550,120",
"pagenum": "1",
"reason": "Digital Signature",
"location": "India",
"greenticked": "y",
"dateformat": "dd-MMM-yyyy hh:mm a",
"lockpdf": "n"
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<request>
<auth>
<command>esign</command>
<token>YOUR_TOKEN</token>
<key>YOUR_KEY</key>
</auth>
<parameter>
<uploadpdf>
<pdf64>BASE64_ENCODED_PDF</pdf64>
<title>Document Title</title>
<mode>online-aadhaar-otp</mode>
<txn>YOUR_TRANSACTION_ID</txn>
<signername>Signer Name</signername>
<callbackurl>https://your-server.com/callback</callbackurl>
<option>
<cood>350,50,550,120</cood>
<pagenum>1</pagenum>
<reason>Digital Signature</reason>
<location>India</location>
<greenticked>y</greenticked>
<dateformat>dd-MMM-yyyy hh:mm a</dateformat>
<lockpdf>n</lockpdf>
</option>
</uploadpdf>
</parameter>
</request>
curl -X POST "https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign" \
-H "Content-Type: application/json" \
-d '{
"auth": {
"command": "esign",
"token": "YOUR_TOKEN",
"key": "YOUR_KEY"
},
"parameter": {
"uploadpdf": {
"pdf64": "JVBERi0xLjQK...",
"title": "Contract",
"mode": "online-aadhaar-otp",
"txn": "TXN123456",
"signername": "John Doe"
}
}
}'
curl -X POST "https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign" \
-H "Content-Type: application/xml" \
-d '<?xml version="1.0" encoding="UTF-8"?>
<request>
<auth>
<command>esign</command>
<token>YOUR_TOKEN</token>
<key>YOUR_KEY</key>
</auth>
<parameter>
<uploadpdf>
<pdf64>JVBERi0xLjQK...</pdf64>
<title>Contract</title>
<mode>online-aadhaar-otp</mode>
<txn>TXN123456</txn>
<signername>John Doe</signername>
</uploadpdf>
</parameter>
</request>'
Request Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
pdf64 |
String | Yes | Base64 encoded PDF (get from /upload-pdf or encode yourself) |
title |
String | Yes | Document title (max 50 characters) |
mode |
String | Yes | Authentication mode (see Authentication Modes) |
txn |
String | Yes | Unique transaction ID |
signername |
String | Yes | Name of the signer |
callbackurl |
String | No | URL for callback after signing |
option |
Object | No | Signing options (see Signing Options) |
Success Response¶
{
"success": "OK",
"command": "esign",
"responsedata": {
"response": {
"txn": "TXN123456",
"reference": "A1B2C3D4E5F6...",
"redirecturl": "https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign/redirect/A1B2C3D4E5F6...",
"getsigneddocurl": "https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign/signed/A1B2C3D4E5F6...?token=SHORT_LIVED_TOKEN"
}
}
}
Error Response¶
3. Secure Transaction Lookup (Status + PDF URL)¶
POST /api/java/v1/esign/transaction¶
This is the single secured lookup endpoint. It accepts reference, transactionid, or internaltxn and returns current status and pdfurl (and signpdf64 if completed).
Accepted identifiers (use one):
- reference (server-generated)
- transactionid (your client transaction ID)
- internaltxn (system-generated)
Lookup precedence: reference ? transactionid ? internaltxn
If multiple are provided, the first non-empty value in this order is used.
Response (JSON)¶
{
"status": "SUCCESS",
"statuscode": "200",
"command": "esign",
"requestid": "17707012345678900000",
"date": "2026-02-10T12:30:00+05:30",
"responsedata": {
"response": {
"pdfurl": "https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign/document/A1B2C3D4E5F6...?token=SHORT_LIVED_TOKEN",
"txn": "TXN123456",
"reference": "A1B2C3D4E5F6...",
"transactionStatus": "COMPLETED",
"signpdf64": "JVBERi0xLjQK..."
}
}
}
4. Download Signed PDF¶
GET /api/java/v1/esign/document/{reference}¶
Possible responses:
- 200 with PDF bytes (signed document)
- 202 if signing is still in progress
- 404 if transaction or signed PDF is not found
- 410 if signing failed
- 401 if token is missing/invalid and auth headers are not provided
4.1 Signed PDF as Base64¶
GET /api/java/v1/esign/signed/{reference}¶
Returns Base64 (signpdf64) plus pdfurl for direct download.
Requires auth headers: X-Auth-Token and X-Auth-Key.
You can force format using:
- /signed/{reference}/json
- /signed/{reference}/xml
Possible error codes in response:
- PENDING when signing is in progress (status is PENDING)
- FAILED when signing failed
- NOTFOUND when transaction or signed PDF is missing
- ERROR for server-side errors
- AUTH-xxx when auth headers are missing/invalid and token is not provided
5. Health Check¶
GET /api/java/v1/esign/health¶
Response¶
Authentication Modes¶
| Mode | Description | Use Case |
|---|---|---|
online-aadhaar-otp |
OTP to registered mobile | Remote signing |
online-aadhaar-bio |
Fingerprint scan | In-person with device |
online-aadhaar-iris |
Iris scan | High security |
online-aadhaar-face |
Face scan | Modern biometric |
capricorn-ekyc-account |
Pre-verified eKYC | KYC customers |
Signing Options¶
| Option | Values | Default | Description |
|---|---|---|---|
cood |
x1,y1,x2,y2 or custom |
350,50,550,120 |
Signature position |
pagenum |
1, all, first, last, 1-3, 1,3,5, custom |
1 |
Pages to sign |
reason |
String | Digital Signature |
Signing reason |
location |
String | India |
Signing location |
customtext |
String | - | Custom text |
greenticked |
y / n |
y |
Green checkmark |
dateformat |
Pattern | dd-MMM-yyyy hh:mm a |
Date format |
lockpdf |
n / y / cf / cfa |
n |
Lock mode |
signaturePositions |
Array | - | Multi-location positions (see below) |
searchbytext |
String | - | Enable global search-by-text mode (use with pagenum=searchbytext and cood=searchbytext) |
boxsize |
String | - | Required in search-by-text mode. Format: width,height |
boxposition |
String | - | Required in search-by-text mode. One of: top, bottom, left, right, on |
Multi-Location Signing¶
For different signature positions on different pages, use signaturePositions:
Requirements¶
- Set
cood="custom" - Set
pagenum="custom" - Provide
signaturePositionsarray
JSON Example¶
{
"auth": {
"command": "esign",
"token": "YOUR_TOKEN",
"key": "YOUR_KEY"
},
"parameter": {
"uploadpdf": {
"pdf64": "BASE64_PDF...",
"title": "Contract",
"mode": "online-aadhaar-otp",
"signername": "John Doe",
"option": {
"cood": "custom",
"pagenum": "custom",
"reason": "Digital Signature",
"signaturePositions": [
{ "pages": "first", "cood": "50,50,200,120" },
{ "pages": "2,3", "cood": "200,400,400,470" },
{ "pages": "last", "cood": "400,50,550,120" }
]
}
}
}
}
signaturePositions Array¶
| Field | Type | Description |
|---|---|---|
pages |
String | "first", "last", "all", "1", "1-3", "1,3,5" |
cood |
String | Coordinates: "x1,y1,x2,y2" |
Search By Text (Global Auto-Placement)¶
Enable automatic signature placement by text search across all pages.
Requirements¶
- Set
pagenum = "searchbytext" - Set
cood = "searchbytext" - Provide
searchbytextat PDF level - Provide both
boxsizeandboxposition - Any
signaturePositionsor manual coords are ignored in this mode
Behavior¶
- Searches all pages
- Case-insensitive, partial match
- Signature is placed for each occurrence of the text
- If text not found anywhere, request fails with validation error
Example (XML)¶
<option>
<pagenum>searchbytext</pagenum>
<cood>searchbytext</cood>
<searchbytext>Authorized Signatory</searchbytext>
<boxsize>220,80</boxsize>
<boxposition>bottom</boxposition>
</option>
Example (JSON)¶
{
"option": {
"pagenum": "searchbytext",
"cood": "searchbytext",
"searchbytext": "Authorized Signatory",
"boxsize": "220,80",
"boxposition": "bottom"
}
}
Page Selection¶
| Value | Description |
|---|---|
1 |
First page only |
first |
First page |
last |
Last page |
all |
All pages |
1-3 |
Pages 1 to 3 |
1,3,5 |
Pages 1, 3, and 5 |
PDF Lock Modes¶
| Value | Mode | Description |
|---|---|---|
n |
No Lock | Allow more signatures (default) |
y |
Fully Locked | No changes allowed |
cf |
Form Filling Only | Only form fields editable |
cfa |
Forms + Annotations | Forms and comments allowed |
Date Formats¶
| Format | Output |
|---|---|
dd-MMM-yyyy hh:mm a |
06-Jan-2025 02:30 PM |
dd/MM/yyyy HH:mm |
06/01/2025 14:30 |
yyyy-MM-dd |
2025-01-06 |
MMMM dd, yyyy |
January 06, 2025 |
Error Codes¶
Authentication Errors¶
| Code | Description | Solution |
|---|---|---|
AUTH-001 |
Authentication info is missing | Include auth block in request |
AUTH-002 |
Token is required | Provide auth.token |
AUTH-003 |
Key is required | Provide auth.key |
AUTH-004 |
Invalid token | Check api.auth.token in your request matches server config |
AUTH-005 |
Invalid key | Check api.auth.key in your request matches server config |
AUTH-006 |
Invalid command | Use a valid command value |
Request Validation Errors¶
| Code | Description | Solution |
|---|---|---|
REQ-001 |
Request body is empty | Send a valid JSON/XML payload |
REQ-002 |
Parameter section is missing | Include <parameter> / parameter |
REQ-003 |
uploadpdf section is missing |
Include <uploadpdf> / uploadpdf |
REQ-004 |
Either pdf64 or pdfurl is required |
Provide one of them |
REQ-005 |
mode is required |
Provide a valid mode |
REQ-006 |
Invalid mode | Use online-aadhaar-otp, online-aadhaar-bio, online-aadhaar-iris, online-aadhaar-face, or capricorn-ekyc-account |
REQ-007 |
ekycid is required (eKYC mode) |
Provide ekycid for eKYC modes |
REQ-008 |
signername is required |
Provide a signer name |
REQ-009 |
title must not exceed 50 characters |
Shorten the title |
Validation Errors¶
| Code | Description | Solution |
|---|---|---|
VAL-001 |
Invalid PDF data | Ensure PDF is valid and properly Base64 encoded |
VAL-002 |
Invalid signer name | Provide a non-empty signer name |
VAL-003 |
Invalid mode specified | Use a valid mode |
VAL-004 |
Invalid page selection | Use 1, all, first, last, 1-3, or 1,3,5 |
VAL-005 |
Invalid coordinates | Use x1,y1,x2,y2 with valid numbers |
VAL-006 |
Title too long | Title must be 50 characters or less |
VAL-007 |
Invalid date format | Check dateformat pattern |
VAL-008 |
signaturePositions provided but cood is not custom |
Set cood=custom |
VAL-009 |
signaturePositions provided but pagenum is not custom |
Set pagenum=custom |
VAL-010 |
Empty signaturePositions array |
Provide at least one position |
VAL-011 |
Invalid page value in position | Fix the pages value |
VAL-012 |
Invalid coordinates in position | Fix the cood value |
SearchByText Errors¶
| Code | Description | Solution |
|---|---|---|
SBT-001 |
searchByText value is empty | Provide non-empty searchbytext |
SBT-002 |
Search text not found in PDF | Ensure text exists in PDF |
SBT-003 |
PDF has no extractable text | Use a text-based PDF (OCR not supported) |
SBT-004 |
pages/cood mismatch for searchByText | Set both pagenum and cood to searchbytext |
SBT-005 |
Invalid boxsize |
Use width,height with positive numbers |
SBT-006 |
Invalid boxposition |
Use top, bottom, left, right, or on |
SBT-999 |
SearchByText processing error | Retry or contact support |
Transaction Errors¶
| Code | Description | Solution |
|---|---|---|
TXN-001 |
Transaction ID already used | Use a unique transaction ID (see below) |
TXN-002 |
Transaction not found | Check reference/transaction ID |
TXN-003 |
Transaction expired | Start a new signing request |
ESP (eSign Provider) Errors¶
| Code | Description | Solution |
|---|---|---|
ESP-901 |
Invalid Authentication Mode | Check AuthMode |
ESP-902 |
Invalid ASP ID. It cannot be Empty | Configure ASP ID |
ESP-903 |
Invalid ASP ID. It may not exist or may be inactive. | Verify ASP ID |
ESP-905 |
Document Hash not received | Ensure hash is sent |
ESP-906 |
UID Token does not match | Check UID token |
ESP-907 |
Request Time Stamp cannot be Empty | Ensure timestamp is set |
ESP-908 |
Request Time Stamp is not valid. Please check the server time. | Sync server time |
ESP-909 |
Transaction ID cannot be Empty | Provide txn |
ESP-910 |
Duplicate Transaction ID for the given ASP. | Use unique txn |
ESP-911 |
Input XML Signature verification failed. | Verify XML signature |
ESP-922 |
Invalid Signature on Input XML. | Use correct certificate |
ESP-944 |
User terminated eKYC process | User canceled |
ESP-945 |
User terminated eKYC process after OTP Generation | User canceled after OTP |
ESP-946 |
User interface page expired | Restart signing |
ESP-991 |
ESP Database Connectivity Error | Retry later |
ESP-992 |
Input XML Parsing Error. | Validate XML |
ESP-993 |
Error Parsing CA Response XML | Retry or contact ESP |
ESP-999 |
Unknown Error | Contact ESP |
Processing Errors¶
| Code | Description | Solution |
|---|---|---|
PROC-001 |
PDF data required | Provide either pdf64 or pdfurl |
PROC-002 |
Unsupported authentication mode | Use a supported mode |
PROC-003 |
PDF processing failed | Check PDF integrity |
PROC-004 |
Signature embedding failed | Contact support |
PROC-999 |
General processing error | Retry or contact support |
License Errors¶
| Code | Description | Solution |
|---|---|---|
LIC-001 |
License file not found | Place eSignLicense in config/ folder |
LIC-002 |
License expired | Contact Capricorn for license renewal |
LIC-003 |
License invalid | Check license file is correct |
Certificate Errors¶
| Code | Description | Solution |
|---|---|---|
CERT-001 |
Certificate file not found | Place privatekey.pfx in config/ folder |
CERT-002 |
Certificate password incorrect | Check esign.certificate.password in config |
CERT-003 |
Certificate expired | Contact Capricorn for certificate renewal |
System Errors¶
| Code | Description | Solution |
|---|---|---|
SYS-001 |
General system error | Retry or contact support |
SYS-002 |
Error fetching status | Retry status lookup |
Transaction ID Uniqueness¶
Important: Transaction IDs Cannot Be Reused
Once a PDF is successfully signed with a transaction ID (txn), that ID cannot be used again. This prevents duplicate signing and ensures each transaction is unique.
How It Works¶
- You send a request with
txn: "ORDER-12345" - User completes signing successfully
- Transaction
ORDER-12345is marked as COMPLETED - Any future request with
txn: "ORDER-12345"returns error:
{
"status": "error",
"errorCode": "TXN-001",
"errorMessage": "Transaction ID 'ORDER-12345' has already been used for a completed signing. Each transaction ID can only be used once. Please use a unique transaction ID."
}
Best Practices for Transaction IDs¶
| Practice | Example |
|---|---|
| Use unique identifiers | ORDER-12345, INV-2025-001, CONTRACT-ABC123 |
| Include timestamp | DOC-20251215-143052-001 |
| Use UUID | 550e8400-e29b-41d4-a716-446655440000 |
| Prefix by document type | LOAN-001, KYC-002, AGREEMENT-003 |
Checking If Transaction ID Was Used¶
Before submitting, you can track used transaction IDs in your system, or handle the TXN-001 error and generate a new ID.
Complete Flow¶
sequenceDiagram
participant App as Your App
participant API as eSign API
participant ESP as ESP Server
participant User as User
Note over App,API: Step 1: (Optional) Convert PDF to Base64
App->>API: POST /upload-pdf (form-data with file)
API-->>App: { success: true, pdf64: "..." }
Note over App,API: Step 2: Initiate Signing
App->>API: POST /esign (JSON/XML with pdf64)
API-->>App: { redirectUrl, reference }
Note over App,User: Step 3: User Authentication
App->>User: Open redirectUrl
User->>ESP: Complete OTP/Biometric Auth
ESP->>API: Callback with signature
Note over API: Step 4: Process Signature
API-->>API: Embed signature in PDF
Note over App,API: Step 5: Retrieve Signed Document
App->>API: POST /transaction (auth + reference)
API-->>App: { transactionStatus: "COMPLETED", pdfurl: "..." }
App->>API: GET /document/{reference}?token=SHORT_LIVED_TOKEN
API-->>App: Signed PDF
SDK Integration¶
JavaScript SDK¶
const client = new ESignClient({
baseUrl: 'https://your-ngrok-url.ngrok-free.dev',
token: 'YOUR_TOKEN',
key: 'YOUR_KEY'
});
const result = await client.signDocument({
pdfBase64: base64Pdf,
signerName: 'John Doe',
mode: ESignMode.AADHAAR_OTP
});
window.location.href = result.redirectUrl;
Android SDK¶
val client = ESignClient.Builder()
.baseUrl("https://your-ngrok-url.ngrok-free.dev")
.token("YOUR_TOKEN")
.key("YOUR_KEY")
.build()
val request = ESignRequest.Builder()
.pdfBase64(base64Pdf)
.signerName("John Doe")
.mode(ESignMode.AADHAAR_OTP)
.build()
client.signDocument(request) { response ->
// Open redirectUrl in WebView or browser
}
Quick Test¶
# 1. Health check
curl https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign/health
# 2. (Optional) Convert PDF file to Base64
curl -X POST https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign/upload-pdf \
-F "file=@document.pdf"
# 3. Sign PDF (use pdf64 from step 2 or your own Base64 encoded PDF)
curl -X POST https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign \
-H "Content-Type: application/json" \
-d '{
"auth": {
"command": "esign",
"token": "YOUR_TOKEN",
"key": "YOUR_KEY"
},
"parameter": {
"uploadpdf": {
"pdf64": "YOUR_BASE64_PDF",
"title": "Test Document",
"mode": "online-aadhaar-otp",
"txn": "TEST-001",
"signername": "John Doe"
}
}
}'
# 4. Secure lookup (status + pdfurl)
curl -X POST https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign/transaction \
-H "Content-Type: application/json" \
-d '{
"auth": { "token": "YOUR_TOKEN", "key": "YOUR_KEY" },
"reference": "YOUR_REFERENCE"
}'
# 5. Download signed PDF (when status is COMPLETED)
curl -o signed.pdf "https://your-ngrok-url.ngrok-free.dev/api/java/v1/esign/document/YOUR_REFERENCE?token=SHORT_LIVED_TOKEN"
Version: 1.0 | For: JavaScript SDK, Android SDK, Direct API Integration