Templates
Reusable documents with variables: written as blocks that squiggli lays out, or a PDF with fields placed by role.
There are two kinds. A block template is a document written as a list of blocks; squiggli lays it out on A4 pages, fills in the variables and places the fields. A PDF template is your own PDF with fields placed on it by role. Both can be built visually in the web app (Templates) or embedded in your own app.
Block templates
{
"name": "Pest control quote",
"blocks": [
{ "type": "heading", "text": "Quote {{quote_id}}" },
{ "type": "paragraph", "text": "Prepared for {{client.name}} at {{address}}." },
{ "type": "table", "header": true, "rows": [["Service", "Price inc GST"], ["Ant treatment", "{{price}}"]] },
{ "type": "field", "field": "text", "role": "client", "label": "Preferred day", "key": "day" },
{ "type": "field", "field": "checkbox", "role": "client", "label": "I accept the terms", "required": true },
{ "type": "signature", "role": "client", "label": "Client signature" }
]
}squiggli works out the roles (client) and variables (quote_id, client.name, address, price) and returns them on the template.
Blocks
| Type | Properties | Notes |
|---|---|---|
heading | text, level (1 to 3) | Bold heading. Level 1 is largest. |
paragraph | text, align (left or center) | Wraps across lines and pages. Use \n for line breaks. |
list | items, ordered | Bulleted, or numbered when ordered is true. |
table | rows, header | Up to 8 columns. The first row is bold when header is true. |
divider | A thin line. | |
spacer | height (points) | Empty space. |
page_break | Starts a new page. | |
field | field, role, label, required, key, width | A field for a role: text, checkbox, initials, name, email or date_signed. |
signature | role, label | A signature line, with the date signed beside it. |
Variables
Write {{name}} anywhere in text: headings, paragraphs, list items, table cells and field labels. Names can use letters, numbers, dots, dashes and underscores. When you send, every variable must have a value, or the API answers 422 missing_variables with the list. Previews show missing ones as {{name}}.
Roles
Fields belong to roles, like tenant and landlord. When you send, each signer fills the role in their role; signers without one fill the remaining roles in order. A role nobody fills is refused with 422 unfilled_role. Give roles labels with roles: [{ "key": "tenant", "label": "Tenant" }].
PDF templates
Upload a PDF and place fields by role, in points from the top-left:
{
"name": "Residential lease",
"file_url": "https://files.example.com/lease-template.pdf",
"fields": [
{ "role": "tenant", "type": "signature", "page": 4, "x": 72, "y": 600 },
{ "role": "tenant", "type": "date_signed", "page": 4, "x": 320, "y": 628 },
{ "role": "landlord", "type": "signature", "page": 4, "x": 72, "y": 700 }
]
}Previews
POST /v1/templates/{id}/preview with variables returns the PDF. POST /v1/templates/preview renders blocks you haven't saved, which is what the visual editor uses for its live preview.
Sending a template
curl https://squiggli.billy-965.workers.dev/v1/envelopes \
-H "Authorization: Bearer $SQUIGGLI_API_KEY" -H "Content-Type: application/json" \
-d '{
"title": "Quote Q-7",
"template_id": "tpl_...",
"variables": { "quote_id": "Q-7", "client.name": "Ava Chen", "address": "4 Harbour Lane", "price": "$239" },
"signers": [{ "name": "Ava Chen", "email": "ava@example.com", "role": "client" }],
"send": true
}'Changing a template later doesn't change envelopes already made from it: each envelope keeps the PDF it was sent with.