DocuSign
DocuSign collects legally binding signatures on a document. Here that is /v1/esign — 13 operations, a signing link that carries its own token, and an audit trail you can read.
DocuSign sends a document to people and collects their signatures. /v1/esign
(13 operations) is the same sequence: create a document, add recipients and
fields, send it, and read the audit trail when it is done.
The shape that differs: the signer's link is the credential. A recipient does
not have an account here. GET /v1/esign/o/{org}/sign/{token} is the whole
session — the token names the org, the document and the recipient, and the
signing routes carry no other authentication.
Start here
Three calls: mint a key, upload the PDF, add the person who signs it.
# 1. mint a key — sk- belongs on a server, pk- is safe in a browser
curl -sS -X POST https://api.hanzo.ai/v1/account/keys \
-H "Authorization: Bearer $HANZO_SESSION" \
-H 'Content-Type: application/json' \
-d '{"type":"secret"}'
# 2. upload the PDF — 201, and the document is in DRAFT
ID=$(curl -sS -X POST https://api.hanzo.ai/v1/esign/documents \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"title\":\"Mutual NDA\",\"pdfBase64\":\"$(base64 < nda.pdf | tr -d '\n')\"}" \
| jq -r .id)
# 3. add the signer — the response carries their token
curl -sS -X POST "https://api.hanzo.ai/v1/esign/documents/$ID/recipients" \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","name":"Dana Lee","role":"SIGNER"}'You have a DRAFT document and one recipient, and step 3 answered a token —
minted before anything is sent, and the entire credential the signing endpoint
accepts. That is the shape difference from DocuSign in one call: the signer has
no account, only the link built from that token.
Core capabilities
| Capability | What it does | Operations |
|---|---|---|
/v1/esign | Upload a PDF, add recipients and fields, send, read the audit trail | 13 |
/v1/dataroom | Holds the documents and the links that share them — where a DocuSign template's reusable shape lives | 26 |
/v1/compliance | Subjects, verifications and accreditation decisions — the identity check you run before handing over a link | 17 |
Nouns
| DocuSign | Hanzo |
|---|---|
| Account | Your org, taken from the validated key |
| Envelope | Document — POST /v1/esign/documents |
| Document (inside an envelope) | The document itself. One per envelope |
| Recipient / Signer | POST /v1/esign/documents/{id}/recipients |
| Tab (SignHere, DateSigned, Text) | Field — POST /v1/esign/documents/{id}/fields |
| Routing order | signingOrder on the recipient |
| Send envelope | POST /v1/esign/documents/{id}/send |
| Signing ceremony URL | GET /v1/esign/o/{org}/sign/{token} |
| Certificate of completion | GET /v1/esign/documents/{id}/audit |
| Completed PDF | GET /v1/esign/documents/{id}/download |
| Decline to sign | POST /v1/esign/o/{org}/sign/{token}/reject |
| Template library | Hanzo Dataroom — /v1/dataroom (26), documents and the links that share them |
The call
DocuSign, creating and sending:
curl -sS -X POST \
"https://demo.docusign.net/restapi/v2.1/accounts/$ACCT/envelopes" \
-H "Authorization: Bearer $DS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"emailSubject":"Please sign","status":"sent","documents":[…],"recipients":{…}}'Hanzo — the same thing, as four calls that each do one thing:
# 1. the document — title and the base64 PDF, both required
ID=$(curl -sS -X POST https://api.hanzo.ai/v1/esign/documents \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"title\":\"Services Agreement\",\"pdfBase64\":\"$(base64 < contract.pdf | tr -d '\n')\"}" \
| jq -r .id)
# 2. who signs it — the response carries the recipient id and their token
RCPT=$(curl -sS -X POST "https://api.hanzo.ai/v1/esign/documents/$ID/recipients" \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","name":"A Signer","signingOrder":1}' \
| jq -r .id)
# 3. where they sign — a field is placed against that recipient
curl -sS -X POST "https://api.hanzo.ai/v1/esign/documents/$ID/fields" \
-H "Authorization: Bearer $HANZO_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"recipientId\":\"$RCPT\",\"type\":\"SIGNATURE\",\"page\":1,\"positionX\":120,\"positionY\":640}"
# 4. send
curl -sS -X POST "https://api.hanzo.ai/v1/esign/documents/$ID/send" \
-H "Authorization: Bearer $HANZO_API_KEY"A field's page and coordinates are the caller's numbers, kept as given — the route does not round them, so a template that positions fields fractionally ports without drift.
What does not carry
Templates live in the Dataroom, not on this API. DocuSign templates hold
recipients, tabs and routing so an envelope can be created from one. Hanzo
Dataroom (dataroom.hanzo.ai) is where documents and their reusable shapes are
kept — /v1/dataroom (26) carries the datarooms, the documents and the links
that share them. What /v1/esign publishes is the signing sequence itself, and it
has no template noun: driving it from the API means posting the field list per
document, which is what a template is once it stops going stale.
No bulk send. One document, one set of recipients. A hundred contracts is a hundred sequences, which is a loop rather than a feature.
No embedded signing ceremony. DocuSign's JS embeds the ceremony in your page with a recipient view URL. The signing link here is a page we serve.
Identity is verified somewhere else, not in the ceremony. DocuSign gates a
signer with SMS, an access code or an ID check inside the envelope. The token in
the link is the whole authentication here. Proving who someone is has its own
capability — /v1/compliance carries subjects, records and accreditation
decisions — so the check is a step you run before you hand the link over, rather
than a setting on the document.
No connect webhooks yet. DocuSign pushes envelope events to a listener. Poll
GET /v1/esign/documents/{id} for status, or subscribe on /v1/webhook if the
event you need is already published there.
How is this guide?
Lago
Lago meters usage and turns it into invoices. Here /v1/billing raises and collects the invoice, /v1/usage takes the samples, and /v1/pricing is the rate card.
Carta
Carta keeps who owns what in a company. Here that is /v1/captable — 31 operations over stakeholders, share classes, SAFEs, options and rounds, with the summary derived rather than stored.