Signadoc Sign in Start free

REST API reference

Everything you can do to your Signadoc account over HTTPS. Examples use placeholder keys; sign in to see them filled in with your own. New here? Read the integration overview first.

Getting started

Base URL: https://signadoc.app. All endpoints are under /api, accept and return JSON (except uploads, which are multipart, and PDF downloads), and use conventional HTTP status codes. IDs are prefixed so you can tell them apart: doc_ documents, env_ envelopes, fld_ fields, emb_ embed tokens.

Your first call, which lists your templates:

curl https://signadoc.app/api/documents -H "X-Api-Key: sk_YOUR_SECRET_KEY"

There are no webhooks yet. To learn when a document is signed, poll GET /api/envelopes/:id or, when embedding the signing page, listen for the signed event.

Authentication

Send your secret key with every request, either as an X-Api-Key header or as a bearer token. Keep it on your server: it grants full access to your account.

curl https://signadoc.app/api/envelopes -H "X-Api-Key: sk_YOUR_SECRET_KEY"
curl https://signadoc.app/api/envelopes -H "Authorization: Bearer sk_YOUR_SECRET_KEY"

The publishable key (pk_…) is different: it is safe in a web page but can only open the embedded field designer from your allowed origins. It cannot read or create anything through the API.

Embed tokens (emb_…) are scoped, expiring credentials created by POST /api/embed/sessions. The embedded pages send them as X-Embed-Token; you normally never handle them directly.

Errors

Every error is JSON with a human-readable error message, sometimes with extra machine-readable fields:

{ "error": "Missing values for API-filled fields: Company", "missing": ["Company"], "hint": "Pass them in \"values\" or set \"allow_missing\": true to leave them blank." }
{ "error": "A document named \"NDA\" already exists. Choose a different name.", "code": "name_taken", "document_id": "doc_…" }
{ "error": "The Free plan allows 3 signing requests per month. Upgrade to Pro for unlimited signing.", "code": "plan_limit", "limit": "envelopes_per_month", "upgrade_url": "/app/billing" }
StatusMeaning
400The request is malformed or missing something. The message says what.
401No valid key. Check the X-Api-Key header.
402A plan limit was reached (code: plan_limit). The message names the limit and upgrade_url points to billing.
403The credential is not allowed to do this (for example an embed token calling an account-wide endpoint).
404Unknown ID, or the resource belongs to another account.
409Conflict with current state: duplicate document name, or changing an envelope that is no longer pending.
413The upload or request body is too large for your plan.
500Something failed on our side. Retrying is safe for GET requests.

Documents

A document is an uploaded PDF plus its field layout. Upload once, reuse it as a template for every signer.

GET/api/documents

List your documents.

Example request
curl https://signadoc.app/api/documents -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "documents": [ { "id": "doc_…", "name": "Service Agreement", "page_count": 1, "tags": ["Sales"], "field_count": 6,
                    "envelope_count": 12, "completed_count": 9, "pending_count": 2, "created_at": "…", "updated_at": "…" } ] }
POST/api/documents

Upload a PDF. Multipart form, not JSON.

ParameterTypeDescription
filefileThe PDF. Required.
namestringDisplay name. Must be unique on your account (case-insensitive). Defaults to the file name.
tagsstringComma-separated tags, e.g. "Sales, HR".
external_refstringYour own identifier, stored and returned as-is.
fieldsJSON stringOptional field list, same shape as PUT /fields, to define fields in the same call.
Example request
curl -X POST https://signadoc.app/api/documents -H "X-Api-Key: sk_YOUR_SECRET_KEY" \
  -F "file=@agreement.pdf" -F "name=Service Agreement" -F "tags=Sales"
Response
201 { "document": { "id": "doc_…", "name": "Service Agreement", "page_count": 1, "pages": [ { "width": 612, "height": 792, "rotation": 0 } ],
                     "tags": ["Sales"], "sha256": "…", "size": 18271, "fields": [] } }
409 { "error": "A document named \"Service Agreement\" already exists…", "code": "name_taken", "document_id": "doc_…" }
GET/api/documents/:id

One document with page sizes and its fields.

Example request
curl https://signadoc.app/api/documents/DOC_ID -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "document": { "id": "doc_…", "name": "…", "pages": [ { "width": 612, "height": 792 } ], "fields": [ { "key": "Name", "type": "name", "page": 1, "x": 90, "y": 150, "w": 200, "h": 18, "required": true, "fill": "signer" } ] } }
GET/api/documents/:id/file

Download the original PDF.

Example request
curl https://signadoc.app/api/documents/DOC_ID/file -H "X-Api-Key: sk_YOUR_SECRET_KEY" -o original.pdf
PATCH/api/documents/:id

