squiggli Get a free API key
Reference

API reference

Every endpoint of the squiggli API, with parameters, bodies and responses.

Base URL https://squiggli.billy-965.workers.dev/v1. Send Authorization: Bearer sq_live_... (or sq_test_...) and JSON bodies. Objects come back as { "id", "object", ... }, lists as { "object": "list", "data", "has_more", "next_cursor" }, and errors as { "error": { "code", "message" } }. The machine-readable version is /openapi.json.

Envelopes

POST/v1/envelopesCreate an envelope

A draft, or sent at once with send: true. Documents are PDFs (file_base64, file_url) or templates (template_id + variables). Live sends: 402 card_required (with add_card_url) when the business has no card and no free documents left; 403 squiggli_not_enabled without a subscription.

Body

FieldTypeDescription
title requiredstringWhat signers see, e.g. "Harbour Lane lease, unit 4".
messagestringA note to signers, shown in the email and on the signing page.
documentsarray of object
documents[].namestringFile name shown to signers. Defaults to the template name or "Document 1".
documents[].file_base64stringA PDF, base64-encoded. Up to 10 MB.
documents[].file_urlstringAn https link squiggli downloads the PDF from (up to 10 MB).
documents[].template_idstringRender this template (tpl_...) as the document.
documents[].variablesobjectValues for the template's {{variables}}, e.g. {"client.name": "Ava Chen", "rent": "$650 a week"}.
template_idstringShortcut for documents: [{ template_id, variables }].
variablesobjectValues for the template's {{variables}}, e.g. {"client.name": "Ava Chen", "rent": "$650 a week"}.
signers requiredarray of object
signers[].name requiredstring
signers[].emailstringRequired when delivery is email.
signers[].rolestringThe template role this signer fills, e.g. "tenant". Without roles, signers fill the template's roles in order.
signers[].delivery"email" | "link"email: squiggli emails the signing link and reminders. link: no emails; show signing_url yourself or embed it.
signers[].orderintegerSigning order when signing_order is sequential (1 signs first). Defaults to list order.
signers[].access_codestringA code the signer must enter before they can see the document. Give it to them another way (phone, SMS, in person): it identifies them by more than the link. Recommended for delivery "link".
fieldsarray of object
fields[].signer requiredinteger or stringWhich signer fills it: their index in signers[] (0 is the first), their role, or their email.
fields[].documentintegerIndex into documents[]. Default 0.
fields[].type required"signature" | "initials" | "date_signed" | "name" | "email" | "text" | "checkbox"
fields[].page requiredinteger1 is the first page.
fields[].x requirednumberPDF points from the left edge of the page (A4 is 595 x 842 points).
fields[].y requirednumberPDF points from the top edge of the page.
fields[].widthnumberPoints. Defaults by type: signature 200, initials 60, checkbox 14, others 160.
fields[].heightnumberPoints. Defaults by type: signature 50, initials 32, checkbox 14, others 22.
fields[].requiredbooleanDefault true, except checkboxes.
fields[].labelstring
fields[].keystringYour own name for the field. Returned with its value in GET /v1/envelopes/{id}.
fields[].valuestringPrefill a text field. The signer can change it.
signing_order"parallel" | "sequential"parallel: everyone gets it at once. sequential: one after another, by order.
deadlinestringSigning deadline (ISO 8601). After it the envelope expires.
deadline_daysintegerDeadline as days from sending, instead of deadline.
remindersfalse or objectAutomatic reminder emails. false turns them off.
reminders.every_daysinteger or nullRemind unsigned signers every N days. null for none. Default 3.
reminders.before_deadline_daysarray of integerAlso remind this many days before the deadline. Default [1].
reminders.maxintegerAt most this many reminders per signer. Default 5.
testbooleanTest envelope: free and unlimited, watermarked "TEST - NOT LEGALLY BINDING". Always true with a sq_test_ key.
whitelabelbooleanNo squiggli name or footer anywhere signers look: your business's name and colour only. $1.50 instead of $1.00.
senderobjectWho signers are told sent it ("Ava Chen sent you..."), and who gets the decline and completed emails. Defaults to the business.
sender.name requiredstring
sender.emailstring
metadataobjectYour own key-value data (up to 20 keys), e.g. {"job_id": "J-1042"}. Returned with the envelope and in webhooks.
redirect_urlstringWhere the signing page sends a signer after they sign.
sendbooleantrue sends it now. false keeps a draft to send with POST /v1/envelopes/{id}/send.

Send an Idempotency-Key header so a retry can't do it twice.

Returns 201: The envelope.

GET/v1/envelopesList envelopes

Newest first.

