Placing signature fields
How to put fields on a PDF so they land where you intend, and so each signer gets exactly the boxes they are supposed to fill.
1. Coordinates: PDF points, origin top-left
x, y, width and height are PDF points (1 pt = 1/72 inch). x grows to the right, y grows downward from the top edge, and page is 1-based.
Internally the editor stores percentages of the page and the API converts for you: send points, read points back. Never send percentages.
Many PDF tools use a bottom-left origin. Convert first:
y_top_left = page_height - y_bottom_left - height
2. Use ONE signature-block per signer
A signature-block already contains everything a signer contributes: the signature, the signing date and a truncated verification hash.
// Don't scatter fields
{ "id": "sig", "type": "signature", ... }
{ "id": "date", "type": "date", ... }
{ "id": "hash", "type": "text", ... }
// Do this: one block per signer
{ "id": "sig-provider", "type": "signature-block", "page": 1,
"x": 56, "y": 412, "width": 167, "height": 59 }3. Size the block correctly
The validated size is 28% x 7% of the page — on A4 that is 167 x 59 pt. Too short and the date/hash lines get clipped by the border; too tall and you get a large empty box.
You do not have to guess. GET /documents/{id}/fields returns pageSizes and a matching recommendedSignatureBlock.
GET /documents/{id}/fields
{
"pageSizes": [{ "width": 595, "height": 842 }],
"recommendedSignatureBlock": [{ "width": 167, "height": 59 }]
}3b. Add required wording with caption
Some contracts require the signer to subscribe to specific wording — French practice, for example, asks for "Bon pour fabrication" next to the signature. Put that text in the block's caption: it replaces the generic "Signed by:" heading, so you still place one box.
{
"id": "p1-client-block",
"type": "signature-block",
"caption": "Bon pour fabrication",
"page": 1, "x": 56, "y": 483, "width": 167, "height": 59,
"recipientId": "r_client"
}Long captions wrap onto multiple lines, and the block grows upward automatically when it needs more room — so the signature is never clipped and the bottom edge stays where you anchored it. Maximum 200 characters: a caption is legal wording, not a paragraph.
4. Anchor the block to the signature rule
Put the bottom of the block on the printed signature line, so the block covers the space just above it.
y_top_left = page_height - line_y_bottom_left - height // rule at 300pt from the bottom of an A4 page, block height 59: // y_top_left = 842 - 300 - 59 = 483
5. Assign every field to a recipient
A field with no assignee is shown to every signer — on a two-party document that means both people are asked to fill the same box.
{
"mode": "individual",
"recipients": [
{ "id": "r_provider", "name": "Alex", "email": "alex@example.com" },
{ "id": "r_client", "name": "Sam", "email": "sam@example.com" }
],
"fields": [
{ "id": "p1-provider-block", "type": "signature-block", "page": 1,
"x": 56, "y": 483, "width": 167, "height": 59, "recipientId": "r_provider" },
{ "id": "p1-client-block", "type": "signature-block", "page": 1,
"x": 320, "y": 483, "width": 167, "height": 59, "recipientId": "r_client" }
]
}Common mistakes
| Symptom | Cause |
|---|---|
| Signature lands off the page or far right | Sent percentages where points are expected |
| Signature appears mirrored vertically | Computed y from a bottom-left origin |
| Both signers asked to fill the same box | Field has no recipientId |
| Date/hash clipped inside the block | Block too short |
| Large empty box | Block too tall |
| 400 on PUT /fields | Field targets a page that does not exist |
End-to-end checklist
POST /documentswith the PDF → notedocumentId.GET /documents/{id}/fields→ read page sizes and the recommended block size.- Compute each block position from the signature rule (top-left origin).
PUT /documents/{id}/fieldswith recipients and one block per signer.GET /documents/{id}/fields→ verify coordinates and assignee.POST /documents/{id}/signers→ invites (and emails) each signer.POST /documents/{id}/sendwith{"resend": false}→ commit.- Poll
GET /documents/{id}, or use the SDK'swaitForCompletion().