Rename a document and/or replace its tags.

ParameterTypeDescription
namestringNew name (unique per account).
tagsstring[]Full replacement tag list. Pass [] to clear.
Example request
curl -X PATCH https://signadoc.app/api/documents/DOC_ID -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" -d '{ "tags": ["Sales", "2026"] }'
Response
{ "document": { "id": "doc_…", "name": "…", "tags": ["Sales", "2026"] } }
DELETE/api/documents/:id

Delete the document, its files and every envelope created from it. Irreversible.

Example request
curl -X DELETE https://signadoc.app/api/documents/DOC_ID -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "ok": true }

Fields

Fields are the boxes on the page. Each has a key (what you pass in values), a type, a position in PDF points measured from the top-left of the page, and a fill mode that says who supplies the value.

GET/api/documents/:id/fields

The field list.

Example request
curl https://signadoc.app/api/documents/DOC_ID/fields -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "fields": [ { "id": "fld_…", "key": "Name", "label": "Name", "type": "name", "page": 1, "x": 90, "y": 150, "w": 200, "h": 18, "required": true, "font_size": 11, "fill": "signer", "auto_source": null } ] }
PUT/api/documents/:id/fields

Replace all fields. Send the complete list every time.

ParameterTypeDescription
keystringName used in values. Required. Repeating a key puts the same value in several places.
labelstringShown to the signer. Defaults to the key.
typestringname, address, phone, email, date, text, signature, initials, checkbox.
pagenumber1-based page number.
x, y, w, hnumberPosition and size in PDF points from the top-left corner.
requiredbooleanDefault true.
font_sizenumberPoints. Default 11. Ignored for signature, initials, checkbox.
fillstringsigner (default), api, or auto. See below.
auto_sourcestringFor fill=auto: date, signer_name, signer_email, envelope_id, document_name.
Example request
curl -X PUT https://signadoc.app/api/documents/DOC_ID/fields -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" \
  -d '{ "fields": [ { "key": "Name", "type": "name", "page": 1, "x": 90, "y": 150, "w": 200, "h": 18, "fill": "api" },
                    { "key": "Signature", "type": "signature", "page": 1, "x": 90, "y": 640, "w": 200, "h": 44 } ] }'
Response
{ "fields": [ … ] }

Fill modes

fillWho supplies the valueWhat the signer sees
signerThe signer types it. If you pre-fill it through values it is locked by default (pass locked: false or a list of keys to keep it editable).An input, or read-only text if pre-filled and locked.
apiYour system, in values when the envelope is created. Required unless allow_missing: true.Read-only text.
autoSignadoc, at the moment of signing, from auto_source.A read-only preview.

Envelopes (signing requests)

An envelope is one document sent to one signer. It carries the pre-filled values, the private signing link, its status (pending, completed or void), an audit trail, and the signed PDF once done.

POST/api/documents/:id/envelopes

Create a signing request for one person.

ParameterTypeDescription
signer_namestringShown on the signing page and in the certificate.
signer_emailstringNeeded to email the link. Falls back to values.Email.
valuesobjectField key → value. Stamped into the PDF. Unknown keys are ignored; signature fields cannot be set here.
lockedboolean | string[]true (default) locks every pre-filled field; false leaves them editable; an array locks only those keys. API-filled fields are always locked.
allow_missingbooleanAllow required api-filled fields to be left blank.
redirect_urlstringWhere to send the signer after signing (http/https).
external_refstringYour own identifier, returned as-is.
sendbooleantrue emails the link immediately (needs a plan with email and SMTP configured).
subject, messagestringEmail subject and intro text when send is true.
Example request
curl -X POST https://signadoc.app/api/documents/DOC_ID/envelopes -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" \
  -d '{ "signer_name": "Jane Doe", "signer_email": "jane@example.com",
        "values": { "Name": "Jane Doe", "Phone": "555-0100" }, "redirect_url": "https://example.com/thanks", "send": true }'
Response
201 { "envelope": { "id": "env_…", "status": "pending", "sign_url": "https://signadoc.app/sign/…", "embed_sign_url": "…?embed=1", "values": { … }, "locked": ["Name", "Phone"], "signed_pdf_url": null }, "delivery": { "sent": true, "mode": "smtp" } }
400 { "error": "Missing values for API-filled fields: Company", "missing": ["Company"], "hint": "…" }
402 { "error": "The Free plan allows 3 signing requests per month…", "code": "plan_limit", "upgrade_url": "/app/billing" }
POST/api/documents/:id/send

Send to up to 200 recipients in one call. Each gets their own envelope.

