Templates
Save reusable signer layouts once and initialize Esign sessions from them at runtime.
If you send the same document layout repeatedly — offer letters, NDAs,
agreements — templates let you define the signer layout once and reuse it.
A template stores the source file_id and an ordered signers array,
where each signer contains its own PDF elements and optional defaults
(sign type, verification settings, geofencing, and more).
How templates work
- Save a template with the file and the per-signer element layout.
- At runtime, call
Initialize Esign from template
with the
template_idand the actual signer details (name, email/mobile, reason). - The template's signer defaults are merged with the runtime signer data,
then the normal Esign validation flow runs — the result is a real Esign
session, identical to one created with
initialize-esign.
Ordering rules
The template's signers array is ordered: the first template signer
maps to the first runtime signer in initialize-from-template, the second
to the second, and so on. The runtime signer count must match the template
signer count exactly, or the request fails with signer_count_mismatch.
Every template signer must contain at least one signature element.
Save a template
{
"name": "Employment Offer Template",
"file_id": "file_onwEUoMxnWhewUzodZeW",
"folder": "HR",
"signers": [
{
"sign_type": "suresign",
"auth_mode": 1,
"max_retry": 1,
"reason": "Employer sign",
"verify_email": false,
"verify_mobile": false,
"elements": [
{ "x": 100, "y": 120, "page": 0, "alignment": "center", "type": "signature" }
]
},
{
"sign_type": "suresign",
"auth_mode": 1,
"reason": "Employee sign",
"verify_email": true,
"verify_location": true,
"location_source": "ip",
"enforce_geofence": true,
"latitude": 19.076,
"longitude": 72.8777,
"radius": 500,
"elements": [
{ "x": 100, "y": 220, "page": 0, "alignment": "center", "type": "signature" }
]
}
]
}Only name, file_id, and signers (with x, y, page, alignment,
type per element) are required — everything else is an optional signer
default. file_id must belong to the authenticated user.
Success response (truncated):
{
"data": {
"client_id": "template_xxx",
"name": "Employment Offer Template",
"file_id": "file_onwEUoMxnWhewUzodZeW",
"folder": "HR",
"signers": [
{
"sign_type": "suresign",
"auth_mode": [1],
"reason": "Employer sign",
"elements": [
{
"field_id": "field_xxx",
"x": 100,
"y": 120,
"page": 0,
"type": "signature",
"alignment": "center",
"width": 50,
"height": 50
}
]
}
]
},
"status_code": 200,
"message": "Success",
"success": true
}Error responses:
| HTTP Status | Message Code | Description |
|---|---|---|
400 | bad_request | Template signer validation failed. |
401 | unauthorized | Invalid or expired access token. |
404 | not_found | The provided file ID does not exist for the current user. |
field_id and element_values
When a template is saved, each element gets an auto-generated field_id
(returned in the save/update response). At runtime, you can fill element
values per signer by referencing those IDs:
{
"template_id": "template_xxx",
"signers": [
{
"full_name": "Employer A",
"email": "employer@example.com",
"reason": "Employer sign",
"element_values": {
"field_xxx": "INV-1001",
"field_yyy": "now"
}
}
]
}element_values only overrides an element's value — position and type
always come from the template. Signature value asset IDs are stripped at
initialization unless the saved field sets allow_wet_signature: true.
Initialize an Esign from a template
{
"template_id": "template_xxx",
"sign_type": "suresign",
"auth_mode": 1,
"max_retry": 1,
"folder": "HR",
"allow_download": true,
"expiry_seconds": 7200,
"redirect_url": "https://example.com/esign/complete",
"backend": "emudhra",
"stamp": {
"amount": "100.00",
"state_code": "MH",
"article_id": "article_001",
"first_party_name": "Employer A",
"second_party_name": "Employee B"
},
"email_template_overrides": {
"company_name": "Acme Corp",
"legal_name": "Acme Corporation Pvt Ltd.",
"support_email": "support@acme.com"
},
"signers": [
{
"full_name": "Employer A",
"email": "employer@example.com",
"reason": "Employer sign",
"face_ref_file_id": "file_faceReferenceImage",
"face_match_threshold": 80,
"face_max_attempts": 5,
"notification": { "invite": true, "completion": true, "whatsapp": true },
"element_values": { "field_xxx": "INV-1001", "field_yyy": "now" }
},
{
"full_name": "Employee B",
"email": "employee@example.com",
"mobile": "9123456789",
"country_code": "+91",
"reason": "Employee sign",
"name_match": true,
"notification": { "invite": false, "completion": true, "whatsapp": false },
"element_values": { "field_zzz": "Employee B" }
}
]
}Notes
- Only
template_idandsignersare required; signers must be supplied in the same order as the template signer array, with a matching count. full_nameshould be supplied,reasonmust be supplied unless a default reason is already saved in the template signer, and at least one ofemailormobilemust be present (country_codeis required whenmobileis provided).expiry_seconds: optional, min = 3600 (1 hour), max = 2592000 (30 days).name_matchis optional and only applies to Aadhaar signers; it is ignored for non-Aadhaar signers.face_ref_file_idenables face verification for the runtime signer — upload the JPEG or PNG through Upload asset and use the returnedclient_id.face_match_threshold(50–100, default 80) andface_max_attempts(1–10, default 5) apply only when it is provided.stamp: optional e-stamping. Use either the amount-based reservation flow (amount+state_code+article_id, required together) or pass pre-reservedstamp_instance_ids.notificationworks exactly as ininitialize-esign— see Getting started.
The response is a full Esign session: each signer includes an
invite_url, token, merged element list, and verification state.
Error responses:
| HTTP Status | Message Code | Description |
|---|---|---|
400 | signer_count_mismatch | Runtime signer count does not match the saved template. |
400 | bad_request | Validation failed after template and runtime signer merge. |
401 | unauthorized | Invalid or expired access token. |
404 | not_found | The provided template ID or referenced file ID does not exist. |
Updating a template
Update template takes the
template client_id; name, folder, file_id, and signers are all
optional:
{
"client_id": "template_xxx",
"name": "Employment Offer Template v2",
"folder": "HR Updated",
"signers": [
{
"sign_type": "suresign",
"max_retry": 2,
"reason": "Employer sign updated",
"accept_virtual_sign": true,
"elements": [
{ "x": 140, "y": 120, "page": 0, "alignment": "center", "type": "signature" }
]
},
{
"sign_type": "pfx",
"auth_mode": [1, 2],
"max_retry": 3,
"pfx_id": "pfx_yyy",
"reason": "Employee sign updated",
"verify_email": true,
"verify_mobile": true,
"elements": [
{ "x": 140, "y": 220, "page": 0, "alignment": "center", "type": "signature" }
]
}
]
}- If
signersis provided, it replaces the saved blueprint completely and regenerates everyfield_id— update any storedelement_valuesmappings accordingly. - If
signersis omitted, the saved signers are preserved. - If
file_idis provided, it must belong to the authenticated user.
Error responses:
| HTTP Status | Message Code | Description |
|---|---|---|
400 | bad_request | Template signer validation failed when signers is provided. |
401 | unauthorized | Invalid or expired access token. |
404 | not_found | The template or provided file ID does not exist. |
Signer defaults available in templates
Per template signer you can preset:
sign_type(aadhaar,suresign, orpfx),auth_mode,max_retry,pfx_id,reasonverify_email/verify_mobile,accept_virtual_sign- Location controls:
verify_location,location_source(deviceorip), and geofencing viaenforce_geofence+latitude+longitude+radius(the last three are required together when geofencing is on)
Runtime-only signer options — name_match, face verification
(face_ref_file_id, face_match_threshold, face_max_attempts), and
notification — are passed in initialize-from-template.