ParameterInDescription
statusqueryComma-separated statuses
testqueryboolean
template_idquerystring
metadata[key]queryMatch a metadata value, e.g. metadata[job_id]=J-1042
limitqueryinteger
cursorquerynext_cursor from the previous page

Returns 200: A page of envelopes.

GET/v1/envelopes/{id}Get an envelope

Everything: documents and page sizes, signers with their status, opens and links, fields and values, deadline, reminders, and download links once signed.

ParameterInDescription
id requiredpathEnvelope id (env_...)

Returns 200: The envelope.

PATCH/v1/envelopes/{id}Update an envelope

Deadline, reminders, metadata and redirect_url any time it is open; title and message while it is a draft.

ParameterInDescription
id requiredpathEnvelope id (env_...)

Body

FieldTypeDescription
titlestring
messagestring or null
deadlinestring or nullMove or clear the deadline. Works on sent envelopes too.
remindersfalse or objectAutomatic reminder emails. false turns them off.
reminders.every_daysinteger or nullRemind unsigned signers every N days. null for none. Default 3.
reminders.before_deadline_daysarray of integerAlso remind this many days before the deadline. Default [1].
reminders.maxintegerAt most this many reminders per signer. Default 5.
metadataobjectYour own key-value data (up to 20 keys), e.g. {"job_id": "J-1042"}. Returned with the envelope and in webhooks.
redirect_urlstring or null

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: The envelope.

DELETE/v1/envelopes/{id}Delete a draft

Only drafts. Void sent envelopes instead.

ParameterInDescription
id requiredpathEnvelope id (env_...)

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: Deleted.

POST/v1/envelopes/{id}/sendSend a draft

Emails the signers whose turn it is (sequential envelopes go one at a time).

ParameterInDescription
id requiredpathEnvelope id (env_...)

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: The envelope.

POST/v1/envelopes/{id}/voidVoid (cancel) an envelope

Signers are emailed that it was cancelled.

ParameterInDescription
id requiredpathEnvelope id (env_...)

Body

FieldTypeDescription
reasonstringShown to signers in the cancellation email.

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: The envelope.

POST/v1/envelopes/{id}/remindRemind signers

A fresh link by email to signers whose turn it is, at most hourly per signer.

ParameterInDescription
id requiredpathEnvelope id (env_...)

Body

FieldTypeDescription
signer_idsarray of stringDefault: every signer whose turn it is and who has not signed.

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: Who was reminded and who was skipped.

GET/v1/envelopes/{id}/eventsAudit trail

Every event in order, with IP address and device for signer actions.

ParameterInDescription
id requiredpathEnvelope id (env_...)

Returns 200: Events.

GET/v1/envelopes/{id}/documents/{documentId}Download a document as sent

The PDF signers see.

ParameterInDescription
id requiredpathEnvelope id (env_...)
documentId requiredpathDocument id (doc_...)

Returns 200: PDF (a PDF).

GET/v1/envelopes/{id}/signed.pdfDownload the signed PDF

Every document with every signature and value, once status is signed.

ParameterInDescription
id requiredpathEnvelope id (env_...)

Returns 200: Signed PDF (a PDF).

GET/v1/envelopes/{id}/certificate.pdfDownload the completion certificate

Who signed, when, from where, and the audit trail.

ParameterInDescription
id requiredpathEnvelope id (env_...)

Returns 200: Certificate PDF (a PDF).

Templates

GET/v1/templatesList templates

Returns 200: Templates.

POST/v1/templatesCreate a template

Blocks (laid out by squiggli on A4, with {{variables}}) or a PDF with fields by role.

Body

