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

SymptomCause
Signature lands off the page or far rightSent percentages where points are expected
Signature appears mirrored verticallyComputed y from a bottom-left origin
Both signers asked to fill the same boxField has no recipientId
Date/hash clipped inside the blockBlock too short
Large empty boxBlock too tall
400 on PUT /fieldsField targets a page that does not exist

End-to-end checklist

  1. POST /documents with the PDF → note documentId.
  2. GET /documents/{id}/fields → read page sizes and the recommended block size.
  3. Compute each block position from the signature rule (top-left origin).
  4. PUT /documents/{id}/fields with recipients and one block per signer.
  5. GET /documents/{id}/fields → verify coordinates and assignee.
  6. POST /documents/{id}/signers → invites (and emails) each signer.
  7. POST /documents/{id}/send with {"resend": false} → commit.
  8. Poll GET /documents/{id}, or use the SDK's waitForCompletion().