Skip to content

Envelopes API

The envelopes API sends documents for signature from your own system. An envelope is what the app calls a signature request: the same thing, under its API name. It holds up to 10 documents, the people who sign or receive them, and the fields each signer fills.

AutomaDoc Sign records a simple electronic signature with an audit trail: who signed, when, from where, and the fingerprint (SHA-256) of every file. It is not a certificate-based digital signature. Some documents (wills, family matters, court filings) and some official systems need another form of signature, so check what yours requires.

Every route takes a company API key (it starts with amk_), in either header:

X-Webhook-API-Key: amk_…
Authorization: Bearer amk_…

An admin creates company keys in the Company Portal, under Company → API keys (see the API quickstart). A template’s own key opens that one template, not your company’s envelopes: it is refused with API_KEY_INVALID. A key sees every envelope of its company, whether it was made through the API or in the portal, and nothing of another company (ENVELOPE_NOT_FOUND).

Two rate limits apply:

  • 60 requests a minute per key, across all the envelope routes.
  • 600 documents a minute per company, shared with the document API and the HTTP trigger. A create counts one per document in it.

Past either one the answer is 429 with RATE_LIMITED.

  1. POST /api/v1/envelopes stores your documents and answers 201 at once, with the envelope still a draft and each document prepareState: "pending".
  2. AutomaDoc prepares every document: Word, Excel and PowerPoint files become PDF, and the text is searched for your anchors and [[…]] tags. A document still pending after 30 minutes fails as timeout.
  3. Once the last document is ready, the fields from anchors and tags are placed and, with send: true, the envelope is sent. Email recipients whose turn it is get their invitation.
  4. Read GET /api/v1/envelopes/:id to follow it. If it could not be sent, it stays a draft and sendError says why.

The public API has no separate send call: an envelope created without send: true stays a draft. A draft that could not be sent cannot be retried through the API either; create a new envelope. Drafts nobody changes for 30 days are deleted.

POST https://api.automadoc.cc/api/v1/envelopes

Send the body as JSON (Content-Type: application/json, at most 14 MB), or as multipart/form-data with an envelope part holding the same JSON plus one part per file (at most 26 MB for the whole request).

Field Required What it does
title yes Shown to the signers and in the emails. Up to 200 characters.
message no A note to the recipients, up to 1,000 characters.
documents yes 1 to 10 documents, in order (below).
recipients yes 1 to 20 recipients (below).
fields no Fields placed by coordinates (below). At most 500.
anchors no Fields placed relative to text in the documents (below). At most 50.
autoTags no true places fields from [[…]] tags written in the documents (below).
send no true sends the envelope as soon as the documents are prepared and the fields placed. Otherwise it stays a draft.
locale no The language of the emails and the signing page: en, zh, id, es, vi, th or ja. Anything else is ignored.
timezone no An IANA time zone (Asia/Jakarta) for dates written on the documents and the certificate. Default UTC.
expiryDays no Days from sending until the envelope expires: 1 to 120, default 30.
reminders no { "everyDays": 3, "max": 3 } (the default; everyDays 1 to 30, max 0 to 10), or false for none.
appendCertificate no Default true: each signed PDF ends with the certificate of completion. The certificate is always downloadable on its own too.

Each document is exactly one of:

Field What it is
base64 The file’s bytes in base64 (a data: prefix is accepted). All base64 documents of a request may total at most 10 MB once decoded; send larger files as multipart.
file The name of a part of the multipart request that holds the file.
generationId A completed document AutomaDoc generated for your company (the generationId of the document API, or any other generated document still kept). Its file is copied into the envelope.

name is optional: it defaults to the part’s file name, the generated file’s name, or “Document 1”, “Document 2”. A trailing .pdf, .docx, .xlsx or .pptx is dropped. Files may be PDF, Word, Excel or PowerPoint, recognised by their content, never by their name. Each file may be at most 25 MB, and an envelope’s files at most 50 MB together.