FieldTypeDescription
namestringRequired unless you use a starter (its name is the default).
descriptionstring
starterstringStart from a ready-made design (GET /v1/templates/starters), e.g. "statement-of-work". Anything else you send overrides it.
themeobjectHow the document looks. Every setting is optional.
theme.font"helvetica" | "inter" | "roboto" | "poppins" | "montserrat" | "open-sans" | "lora" | "merriweather" | "playfair-display" | "instrument-sans" | "familjen-grotesk"Body font. Default helvetica.
theme.heading_font"helvetica" | "inter" | "roboto" | "poppins" | "montserrat" | "open-sans" | "lora" | "merriweather" | "playfair-display" | "instrument-sans" | "familjen-grotesk"Heading and cover title font. Default: the body font.
theme.text_colorstringBody text. Default #141a2e.
theme.heading_colorstringHeadings. Default: the text colour.
theme.accent_colorstringTable header rules, callout tint, and the cover when it has no background_color.
theme.font_sizenumberBody size in points. Default 11.
theme.line_heightnumberDefault 1.45.
theme.page_size"A4" | "Letter"Default A4.
theme.marginnumberPage margin in points. Default 56.
theme.page_numbersbooleanDefault true. Never on the cover.
theme.header_logobooleanThe business's logo at the top right of every page except the cover.
blocksarray of objectA block document: squiggli lays it out on the page. Text can use {{variables}}.
blocks[].type required"heading"
blocks[].text requiredstring
blocks[].level1 or 2 or 3
blocks[].colorstring
blocks[].align"left" | "center" | "right"
file_base64stringOr a PDF (base64) with fields placed on it.
file_urlstring
fieldsarray of objectFields on the PDF, by role. Only with file_base64 or file_url.
fields[].type required"signature" | "initials" | "date_signed" | "name" | "email" | "text" | "checkbox"
fields[].page requiredinteger1 is the first page.
fields[].x requirednumberPDF points from the left edge of the page (A4 is 595 x 842 points).
fields[].y requirednumberPDF points from the top edge of the page.
fields[].widthnumberPoints. Defaults by type: signature 200, initials 60, checkbox 14, others 160.
fields[].heightnumberPoints. Defaults by type: signature 50, initials 32, checkbox 14, others 22.
fields[].requiredbooleanDefault true, except checkboxes.
fields[].labelstring
fields[].keystringYour own name for the field. Returned with its value in GET /v1/envelopes/{id}.
fields[].role requiredstringSigner role, e.g. "tenant" or "landlord".
rolesarray of objectLabels for the roles the fields use. Worked out from the fields when left out.
roles[].key requiredstringSigner role, e.g. "tenant" or "landlord".
roles[].labelstring

Send an Idempotency-Key header so a retry can't do it twice.

Returns 201: The template.

POST/v1/templates/previewPreview blocks

Renders unsaved blocks to a PDF.

Body

FieldTypeDescription
blocksarray of objectA block document: squiggli lays it out on the page. Text can use {{variables}}.
blocks[].type required"heading"
blocks[].text requiredstring
blocks[].level1 or 2 or 3
blocks[].colorstring
blocks[].align"left" | "center" | "right"

Returns 200: Preview PDF (a PDF).

GET/v1/templates/{id}Get a template

ParameterInDescription
id requiredpathTemplate id (tpl_...)

Returns 200: The template.

PATCH/v1/templates/{id}Update a template

Send only what changes.

ParameterInDescription
id requiredpathTemplate id (tpl_...)

Body

FieldTypeDescription
namestringRequired unless you use a starter (its name is the default).
descriptionstring
starterstringStart from a ready-made design (GET /v1/templates/starters), e.g. "statement-of-work". Anything else you send overrides it.
themeobjectHow the document looks. Every setting is optional.
theme.font"helvetica" | "inter" | "roboto" | "poppins" | "montserrat" | "open-sans" | "lora" | "merriweather" | "playfair-display" | "instrument-sans" | "familjen-grotesk"Body font. Default helvetica.
theme.heading_font"helvetica" | "inter" | "roboto" | "poppins" | "montserrat" | "open-sans" | "lora" | "merriweather" | "playfair-display" | "instrument-sans" | "familjen-grotesk"Heading and cover title font. Default: the body font.
theme.text_colorstringBody text. Default #141a2e.
theme.heading_colorstringHeadings. Default: the text colour.
theme.accent_colorstringTable header rules, callout tint, and the cover when it has no background_color.
theme.font_sizenumberBody size in points. Default 11.
theme.line_heightnumberDefault 1.45.
theme.page_size"A4" | "Letter"Default A4.
theme.marginnumberPage margin in points. Default 56.
theme.page_numbersbooleanDefault true. Never on the cover.
theme.header_logobooleanThe business's logo at the top right of every page except the cover.
blocksarray of objectA block document: squiggli lays it out on the page. Text can use {{variables}}.
blocks[].type required"heading"
blocks[].text requiredstring
blocks[].level1 or 2 or 3
blocks[].colorstring
blocks[].align"left" | "center" | "right"
file_base64stringOr a PDF (base64) with fields placed on it.
file_urlstring
fieldsarray of objectFields on the PDF, by role. Only with file_base64 or file_url.
fields[].type required"signature" | "initials" | "date_signed" | "name" | "email" | "text" | "checkbox"
fields[].page requiredinteger1 is the first page.
fields[].x requirednumberPDF points from the left edge of the page (A4 is 595 x 842 points).
fields[].y requirednumberPDF points from the top edge of the page.
fields[].widthnumberPoints. Defaults by type: signature 200, initials 60, checkbox 14, others 160.
fields[].heightnumberPoints. Defaults by type: signature 50, initials 32, checkbox 14, others 22.
fields[].requiredbooleanDefault true, except checkboxes.
fields[].labelstring
fields[].keystringYour own name for the field. Returned with its value in GET /v1/envelopes/{id}.
fields[].role requiredstringSigner role, e.g. "tenant" or "landlord".
rolesarray of objectLabels for the roles the fields use. Worked out from the fields when left out.
roles[].key requiredstringSigner role, e.g. "tenant" or "landlord".
roles[].labelstring

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: The template.

