End-to-End Signing Flow
A complete walkthrough of the document signing workflow via the API.
End-to-End Signing Flow
This guide walks through the complete workflow from uploading a document to getting a signed PDF.
Signature evidence
Completed signing workflows keep a signer and document evidence package alongside the PDF:
- Explicit e-sign consent before submission
- Viewed, consent, field completion, submission, and PDF-generated audit events
- Signer timestamps, IP address, and user agent where available
- Completed PDF hash for later byte-for-byte comparison
- Cryptographic verification seal over the signer, audit, and document evidence
- Public verification certificate at
/verify/{submissionId}
Formalingo is designed to support ESIGN/UETA-style electronic signature workflows in the US. Internationally, it supports standard electronic signature evidence trails. It is not a qualified trust service provider and does not create eIDAS qualified electronic signatures (QES), which require qualified certificates and qualified trust-service workflows.
Step 1: Upload the document
curl -X POST https://app.formalingo.com/api/v1/documents \
-H "Authorization: Bearer af_live_YOUR_KEY" \
-F "file=@contract.pdf" \
-F "title=Service Agreement"
# → { "data": { "id": "DOC_ID", ... } }Step 2: Create signer roles
curl -X POST https://app.formalingo.com/api/v1/documents/DOC_ID/signer-roles \
-H "Authorization: Bearer af_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "label": "Client" }'
# → { "data": { "role": "signer_1", ... } }Step 3: Place fields on the document
curl -X POST https://app.formalingo.com/api/v1/documents/DOC_ID/fields \
-H "Authorization: Bearer af_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"label": "Client Signature",
"type": "digital_signature",
"pageNumber": 2,
"x": 0.1, "y": 0.85,
"width": 0.35, "height": 0.06,
"assigneeRole": "signer_1",
"isRequired": true
}'Step 4: Create a submission
curl -X POST https://app.formalingo.com/api/v1/documents/DOC_ID/submissions \
-H "Authorization: Bearer af_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"signers": [{
"role": "signer_1",
"name": "Jane Smith",
"email": "jane@client.com",
"prefill": {
"COMPANY_FIELD_ID": "Client Corp Ltd"
}
}]
}'
# → { "data": { "signers": [{ "link": "https://www.formalingo.com/d/TOKEN", ... }] } }Step 5: Share the signing link
Send signers[0].link to your signer. They open it in their browser, review the document, and sign.
Step 6: Wait for completion
When all signers complete signing:
- Submission
status→completed - A signed PDF is generated and stored
- A completed PDF hash and verification seal are recorded
- A
document_all_completewebhook event fires (if configured)
You can either poll the submissions endpoint or listen to the document_all_complete webhook.
Option A: Poll for completion
curl https://app.formalingo.com/api/v1/documents/DOC_ID/submissions \
-H "Authorization: Bearer af_live_YOUR_KEY"
# Look for status: "completed" in the responseOption B: Webhook
Configure a document_all_complete webhook — see Webhook Events for payload details.
Step 7: Verify the evidence
After completion, use the verification certificate to review the signing evidence before or after downloading the signed PDF.
- Public certificate:
https://www.formalingo.com/verify/{submissionId} - Public API:
GET /api/verify/document/{submissionId} - Creator API:
GET /api/documents/{id}/verify?submissionId={submissionId}
Verification checks whether the current PDF bytes match the recorded hash and whether the stored evidence payload matches the cryptographic seal. Older submissions generated before sealing may need PDF regeneration before hash and seal verification are available.
Step 8: Download the signed PDF
Once the submission is completed, download the signed PDF:
/api/v1/documents/{id}/submissions/{sid}/pdfReturns a short-lived presigned download URL (5-minute expiry). Use the URL to download the file directly.
# Get the download URL
curl https://app.formalingo.com/api/v1/documents/DOC_ID/submissions/SUB_ID/pdf \
-H "Authorization: Bearer af_live_YOUR_KEY"
# Response: { "data": { "downloadUrl": "https://...", "expiresIn": 300 } }
# Download the PDF
curl -o signed-contract.pdf "DOWNLOAD_URL_FROM_RESPONSE"{
"success": true,
"data": {
"submissionId": "submission-uuid",
"completedAt": "2026-03-11T14:30:00.000Z",
"downloadUrl": "https://storage.supabase.co/...signed.pdf?token=...",
"expiresIn": 300
}
}The downloadUrl expires after 5 minutes. Request a new URL by calling the endpoint again.