ParameterTypeDescription
recipientsarray[{ name, email, values, external_ref, redirect_url }]. Required.
valuesobjectShared values applied to every recipient (per-recipient values win).
subject, messagestringEmail content.
sendbooleanDefault true. false creates the envelopes without emailing.
locked, redirect_url, external_ref, allow_missingAs for a single envelope.
Example request
curl -X POST https://signadoc.app/api/documents/DOC_ID/send -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" \
  -d '{ "recipients": [ { "name": "Jane Doe", "email": "jane@example.com" }, { "name": "Bob Ray", "email": "bob@example.com" } ],
        "values": { "Company": "Acme LLC" }, "subject": "Please sign" }'
Response
{ "created": 2, "sent": 2, "results": [ { "email": "jane@example.com", "envelope": { "id": "env_…", "sign_url": "…" }, "delivery": { "sent": true } }, { "email": "bad-address", "error": "Invalid email address" } ] }
POST/api/documents/:id/fill

Fill the PDF with values and return it. No envelope, no signing.

ParameterTypeDescription
valuesobjectField key → value.
signer_name, signer_emailstringUsed by auto fields that reference the signer.
Example request
curl -X POST https://signadoc.app/api/documents/DOC_ID/fill -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" -d '{ "values": { "Name": "Jane Doe" } }' -o filled.pdf
Response
The PDF bytes (Content-Type: application/pdf).
GET/api/documents/:id/envelopes

Envelopes created from one document.

Example request
curl https://signadoc.app/api/documents/DOC_ID/envelopes -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "envelopes": [ … ] }
GET/api/envelopes

All envelopes on the account, newest first (max 500).

ParameterTypeDescription
statusquerypending, completed or void.
Example request
curl "https://signadoc.app/api/envelopes?status=pending" -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "envelopes": [ { "id": "env_…", "document_name": "…", "status": "pending", "signer_email": "…", "sign_url": "…", "sent_at": "…", "send_count": 1 } ] }
GET/api/envelopes/:id

Status, values and the full audit trail. Poll this to know when a document is signed.

Example request
curl https://signadoc.app/api/envelopes/ENV_ID -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "envelope": { "id": "env_…", "status": "completed", "completed_at": "…", "signed_sha256": "…", "signed_pdf_url": "https://signadoc.app/api/envelopes/env_…/signed.pdf",
                "audit": [ { "event": "envelope.created", "at": "…" }, { "event": "envelope.sent", "detail": { "to": "…" } }, { "event": "envelope.viewed", "ip": "203.0.113.9", "user_agent": "…" },
                           { "event": "envelope.signed" }, { "event": "envelope.completed" } ] } }
Audit events: envelope.created, envelope.updated, envelope.sent, envelope.send_failed, envelope.viewed, envelope.signed, envelope.completed, envelope.voided.
PATCH/api/envelopes/:id

Change values or signer details on a pending envelope, for example when your CRM learns a phone number after sending.

ParameterTypeDescription
valuesobjectKeys to set or overwrite.
clearstring[]Keys to remove.
lockedboolean | string[]As on creation.
signer_name, signer_emailstring
Example request
curl -X PATCH https://signadoc.app/api/envelopes/ENV_ID -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" -d '{ "values": { "Phone": "555-0199" } }'
Response
{ "envelope": { … } }   409 if the envelope is no longer pending.
POST/api/envelopes/:id/send

Email the signing link, or send a reminder.

ParameterTypeDescription
tostringOverride the recipient address.
subject, messagestringEmail content.
Example request
curl -X POST https://signadoc.app/api/envelopes/ENV_ID/send -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" -d '{ "message": "Friendly reminder!" }'
Response
{ "delivery": { "sent": true, "mode": "smtp" }, "envelope": { "sent_at": "…", "send_count": 2 } }
GET/api/envelopes/:id/signed.pdf

Download the signed, flattened PDF with its certificate page. 404 until signed.

ParameterTypeDescription
downloadquerydownload=1 sets Content-Disposition: attachment.
Example request
curl https://signadoc.app/api/envelopes/ENV_ID/signed.pdf -H "X-Api-Key: sk_YOUR_SECRET_KEY" -o signed.pdf
POST/api/envelopes/:id/void

Cancel a pending request. The link stops working. Completed envelopes cannot be voided.

ParameterTypeDescription
reasonstringStored in the audit trail.
Example request
curl -X POST https://signadoc.app/api/envelopes/ENV_ID/void -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" -d '{ "reason": "Superseded" }'
Response
{ "envelope": { "status": "void" } }
DELETE/api/envelopes/:id

Delete an envelope and its signed PDF.