DELETE/v1/templates/{id}Delete a template

Envelopes already made from it are not affected.

ParameterInDescription
id requiredpathTemplate id (tpl_...)

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: Deleted.

POST/v1/templates/{id}/previewPreview a template

Renders it with these variables. Missing variables show as {{name}}.

ParameterInDescription
id requiredpathTemplate id (tpl_...)

Body

FieldTypeDescription
variablesobjectValues for the template's {{variables}}, e.g. {"client.name": "Ava Chen", "rent": "$650 a week"}.

Returns 200: Preview PDF (a PDF).

Webhooks

GET/v1/webhooksList webhooks

Returns 200: Webhooks.

POST/v1/webhooksCreate a webhook

Events: envelope.sent, envelope.viewed, envelope.signed, envelope.completed, envelope.declined, envelope.voided, envelope.expired. Each POST has Squiggli-Event-Id and Squiggli-Signature: t=<unix>,v1=hex(HMAC-SHA256(secret, "t.body")). Retried for about 21 hours.

Body

FieldTypeDescription
url requiredstringPublic https URL that accepts POSTed JSON.
eventsarray of "envelope.sent" | "envelope.viewed" | "envelope.signed" | "envelope.completed" | "envelope.declined" | "envelope.voided" | "envelope.expired"Default: every event.
all_envelopesbooleantrue: every envelope in the business. false (default): only envelopes made with this credential.

Send an Idempotency-Key header so a retry can't do it twice.

Returns 201: The webhook, with its secret (shown once).

DELETE/v1/webhooks/{id}Delete a webhook

ParameterInDescription
id requiredpathWebhook id (whk_...)

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: Deleted.

Keys and embed tokens

GET/v1/api-keysList API keys

Web app session or live key only.

Returns 200: Keys (without the secret part).

POST/v1/api-keysCreate an API key

Shown once.

Body

FieldTypeDescription
name requiredstring
mode"live" | "test"

Send an Idempotency-Key header so a retry can't do it twice.

Returns 201: The key.

DELETE/v1/api-keys/{id}Revoke an API key

ParameterInDescription
id requiredpathKey id (key_...)

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: Revoked.

POST/v1/embed-tokensCreate an embed token

For the editor or one envelope inside your web app. Load embed.js and pass the token.

Body

FieldTypeDescription
scope required"editor" | "envelope"editor: the template editor. envelope: one envelope (build, review and send it).
template_idstringeditor: open this template. Leave out to start a new one.
envelope_idstringRequired for scope envelope.
ttl_secondsintegerDefault 3600.

Send an Idempotency-Key header so a retry can't do it twice.

Returns 201: Token and iframe URL.

Account

GET/v1/meGet account

The business this credential acts for: whether it can send live documents, free documents left, prices.

Returns 200: Account.

GET/v1/usageGet usage

Documents sent this month (or ?month=YYYY-MM), by kind and source. Billed on the Kiewa statement.

ParameterInDescription
monthquerystring

Returns 200: Usage.

GET/v1/settingsGet branding

The name, colour and logo signers see.

Returns 200: Settings.

PATCH/v1/settingsUpdate branding

Change the name, colour, logo or white-label default.

Body

FieldTypeDescription
display_namestring or nullThe name signers see. Default: the business name.
brand_colorstring or nullHex colour (#2340c8, 2340c8 or #24c), used for the signing page button and email button.
brand_display"logo_and_name" | "name" | "logo"How signers see you on the signing page and in emails: logo and name (default), name only, or logo only. Without a logo, the name is shown.
whitelabel_defaultbooleanNew envelopes are white-labelled unless they say otherwise.
notify_emailstring or nullGets decline, expiry and completed emails for envelopes with no sender email.
logo_base64string or nullA PNG logo, base64 (under 500 KB). null removes it.

Send an Idempotency-Key header so a retry can't do it twice.

Returns 200: Settings.

POST/v1/card-linkGet a card link

A Kiewa page where the business saves a card (billing). Comes back to the web app.

Returns 200: { url, expires_at }.