Foliant

Templates / Contract for signature

Contract for signature

Numbered clauses from JSON, parties block, two signature fields with printed names and dates. Multi-page with running header and page numbers.

1 page, A4. Rendered in 45 ms. 8 inputs, all optional.

Download .typ Open preview

Rendered Contract for signature template, first page
First page, rendered from the source below with the sample inputs.

Inputs

Everything variable comes in through sys.inputs. Missing keys fall back to sensible defaults, so an agent can send only what it knows.

KeySample value
clauses
JSON, 1054 chars
[
  {
    "title": "Subject",
    "text": "The Contractor designs and delivers the customer portal described in Quote Q-2026-118, which forms part of this agreement."
  },
  {
    "title": "Deliverables and acceptance",
    "text": "Deliverables are handed over per milestone. The Client reviews each within ten working days; silence counts as acceptance."
  },
  {
    "title": "Fees and payment",
    "text": "The fee is EUR 19 200 net. 50 % is due on signature, 50 % on final acceptance, each within 14 days of invoice."
  },
  {
    "title": "Intellectual property",
    "text": "Upon full payment the Client receives an exclusive, perpetual licence to the deliverables. The Contractor may reference the project publicly."
  },
  {
    "title": "Confidentiality",
    "text": "Both parties keep non-public information of the other confidential for three years after the end of this agreement."
  },
  {
    "title": "Term and termination",
    "text": "Either party may terminate for cause with immediate effect. Otherwise the agreement ends with final acceptance."
  },
  {
    "title": "Governing law",
    "text": "German law applies. Place of jurisdiction is Berlin."
  }
]
date2026-09-28
party_aMeridian Studio GmbH, Rosenthaler Str. 41, 10178 Berlin
party_bNorthwind Traders, Kastanienallee 7, 10435 Berlin
placeBerlin
signer_aMara Ehrlich, Managing Director
signer_bLena Hartmann, Head of Digital
titleService Agreement

Render it

After copying the template into your account:

curl -X POST https://api.foliant.dev/v1/render \
  -H "Authorization: Bearer $FOLIANT_API_KEY" \
  -H "Content-Type: application/json" \
  -o contract.pdf -d @- <<'JSON'
{ "template": "contract.typ",
  "inputs": {
    "clauses": "[{\"title\":\"Subject\",\"text\":\"The Contractor designs and delivers the customer portal described in Quote Q-2026-118, which forms part of this agreement.\"},{\"title\":\"Deliverables and acceptance\",\"text\":\"Deliverables are handed over per milestone. The Client reviews each within ten working days; silence counts as acceptance.\"},{\"title\":\"Fees and payment\",\"text\":\"The fee is EUR 19 200 net. 50 % is due on signature, 50 % on final acceptance, each within 14 days of invoice.\"},{\"title\":\"Intellectual property\",\"text\":\"Upon full payment the Client receives an exclusive, perpetual licence to the deliverables. The Contractor may reference the project publicly.\"},{\"title\":\"Confidentiality\",\"text\":\"Both parties keep non-public information of the other confidential for three years after the end of this agreement.\"},{\"title\":\"Term and termination\",\"text\":\"Either party may terminate for cause with immediate effect. Otherwise the agreement ends with final acceptance.\"},{\"title\":\"Governing law\",\"text\":\"German law applies. Place of jurisdiction is Berlin.\"}]",
    "date": "2026-09-28",
    "party_a": "Meridian Studio GmbH, Rosenthaler Str. 41, 10178 Berlin",
    "party_b": "Northwind Traders, Kastanienallee 7, 10435 Berlin",
    "place": "Berlin",
    "signer_a": "Mara Ehrlich, Managing Director",
    "signer_b": "Lena Hartmann, Head of Digital",
    "title": "Service Agreement"
  } }
JSON

Through MCP, render_document with template: "contract.typ" and the same inputs; get_template or fetch lists the keys.

Source

template.typ, 31 lines
#let input(k, default: "") = sys.inputs.at(k, default: default)
#let clauses = json(bytes(input("clauses", default: "[]")))
#set page(paper: "a4", margin: (top: 26mm, bottom: 26mm, x: 25mm),
  header: context if counter(page).get().first() > 1 [#set text(size: 8.5pt, fill: luma(110)); #input("title") #h(1fr) #input("date")],
  footer: context [#set text(size: 8.5pt, fill: luma(110)); #h(1fr) #counter(page).display() / #counter(page).final().first()])
#set text(font: "Libertinus Serif", size: 11pt, fill: rgb("1a1917"))
#set par(justify: true, leading: 0.7em)
#align(center)[#text(size: 20pt, weight: 600)[#input("title")]]
#v(8mm)
#grid(columns: (1fr, 1fr), gutter: 12mm,
  [#text(size: 8.5pt, fill: luma(110), tracking: 0.6pt)[BETWEEN] \ #input("party_a")],
  [#text(size: 8.5pt, fill: luma(110), tracking: 0.6pt)[AND] \ #input("party_b")])
#v(4mm)
#text(fill: luma(90))[hereinafter "Contractor" and "Client", agree as follows.]
#v(6mm)
#for (i, c) in clauses.enumerate() [
  #block(breakable: false, above: 5mm)[
    #text(weight: 600)[§ #(i + 1) #h(3pt) #c.title]
    #v(2pt)
    #c.text
  ]
]
#v(14mm)
#block(breakable: false)[
  #input("place"), #input("date")
  #v(16mm)
  #grid(columns: (1fr, 1fr), gutter: 20mm,
    [#line(length: 100%, stroke: 0.5pt) #v(2pt) #input("signer_a") \ #text(size: 8.5pt, fill: luma(110))[for the Contractor]],
    [#line(length: 100%, stroke: 0.5pt) #v(2pt) #input("signer_b") \ #text(size: 8.5pt, fill: luma(110))[for the Client]])
]