Docs

Upload a prepared PDF, drag signature and date fields onto it, assign each to a signer, optionally self-sign, and send.

Uploaded-PDF envelopes

Use this flow when the document you want signed already exists as a PDF — a contract, an NDA, a vendor agreement — and isn't being generated by a form.

The envelope's source_kind is uploaded (versus form_submission for inline / multi-signer plans on forms). Field placements live in the esign_field_placements table; coordinates are normalized 0..1 within each page, so the document can re-render at any DPI and the signature still lands in the right spot.

The flow

  1. Upload the PDF. Open Envelopes → New uploaded-PDF. Drop a PDF in. The platform creates a draft envelope with source_kind = 'uploaded' and stores the source document as an attachment.
  2. Place fields. Open the placement editor. Drag signature and date fields onto the pages where signers will sign. Each field is assigned to a specific signer slot.
  3. Add signers. For each signer, supply a role label, capture mode (inline self-sign or send emailed link), and the email-source field.
  4. Optional self-sign. If the admin is one of the signers, the inline self-sign step happens before send. The admin's signature stamps every field assigned to that admin slot.
  5. Send. The platform fires invitation emails to every send signer. The envelope moves to in_progress. Each signer in order signs the document via their portal link.

When the last required signer signs, the platform stamps every signer's signature PNG into the corresponding field positions (signature fields become PDF XObjects; date fields become text strings rendered at the assigned coordinates), then seals the envelope and generates the Certificate of Completion.

Field placement details

  • Signature fields — accept a signature PNG image. Each signer has one signature image; the same image stamps every signature field assigned to that signer.
  • Date fields — accept a text string. The signer's signed-at timestamp is rendered as the date on every date field assigned to that signer.
  • Coordinatesx, y, width, height are all normalized to 0..1 within the page. Origin is top-left in the authoring UI; the platform flips to PDF's bottom-left origin during stamping.
  • Multi-page support — fields can be placed on any page; the page index is part of the placement record.

Self-sign step

When an admin is one of the signers — for example, the company's counter-signature on a vendor agreement — the placement editor offers an inline self-sign before send. After the admin signs, their signature is stored as an attachment keyed against the self-sign slot, and the rest of the signers receive their portal invitations.

Voiding an in-progress envelope

The same admin dashboard as forms-with-signing handles voids. From the envelope detail view, click Void and supply a reason. The envelope moves to voided; the audit log records the void and the reason; no further signatures can be captured. Completed (sealed) envelopes cannot be voided — the sealed PDF and Certificate of Completion are immutable.

API reference

Upload a PDF and receive an envelope id:

POST /esign/documents
Content-Type: multipart/form-data
Authorization: Bearer <admin JWT>

<binary PDF body>

Response: { "envelope_id": "env_…" }.

Save field placements and signer plan on the draft:

PUT /esign/envelopes/:id/draft
Content-Type: application/json
Authorization: Bearer <admin JWT>

{
  "signers": [ { "role_label": "vendor", "capture": "send", "email_source": { … } } ],
  "placements": [
    { "page": 0, "field_type": "signature", "signer_role": "vendor",
      "x": 0.12, "y": 0.65, "width": 0.25, "height": 0.04 }
  ]
}

Admin self-sign:

POST /esign/envelopes/:id/self-sign
Content-Type: application/json
Authorization: Bearer <admin JWT>

{ "signer_role": "company_counter", "signature_png_base64": "…" }

Send the envelope (admin → in_progress; invitation emails dispatch):

POST /esign/envelopes/:id/send
Authorization: Bearer <admin JWT>

Fetch the current PDF (draft pre-send, sealed after finalize):

GET /esign/envelopes/:id/document.pdf
Authorization: Bearer <admin JWT>

The source_kind discriminator on the envelope determines how the last-signer hook builds the final document: form_submission re-renders from the form payload; uploaded stamps signatures onto the source PDF.

Known limits

  • Field types: only signature and date are supported today. initials and free-text fields are deferred — they will use the same placement model when they ship.
  • PDF format: the upload must be a real PDF, not an image-only scan. The platform doesn't OCR.
  • Document edits after placement: changing the source PDF after placements have been saved invalidates the placements; upload a fresh document instead.