Field Required What it does
key yes Your own name for this recipient (client), used by fields and anchors and returned in every response. 1 to 60 letters, digits, _, - or ., unique in the request.
role yes signer (fills fields and signs) or cc (receives the signed result).
name yes Up to 120 characters.
email with reach: "email" Where the invitation is sent. Optional for a link recipient.
reach no "email" (default): AutomaDoc emails the invitation when it is this recipient’s turn. "link": nothing is mailed, and the create response returns a signingUrl for you to deliver.
routingOrder no 1 to 100, default 1. Recipients with the same number sign in parallel; a higher number waits until every lower one has finished.
accessCode no 6 to 128 characters the recipient must type before they see the documents. Five wrong codes lock the link. Pass it to the recipient yourself, not in the same message as the link.
slot no With autoTags: the role name used in the tags (Client) this recipient fills.
Field Required What it does
document yes The document’s index in documents, from 0.
recipient yes A recipient key. Only signers have fields.
type yes signature, initials, name, date_signed, text, checkbox, company or email.
page yes The page, from 1.
x, y, w, h yes Position and size in points (1/72 inch), measured from the top-left corner of the page as it is displayed (after any rotation). A field must be at least 8 points wide and high and lie inside the page.
required no Default true.
label no A hint shown to the signer, up to 100 characters.
options no For text fields: maxLength (1 to 1,000), validate ("number" or "email"), fontSize (6 to 72, shrinks to fit).

name and email start with the recipient’s name and address, which the signer can change; date_signed is filled with the signing date, written in the envelope’s time zone. Pages and positions are checked against the prepared documents when the envelope is sent (field_bad_page, field_off_page), since a Word file has no pages until it is converted.

An anchor places a field relative to text already in the document, so you do not need coordinates:

Field Required What it does
anchor yes The text to find, up to 200 characters. Matching is exact and case-sensitive; any run of spaces or line breaks matches any other.
recipient yes A recipient key.
type yes A field type, as above.
occurrence no "all" (default: a field at every match, at most 200), or n for the n-th match only, counted across all the envelope’s documents in reading order.
offsetX, offsetY no Points from the top-left of the matched text to the top-left of the field (-2,000 to 2,000, default 0). Negative offsetY moves up.
w, h no The field’s size in points (8 to 1,000). Default: signature 160×48, initials 64×40, checkbox 14×14, date 110×20, email 180×20, other text 160×20.
required, label no As for fields by coordinates.

A field that would run off the page is moved back onto it. An anchor that matches nothing makes no field, which usually shows up as signer_without_fields in sendError.

With autoTags: true, tags written in the documents become fields for the recipient whose slot matches the tag’s role (exactly, case kept):

[[sign:Client]] [[initials:Client]] [[name:Client]] [[date:Client]]
[[text:Client:PO number]] [[check:Client]] [[company:Client]] [[email:Client]]
[[sign:Client;w=180;h=50]] [[text:Client:Notes;optional]]

The field’s top-left corner is the tag’s top-left corner, so the field covers the tag. A tag whose role no recipient fills makes no field.

201 Created with the envelope. Right after a create it is a draft whose documents are still being prepared:

{
"id": "env_01JAB3K9Q7M2X8R4T6V0W1Y2Z3",
"status": "draft",
"finishing": false,
"finalizeFailed": false,
"title": "Service agreement ACME-2026-114",
"createdAt": 1792290600000,
"sentAt": null,
"expiresAt": null,
"completedAt": null,
"documents": [
{
"id": "doc_01JAB3K9RA5C7E9G1H3J5K7M9N",
"name": "Service agreement",
"prepareState": "pending",
"prepareError": null,
"pageCount": null,
"originalSha256": "3b7e0c…",
"preparedSha256": null,
"finalSha256": null,
"deliveredSha256": null
}
],
"recipients": [
{
"id": "rcp_01JAB3K9R2B4D6F8H0J2K4M6P8",
"key": "client",
"role": "signer",
"name": "Dana Lee",
"email": "dana@example.com",
"status": "created",
"routingOrder": 1,
"viewedAt": null,
"completedAt": null,
"declineReason": null
}
],
"auditHead": "a41f9d…",
"sendError": null
}