Example request
curl -X DELETE https://signadoc.app/api/envelopes/ENV_ID -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "ok": true }

Embed sessions

Short-lived tokens that let an iframe act on your account without exposing a key. See the Overview for how the iframe side works.

POST/api/embed/sessions

Create an embed session with your secret key.

ParameterTypeDescription
kindstringdefine (field designer, default) or sign (signing page).
document_idstringdefine: restrict the session to this document. sign: create an envelope from this document.
envelope_idstringsign: embed an existing envelope instead.
values, signer_name, signer_email, redirect_url, external_refsign: passed to envelope creation.
title, accent, allow_uploadstringdefine: designer appearance options.
ttl_secondsnumber60 to 86400. Default 3600.
Example request
curl -X POST https://signadoc.app/api/embed/sessions -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" -d '{ "kind": "sign", "document_id": "DOC_ID", "signer_name": "Jane Doe", "values": { "Name": "Jane Doe" } }'
Response
define → 201 { "kind": "define", "token": "emb_…", "url": "https://signadoc.app/embed/define?token=emb_…", "expires_in": 3600 }
sign   → 201 { "kind": "sign", "envelope": { … }, "url": "https://signadoc.app/sign/…?embed=1", "expires_in": 3600 }
POST/api/embed/sessions/public

Same, but callable from the browser with the publishable key. Origin-checked; define only.

ParameterTypeDescription
publishable_keystringYour pk_ key.
document_idstringOptional.
Example request
fetch('https://signadoc.app/api/embed/sessions/public', { method: 'POST', headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ publishable_key: 'pk_YOUR_PUBLISHABLE_KEY' }) }).then(r => r.json()).then(({ url }) => iframe.src = url);

Account

Mostly used by the dashboard, but available to scripts.

GET/api/auth/me

The current user, plan and keys.

Example request
curl https://signadoc.app/api/auth/me -H "X-Api-Key: sk_YOUR_SECRET_KEY"
Response
{ "user": { "id": "usr_…", "email": "…", "name": "…" }, "plan": { "id": "pro", … }, "secret_key": "sk_…", "publishable_key": "pk_…", "allowed_origins": [ … ] }
PUT/api/auth/settings

Update your name and allowed embed origins.

ParameterTypeDescription
namestring
allowed_originsstring[]Origins allowed to host the embedded designer.
Example request
curl -X PUT https://signadoc.app/api/auth/settings -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" -d '{ "allowed_origins": ["https://portal.example.com"] }'
POST/api/auth/rotate-keys

Generate a new secret or publishable key. The old one stops working immediately.

ParameterTypeDescription
keystring"secret" or "publishable".
Example request
curl -X POST https://signadoc.app/api/auth/rotate-keys -H "X-Api-Key: sk_YOUR_SECRET_KEY" -H "Content-Type: application/json" -d '{ "key": "secret" }'

Objects

Document

{ "id": "doc_…", "name": "Service Agreement", "original_name": "agreement.pdf", "page_count": 2, "size": 18271, "sha256": "…",
  "source": "app" | "api" | "embed", "external_ref": null, "tags": ["Sales"], "created_at": "…", "updated_at": "…",
  "pages": [ { "width": 612, "height": 792, "rotation": 0 } ],      // on GET /api/documents/:id
  "fields": [ Field, … ] }

Field

{ "id": "fld_…", "key": "Name", "label": "Full name", "type": "name", "page": 1, "x": 90, "y": 150, "w": 200, "h": 18,
  "required": true, "font_size": 11, "fill": "signer" | "api" | "auto", "auto_source": null | "date" | "signer_name" | "signer_email" | "envelope_id" | "document_name" }

Envelope

{ "id": "env_…", "document_id": "doc_…", "document_name": "…", "status": "pending" | "completed" | "void",
  "signer_name": "Jane Doe", "signer_email": "jane@example.com", "values": { "Name": "Jane Doe" }, "locked": ["Name"],
  "redirect_url": null, "external_ref": null, "created_at": "…", "completed_at": null, "sent_at": null, "send_count": 0,
  "sign_url": "https://signadoc.app/sign/…", "embed_sign_url": "https://signadoc.app/sign/…?embed=1",
  "signed_pdf_url": null, "signed_sha256": null,
  "audit": [ { "event": "envelope.created", "ip": "…", "user_agent": "…", "detail": {}, "at": "…" } ]   // on GET /api/envelopes/:id
}

Values

A plain object of field key to value. Text-like fields take strings, checkboxes take true/false (or "yes"/"on"), dates take any string you want printed. Keys that do not match a field are ignored. Signature and initials fields can only be drawn by the signer.