squiggli Get a free API key
Guides

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

json
{
  "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

TypePropertiesNotes
headingtext, level (1 to 3)Bold heading. Level 1 is largest.
paragraphtext, align (left or center)Wraps across lines and pages. Use \n for line breaks.
listitems, orderedBulleted, or numbered when ordered is true.
tablerows, headerUp to 8 columns. The first row is bold when header is true.
dividerA thin line.
spacerheight (points)Empty space.
page_breakStarts a new page.
fieldfield, role, label, required, key, widthA field for a role: text, checkbox, initials, name, email or date_signed.
signaturerole, labelA 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:

json
{
  "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

bash
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.