A recipient with reach: "link" also has a signingUrl (https://sign.automadoc.cc/#/…) in this response only: no later read returns it, so store it now. The link starts working when the envelope is sent. Each email invitation and reminder carries a fresh link, so a link recipient is never reminded by email.

GET https://api.automadoc.cc/api/v1/envelopes/{envelopeId}

Answers the same shape as the create, as of now. Poll it every few seconds while the documents prepare; once the envelope is out, polling every few minutes is plenty.

status Meaning
draft Not sent: documents preparing, send not asked, or sendError says why it could not go.
sent Out for signature.
completed Everyone signed and the signed files are ready.
declined A signer declined; their declineReason is on their recipient.
voided You voided it.
expired expiresAt passed before everyone signed.

finishing: true (with status: "sent") means everyone has signed and the signed PDFs are being made. finalizeFailed: true means they could not be made after every retry: the signatures are kept and our team was alerted.

Recipients go created (not yet their turn), sent, viewed, then completed or declined. A cc recipient is sent from the start.

Each document carries the SHA-256 of every stage: originalSha256 (your file), preparedSha256 (the PDF everyone saw and signed), finalSha256 (stamped with the signatures) and deliveredSha256 (the file you download: stamped, plus the certificate when appended). auditHead is the hash of the last event in the envelope’s audit trail. Anyone can check a delivered file with POST https://api.automadoc.cc/api/verify and { "sha256": "…" } (lower-case hex of the whole file), which answers whether it matches a completed envelope.

GET https://api.automadoc.cc/api/v1/envelopes?status=completed&since=1792290600000&limit=50
Query What it does
status draft, sent, completed, declined, voided or expired.
since Only envelopes updated at or after this time (Unix ms).
limit 1 to 100, default 25.
cursor The nextCursor of the previous page.

The answer is { "envelopes": [ … ], "nextCursor": "…" }, newest first; nextCursor is null on the last page. key is null for recipients of envelopes made in the portal.

GET https://api.automadoc.cc/api/v1/envelopes/{envelopeId}/documents/{documentId}/signed
GET https://api.automadoc.cc/api/v1/envelopes/{envelopeId}/certificate
GET https://api.automadoc.cc/api/v1/envelopes/{envelopeId}/combined

signed is one signed document; certificate is the certificate of completion on its own; combined is every signed document in one PDF (with the certificate at the end when appended), made only for envelopes of two or more documents. These work once the envelope is completed: before, they answer 409 with DOCUMENT_NOT_FOUND.

The answer is a short-lived link, not the file:

{
"url": "https://api.automadoc.cc/api/esign-files/env_01JAB3K9Q7M2X8R4T6V0W1Y2Z3/final/doc_01JAB3K9RA5C7E9G1H3J5K7M9N.pdf?e=…&d=a&n=…&s=…",
"filename": "Service agreement.pdf",
"expiresAt": 1792306800000,
"sha256": "e5a01c…"
}

Fetch url within 15 minutes; it needs no key. Ask again for a fresh one. sha256 is the file’s fingerprint (for signed, the document’s deliveredSha256). Every download is recorded in the audit trail. Signed files of a completed envelope are kept until someone deletes them.

POST https://api.automadoc.cc/api/v1/envelopes/{envelopeId}/void
{ "reason": "Replaced by version 2" }

Stops a sent envelope: the links stop working, and recipients who had already been sent it are told by email. reason is required (up to 500 characters). Answers the envelope, now voided. Only a sent envelope that is still open can be voided.

POST https://api.automadoc.cc/api/v1/envelopes/{envelopeId}/recipients/{recipientId}/remind

recipientId is the recipient’s id (rcp_…), not your key. Emails the recipient a fresh link at once; the link in earlier emails stops working. Only for an email recipient whose turn it is, at most once every 10 minutes. Answers { "remindedAt": 1792300000000, "channel": "email" }. Automatic reminders follow the envelope’s reminders setting without any call.

Create an envelope with one signer, place the signature next to the text “Client signature:” and the date next to “Date:”, and send it. The JSON goes in the envelope part and the PDF in a part named contract:

Terminal window
cat > envelope.json <<'EOF'
{
"title": "Service agreement ACME-2026-114",
"message": "Please review and sign by Friday.",
"timezone": "Asia/Jakarta",
"documents": [{ "name": "Service agreement", "file": "contract" }],
"recipients": [
{ "key": "client", "role": "signer", "name": "Dana Lee", "email": "dana@example.com" }
],
"anchors": [
{ "anchor": "Client signature:", "recipient": "client", "type": "signature", "offsetX": 110, "offsetY": -10 },
{ "anchor": "Date:", "recipient": "client", "type": "date_signed", "offsetX": 40, "occurrence": 1 }
],
"send": true
}
EOF
curl -X POST 'https://api.automadoc.cc/api/v1/envelopes' \
-H "X-Webhook-API-Key: $AUTOMADOC_KEY" \
-F 'envelope=<envelope.json' \
-F 'contract=@contract.pdf;type=application/pdf'

Follow it until status is sent (or sendError is set), then until it is completed:

Terminal window
curl -s 'https://api.automadoc.cc/api/v1/envelopes/ENVELOPE_ID' \
-H "X-Webhook-API-Key: $AUTOMADOC_KEY"

Once it is completed, get the signed document’s link and download it:

Terminal window
url=$(curl -s 'https://api.automadoc.cc/api/v1/envelopes/ENVELOPE_ID/documents/DOCUMENT_ID/signed' \
-H "X-Webhook-API-Key: $AUTOMADOC_KEY" | jq -r .url)
curl -s -o signed.pdf "$url"

The same create as JSON puts the file in base64 instead: "documents": [{ "name": "Service agreement", "base64": "JVBERi0xLjcK…" }].

Node.js 18 or later. Run with AUTOMADOC_KEY=amk_… node sign.mjs:

import { readFile, writeFile } from 'node:fs/promises'
import { createHash } from 'node:crypto'
const API = 'https://api.automadoc.cc'
const KEY = process.env.AUTOMADOC_KEY
async function call(method, path, body) {
const res = await fetch(API + path, {
method,
headers: body ? { 'X-Webhook-API-Key': KEY, 'Content-Type': 'application/json' } : { 'X-Webhook-API-Key': KEY },
body: body ? JSON.stringify(body) : undefined,
})
const json = await res.json()
if (!res.ok) throw new Error(`${res.status} ${json.code}: ${json.error}`)
return json
}
const pdf = await readFile('contract.pdf')
let envelope = await call('POST', '/api/v1/envelopes', {
title: 'Service agreement ACME-2026-114',
documents: [{ name: 'Service agreement', base64: pdf.toString('base64') }],
recipients: [{ key: 'client', role: 'signer', name: 'Dana Lee', email: 'dana@example.com' }],
anchors: [{ anchor: 'Client signature:', recipient: 'client', type: 'signature', offsetX: 110, offsetY: -10 }],
send: true,
})
// The documents are prepared and the fields placed, then the envelope is sent.
while (envelope.status === 'draft' && !envelope.sendError) {
await new Promise((resolve) => setTimeout(resolve, 2000))
envelope = await call('GET', `/api/v1/envelopes/${envelope.id}`)
}
if (envelope.sendError) throw new Error(`Not sent: ${JSON.stringify(envelope.sendError)}`)
console.log(`${envelope.id} is ${envelope.status}`)
// Later (a scheduled job, say): download every signed document of a completed envelope.
export async function downloadSigned(envelopeId) {
const current = await call('GET', `/api/v1/envelopes/${envelopeId}`)
if (current.status !== 'completed') return false
for (const doc of current.documents) {
const link = await call('GET', `/api/v1/envelopes/${envelopeId}/documents/${doc.id}/signed`)
const bytes = Buffer.from(await (await fetch(link.url)).arrayBuffer())
if (createHash('sha256').update(bytes).digest('hex') !== link.sha256) throw new Error('Download damaged')
await writeFile(`${doc.id}.pdf`, bytes)
}
return true
}

Errors are JSON: { "code": "…", "error": "English text" }, with path naming the part of the request at fault (recipients[1].email) when there is one.

HTTP code When
400 INVALID_REQUEST The request is not valid; see path and error.
401 API_KEY_MISSING No key in X-Webhook-API-Key or Authorization.
403 API_KEY_INVALID The key is unknown or revoked, or it is a template’s own key.
403 ESIGN_SEND_BLOCKED Remind: sending is paused for your company while a report about its emails is reviewed. Contact support.
404 ENVELOPE_NOT_FOUND No such envelope in your company.
404 RECIPIENT_NOT_FOUND Remind: no such recipient in this envelope.
404 DOCUMENT_NOT_FOUND Download: no such document, or no such file (a combined file for a one-document envelope).
404 GENERATION_NOT_FOUND A generationId that is not a generated document of your company.
409 GENERATION_NOT_COMPLETED The generated document is not completed, or no longer kept.
409 DOCUMENT_NOT_FOUND Download before the envelope is completed.
409 ENVELOPE_NOT_DRAFT Void or remind on an envelope that was never sent.
409 ENVELOPE_CLOSED Void or remind on a completed, declined, voided or expired envelope.
409 ENVELOPE_FINISHING Void or remind after everyone signed, while the signed files are being made.
409 NOT_ALLOWED Remind a recipient whose turn it is not, or a link recipient.
410 ENVELOPE_CLOSED Download after the envelope’s files were deleted.
413 FILE_TOO_LARGE A file over 25 MB, or a multipart request over 26 MB.
413 ENVELOPE_TOO_LARGE The base64 documents total over 10 MB, or the files over 50 MB.
413 INVALID_REQUEST A JSON body over 14 MB.
415 UNSUPPORTED_FILE A file that is not a PDF, Word, Excel or PowerPoint file.
429 RATE_LIMITED Over 60 requests a minute for the key, or 600 documents a minute for the company.
429 ESIGN_SEND_RATE_LIMITED Remind: this recipient was reminded less than 10 minutes ago.
502 ESIGN_WORKER_UNAVAILABLE Remind: the reminder could not be delivered.
503 ESIGN_WORKER_UNSUPPORTED Documents cannot be prepared for signature right now. Try again later; nothing was created.

A create refused while its documents are being stored deletes the draft and its files, so nothing half-made is left.

With send: true, sending happens after the create has answered, so its refusals arrive in sendError of the envelope (which stays a draft), not as an HTTP status:

sendError.code Meaning
SEND_PROBLEMS The envelope is not complete; problems lists why (below).
QUOTA_EXCEEDED The monthly allowance and every document pack are used up (see what it costs).
ESIGN_SEND_RATE_LIMITED Free: your company already sent 3 envelopes in the last hour. On any plan: more than 10 sends in one minute.
ESIGN_RECIPIENT_CAP This send would pass the recipients a day your company may reach (below).
ESIGN_SEND_BLOCKED Sending is paused for your company while a report about its emails is reviewed. Contact support.
ESIGN_EMAIL_UNAVAILABLE Email cannot be sent for this envelope. Nothing was sent or charged; recipients with reach: "link" can still be used.
ESIGN_EMAIL_UNVERIFIED The person who created the key has no verified email address.
ESIGN_ALREADY_PENDING This generated document is already out for signature in another envelope.
INVALID_REQUEST The tags and anchors together made more than 500 fields, or something unexpected went wrong.

Each problem is { "code": "…" }, with documentId, recipientId or fieldId when it is about one of them (ids, not your keys):

Problem Meaning
document_failed A document could not be prepared; its prepareError says why (below).
too_many_pages More than 300 pages across the documents.
envelope_too_large The files total more than 50 MB, or the prepared PDFs more than 100 MB.
no_signer No recipient has the role signer.
signer_without_fields A signer has no field: an anchor matched nothing, or a tag’s role had no slot.
recipient_missing_email An email recipient has no address.
recipient_role_unavailable A role other than signer or cc.
too_many_fields More than 500 fields.
field_for_non_signer A field was given to a cc recipient.
field_bad_page A field’s page is past the end of its document.
field_off_page A field runs off its page, or is smaller than 8 points.
field_type_unavailable A field type other than the eight listed above.

A document’s prepareError is one of pdf_encrypted (the PDF is password-protected), file_too_large (its prepared PDF would pass 50 MB), too_many_pages, unsupported_file, invalid_file (the file is damaged), conversion_failed, source_unavailable, timeout or internal.

Limit Value
Documents per envelope 10
One file 25 MB
Files of one envelope together 50 MB
One prepared document (the PDF everyone signs) 50 MB
Prepared documents of one envelope together 100 MB
Pages across an envelope’s documents 300
Recipients per envelope 20
Fields per envelope 500
Anchors per request 50, each matching at most 200 times
JSON request body 14 MB, with at most 10 MB of base64 documents
Multipart request 26 MB
Expiry 1 to 120 days after sending, default 30
Reminders every 1 to 30 days, at most 10; default every 3 days, 3 times
Wrong access codes before a link locks 5
Download links 15 minutes
Drafts deleted after 30 days without a change
Files of declined, voided and expired envelopes deleted 90 days after closing

To send more than 26 MB of files, add them by generationId, which does not travel in the request.

Sending caps. Without Pro and without a Business seat, a company sends at most 3 envelopes an hour and reaches at most 20 recipients a day (5 a day in the account’s first 24 hours). With Pro or a Business seat, it reaches up to 1,000 recipients a day. Every recipient counts, cc and link recipients included, over a rolling 24 hours. Every company sends at most 10 envelopes a minute.

  • A sent envelope uses one document from your allowance, however many documents and recipients it holds. It is charged when it is sent and not given back if it is later voided, declined or expired. A draft costs nothing.
  • Documents AutomaDoc generated are free to send the first time: an envelope whose documents all come from generationId costs nothing, unless one of them was already sent in another envelope; then it costs one document. An envelope that mixes generated and uploaded files costs one.
  • What pays. An envelope sent with a company key is automated, like the document API: free with Pro (or a trial); otherwise counted against your Business seats’ automation allowance first, then the free monthly allowance, then your document packs. When all are used up, sendError is QUOTA_EXCEEDED. A Starter seat belongs to a person and does not cover API sends.

The sending caps above apply on every plan.