Template gallery / statement-of-work
Statement of work template
Statement of work for a solo professional or small studio, set as an instrument rather than a deck: every paragraph carries a clause number in a hanging gutter, the total fee stands in the header and is summed by the milestone schedule, scope sits beside what is expressly not in scope, and the acceptance section says what "done" means, how long the Client has to say otherwise, and what silence does. Ownership, confidence, warranty and governing law share the last sheet with the execution block, so the signatures never land on a page of their own.
chromium default PDF 25 top-level fields Billed per page
Fields
The full JSON Schema is below. Required fields are marked; anything missing comes back as a 422 naming the path, the expected type and a value that would be accepted.
| Field | Type | Required | Description |
|---|---|---|---|
| accent | string | optional | Rule, badge and card colour. A hex colour or a CSS colour keyword. It is interpolated into the stylesheet, so nothing else is accepted. |
| currency | string | optional | |
| sow_number | string | required | |
| effective_date | string (date) | required | |
| master_agreement | string | optional | The agreement this SOW hangs off, printed in the header and referenced by the signature note. |
| project | object { name } | optional | |
| provider | object { name, entity, address, email, … } | required | |
| client | object { name, entity, address, email, … } | required | |
| background | string | optional | One paragraph: why this work is happening, in the client's own terms. |
| objectives | array of string | optional | |
| scope | object { included, excluded, note } | required | The two lists printed side by side. What is not in `included` is not paid for. |
| deliverables | array of object { id, name, description, format, … } | optional | What the client actually receives. Give each one an id so the milestones can point at it. |
| milestones | array of object { name, note, deliverables, date, … } | optional | Payment schedule. The fees are summed for the total in the header and the table foot. |
| acceptance | object { criteria, process, review_days, deemed_accepted, … } | optional | The part that decides arguments later: what "done" means and what happens if nobody replies. |
| fees | object { fixed_total, structure, rate, invoicing, … } | optional | |
| assumptions | array of string | optional | |
| client_responsibilities | array of string | optional | |
| change_control | string | optional | |
| intellectual_property | string | optional | Who owns the delivered work, and what the Provider keeps. The clause a generated SOW usually forgets, and the one that is argued about later. |
| confidentiality | string | optional | What each side may say about the other's information, and for how long. |
| warranty | string | optional | What the Provider stands behind after acceptance, and for how long. |
| governing_law | string | optional | Which state's law applies and where a dispute is heard. |
| term | string | optional | |
| signature_note | string | optional | |
| footer | string | optional | Replaces the default "not legal advice" line. |
Default render options
Applied unless you override them. Options are part of the cache key.
| page_size | "Letter" |
| margin | {"top":"0.75in","right":"0.75in","bottom":"1in","left":"0.75in"} |
| print_background | true |
Example payload
This exact object renders the preview above. It is also what the API echoes back in a validation error, so an agent can repair a payload without a round trip to the docs.
{
"sow_number": "SOW-2026-07",
"effective_date": "2026-09-21",
"currency": "USD",
"master_agreement": "the Master Services Agreement dated March 2, 2025 between the parties",
"project": {
"name": "Bindery — order intake rebuild"
},
"provider": {
"name": "Wren Ashcroft",
"entity": "Ashcroft Systems LLC",
"address": "221 Bellwether Road, Suite 4, Providence, RI 02903",
"email": "wren@ashcroftsystems.test",
"contact": "Wren Ashcroft, principal",
"signatory": "Wren Ashcroft",
"signatory_title": "Principal"
},
"client": {
"name": "Marisol Trevino",
"entity": "Bindery Goods, Inc.",
"address": "1100 Canal Street, Floor 3, New Orleans, LA 70112",
"email": "marisol@binderygoods.test",
"contact": "Marisol Trevino, VP Operations",
"signatory": "Marisol Trevino",
"signatory_title": "VP Operations"
},
"background": "Bindery takes wholesale orders by email and rekeys each one into the ERP and into a shared spreadsheet. Two people spend… [287 characters, shortened for display]",
"objectives": [
"Cut the time from order received to order confirmed from about 36 hours to under 4",
"Remove the rekeying step entirely for the 14 accounts that place 80 percent of orders",
"Give the operations team one report each morning of anything that did not reconcile",
"Leave Bindery able to run the daily exceptions review without the Provider after the handover"
],
"scope": {
"included": [
"A hosted order intake form, validated against the current wholesale price list",
"Duplicate and short-pay detection on submission, with a confirmation email to the buyer",
"A nightly reconciliation job between the intake records and the ERP export",
"An exceptions report emailed at 6:00 a.m. Central to a distribution list Bindery controls",
"Migration of the 14 named accounts, including their price tiers and shipping defaults",
"Two training sessions of 90 minutes each, recorded, for the operations team",
"30 days of post-launch support for defects in the delivered work"
],
"excluded": [
"Changes to the ERP itself or to any accounting system of record",
"Customer-facing design work beyond the supplied Bindery brand sheet",
"Payment processing, credit checks or tax calculation",
"Migration of the 90 accounts outside the named 14",
"Historical data cleanup before January 1, 2026",
"Ongoing hosting, monitoring or a support retainer after the 30-day window",
"EDI connections to any retail partner"
],
"note": "Anything not in the left column is out of scope and is priced as a change order under the section below, even where it looks small."
},
"deliverables": [
{
"id": "D1",
"name": "Order intake form, deployed",
"description": "Public form with price list validation, duplicate detection and a confirmation email, running on Bindery's own hosting account.",
"format": "Deployed system plus source",
"due": "2026-10-23"
},
{
"id": "D2",
"name": "Reconciliation job",
"description": "Nightly job matching intake records to the ERP export, with a documented match rule set.",
"format": "Deployed system plus source",
"due": "2026-11-06"
},
{
"id": "D3",
"name": "Exceptions report",
"description": "Daily 6:00 a.m. email with everything that did not match, grouped by reason.",
"format": "Email report",
"due": "2026-11-06"
},
{
"id": "D4",
"name": "Account migration",
"description": "The 14 named accounts with price tiers, shipping defaults and contacts loaded and spot-checked against the ERP.",
"format": "Loaded data plus a reconciliation sheet",
"due": "2026-11-20"
},
{
"id": "D5",
"name": "Training and runbook",
"description": "Two recorded 90-minute sessions and a written runbook covering the daily exceptions review and the three most likely failure modes.",
"format": "PDF plus recordings",
"due": "2026-11-24"
}
],
"milestones": [
{
"name": "Kickoff",
"note": "Invoiced on signature; work begins on receipt",
"deliverables": "—",
"date": "2026-09-21",
"fee": 6000
},
{
"name": "Intake form accepted",
"deliverables": "D1",
"date": "2026-10-23",
"fee": 7500
},
{
"name": "Reconciliation and exceptions accepted",
"deliverables": "D2, D3",
"date": "2026-11-06",
"fee": 6500
},
{
"name": "Migration, training and handover accepted",
"deliverables": "D4, D5",
"date": "2026-11-24",
"fee": 4000
}
],
"acceptance": {
"criteria": [
"The deliverable does what its row in the table above says, running on Bindery's own systems and against Bindery's own data, not a sample set",
"For D1 and D2, twenty consecutive real orders process without manual correction",
"For D4, the reconciliation sheet shows zero unexplained differences against the ERP for the 14 named accounts",
"For D5, the runbook is enough for a named operations team member to complete the daily review unaided",
"The deliverable runs on Bindery's own hosting account under Bindery's own credentials, with no dependency on the Provider's accounts"
],
"process": "The Provider submits each deliverable by email with a short note on how to test it. The Client has the review period bel… [433 characters, shortened for display]",
"review_days": 5,
"deemed_accepted": "A deliverable not rejected in writing within five business days of submission is accepted and its milestone becomes invoiceable.",
"rejection_rounds": "Two correction rounds per deliverable are included. Further rounds are billed at the hourly rate below."
},
"fees": {
"structure": "Fixed fee of $24,000 for the scope above, invoiced against the milestones in the table.",
"rate": "$185 per hour for work outside the scope, billed in quarter-hour increments and only after a signed change order.",
"invoicing": "Invoiced on acceptance of each milestone, by email, to accountspayable@binderygoods.test with Marisol Trevino copied.",
"terms": "Net 15 from the invoice date, by ACH or check.",
"expenses": "Third-party service fees are passed through at cost with receipts. Anything over $250 is pre-approved in writing.",
"late": "Invoices unpaid 15 days past due accrue 1.5 percent per month. Work pauses at 30 days past due and resumes within three business days of payment."
},
"assumptions": [
"The wholesale price list in effect on the effective date is authoritative and will not be restructured during the engagement",
"The ERP export is available nightly in its current CSV shape and Bindery can change its schedule if needed",
"Bindery provides a sandbox ERP environment by October 2, 2026",
"One named Bindery person is available for up to four hours a week for questions and review",
"The 14 named accounts are those listed in Appendix A of the kickoff email dated September 15, 2026",
"The intake form is served from Bindery's existing hosting account and Bindery keeps that account current",
"No EDI, marketplace or retail-partner feed is introduced into the order path before the final acceptance"
],
"client_responsibilities": [
"Name one person with authority to accept deliverables, and one backup",
"Provide ERP sandbox credentials and the nightly export by October 2, 2026",
"Supply the current price list and shipping defaults in a single file, once",
"Schedule both training sessions before November 20, 2026",
"Own the hosting account and the distribution list the exceptions report is sent to",
"Review each submitted deliverable within five business days, or say in writing that more time is needed",
"Keep the 14 named accounts stable during migration, and tell the Provider in writing before adding or removing one"
],
"change_control": "Any change to the scope, the deliverables, the dates or the fees takes a written change order signed by both parties bef… [344 characters, shortened for display]",
"term": "This statement of work begins on the effective date and ends on acceptance of the final deliverable, or on December 31, … [328 characters, shortened for display]",
"signature_note": "Each party signs below and initials every sheet. With the Master Services Agreement named on page one, this is the whole of what has been agreed for this project.",
"intellectual_property": "On payment in full of the fee for a milestone, everything delivered under that milestone becomes Bindery's property, inc… [361 characters, shortened for display]",
"confidentiality": "Each party keeps the other's commercial terms, customer lists, price lists and systems information in confidence for thr… [330 characters, shortened for display]",
"warranty": "The Provider warrants that each deliverable will perform as its row in the table above describes for 30 days after its a… [375 characters, shortened for display]",
"governing_law": "Rhode Island law governs this statement of work. The parties will put a dispute to their two named contacts first, in writing, and only then to the courts of Providence County."
}
Values longer than 240 characters — data URIs, inline SVG — are shortened here so the
shape of the payload stays readable, and the replacement says how much was left out.
get_template and GET /v1/templates/:ref return them in full.
Render it
curl -sS https://api.galleyrender.com/v1/render \
-H "Authorization: Bearer $GALLEY_API_KEY" \
-H 'content-type: application/json' \
-d '{
"template": "statement-of-work@1",
"format": "pdf",
"data": "… the example payload above …"
}' # No API key. The first call mints a trial of 10 PDF pages or 10 images.
curl -sS https://mcp.galleyrender.com/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "render",
"arguments": {
"template": "statement-of-work",
"format": "pdf",
"data": { … see the example payload above … }
}
}
}'
Pin the version — statement-of-work@1 — in anything you ship. Publishing a new
version never changes an old one. Render endpoint reference →
Renders the example payload on the production service. No account, no key.
JSON Schema
schema.json (25 top-level properties)
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Statement of work",
"type": "object",
"required": [
"sow_number",
"effective_date",
"provider",
"client",
"scope"
],
"additionalProperties": true,
"properties": {
"accent": {
"type": "string",
"description": "Rule, badge and card colour. A hex colour or a CSS colour keyword. It is interpolated into the stylesheet, so nothing else is accepted.",
"examples": [
"#4338ca"
],
"pattern": "^(#[0-9a-fA-F]{3,8}|[a-zA-Z]{3,20})$"
},
"currency": {
"type": "string",
"default": "USD",
"examples": [
"USD"
]
},
"sow_number": {
"type": "string",
"examples": [
"SOW-2026-07"
]
},
"effective_date": {
"type": "string",
"format": "date",
"examples": [
"2026-09-21"
]
},
"master_agreement": {
"type": "string",
"description": "The agreement this SOW hangs off, printed in the header and referenced by the signature note.",
"examples": [
"the Master Services Agreement dated March 2, 2025 between the parties"
]
},
"project": {
"type": "object",
"properties": {
"name": {
"type": "string",
"examples": [
"Bindery — order intake rebuild"
]
}
}
},
"provider": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"examples": [
"Wren Ashcroft"
]
},
"entity": {
"type": "string",
"examples": [
"Ashcroft Systems LLC"
]
},
"address": {
"type": "string",
"examples": [
"221 Bellwether Road, Suite 4, Providence, RI 02903"
]
},
"email": {
"type": "string",
"format": "email",
"examples": [
"wren@ashcroftsystems.test"
]
},
"contact": {
"type": "string",
"examples": [
"Wren Ashcroft, principal"
]
},
"signatory": {
"type": "string",
"description": "Name on the signature block; defaults to `name`.",
"examples": [
"Wren Ashcroft"
]
},
"signatory_title": {
"type": "string",
"examples": [
"Principal"
]
},
"logo_url": {
"type": "string",
"format": "uri",
"examples": [
"https://example.com/ashcroft.png"
]
}
}
},
"client": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"examples": [
"Marisol Trevino"
]
},
"entity": {
"type": "string",
"examples": [
"Bindery Goods, Inc."
]
},
"address": {
"type": "string",
"examples": [
"1100 Canal Street, Floor 3, New Orleans, LA 70112"
]
},
"email": {
"type": "string",
"format": "email",
"examples": [
"marisol@binderygoods.test"
]
},
"contact": {
"type": "string",
"examples": [
"Marisol Trevino, VP Operations"
]
},
"signatory": {
"type": "string",
"examples": [
"Marisol Trevino"
]
},
"signatory_title": {
"type": "string",
"examples": [
"VP Operations"
]
}
}
},
"background": {
"type": "string",
"description": "One paragraph: why this work is happening, in the client's own terms.",
"examples": [
"Bindery takes wholesale orders by email and rekeys them into two systems. This engagement replaces that with a single intake form and a nightly reconciliation."
]
},
"objectives": {
"type": "array",
"items": {
"type": "string",
"examples": [
"Cut the time from order received to order confirmed from 36 hours to under 4"
]
},
"examples": [
[
"Cut order confirmation time to under four hours"
]
]
},
"scope": {
"type": "object",
"required": [
"included"
],
"description": "The two lists printed side by side. What is not in `included` is not paid for.",
"properties": {
"included": {
"type": "array",
"minItems": 1,
"items": {
"type": "string",
"examples": [
"A hosted order intake form with validation against the current price list"
]
},
"examples": [
[
"A hosted order intake form"
]
]
},
"excluded": {
"type": "array",
"items": {
"type": "string",
"examples": [
"Changes to the accounting system of record"
]
},
"examples": [
[
"Changes to the accounting system of record"
]
]
},
"note": {
"type": "string",
"examples": [
"Anything not listed on the left is out of scope and is priced as a change under the section below."
]
}
}
},
"deliverables": {
"type": "array",
"description": "What the client actually receives. Give each one an id so the milestones can point at it.",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"id": {
"type": "string",
"description": "Defaults to its position in the list.",
"examples": [
"D1"
]
},
"name": {
"type": "string",
"examples": [
"Order intake form, deployed"
]
},
"description": {
"type": "string",
"examples": [
"Public form with price list validation, duplicate detection and a confirmation email."
]
},
"format": {
"type": "string",
"examples": [
"Running on Bindery's account"
]
},
"due": {
"type": "string",
"format": "date",
"examples": [
"2026-10-23"
]
}
}
}
},
"milestones": {
"type": "array",
"description": "Payment schedule. The fees are summed for the total in the header and the table foot.",
"items": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"examples": [
"Kickoff"
]
},
"note": {
"type": "string",
"examples": [
"Invoiced on signature, payable before work begins"
]
},
"deliverables": {
"type": "string",
"description": "Which deliverables this milestone covers, by id or name.",
"examples": [
"D1, D2"
]
},
"date": {
"type": "string",
"format": "date",
"examples": [
"2026-09-21"
]
},
"fee": {
"type": "number",
"minimum": 0,
"examples": [
6000
]
}
}
}
},
"acceptance": {
"type": "object",
"description": "The part that decides arguments later: what \"done\" means and what happens if nobody replies.",
"properties": {
"criteria": {
"type": "array",
"items": {
"type": "string",
"examples": [
"It does what the deliverable row says, on Bindery's own data"
]
},
"examples": [
[
"It does what the deliverable row says"
]
]
},
"process": {
"type": "string",
"description": "Replaces the default review-and-resubmit paragraph.",
"examples": [
"The Provider submits each deliverable in writing and the Client accepts or rejects it in one consolidated list."
]
},
"review_days": {
"type": "integer",
"minimum": 1,
"examples": [
5
]
},
"deemed_accepted": {
"type": "string",
"examples": [
"A deliverable not rejected in writing within the review period is accepted and the milestone becomes invoiceable."
]
},
"rejection_rounds": {
"type": "string",
"examples": [
"Two correction rounds per deliverable are included; further rounds are billed at the hourly rate."
]
}
}
},
"fees": {
"type": "object",
"properties": {
"fixed_total": {
"type": "number",
"minimum": 0,
"description": "Overrides the header total when the engagement is not billed by milestone.",
"examples": [
24000
]
},
"structure": {
"type": "string",
"examples": [
"Fixed fee of $24,000 for the scope above, invoiced against the milestones in the table."
]
},
"rate": {
"type": "string",
"examples": [
"$185 per hour for work outside the scope, in quarter-hour increments, only after a written change order."
]
},
"invoicing": {
"type": "string",
"examples": [
"Invoiced on the acceptance of each milestone, by email, to accountspayable@binderygoods.test."
]
},
"terms": {
"type": "string",
"examples": [
"Net 15 from the invoice date, by ACH or check."
]
},
"expenses": {
"type": "string",
"examples": [
"Third-party service fees are passed through at cost with receipts and pre-approved in writing above $250."
]
},
"late": {
"type": "string",
"examples": [
"Invoices unpaid 15 days past due accrue 1.5% per month, and work pauses at 30 days past due."
]
}
}
},
"assumptions": {
"type": "array",
"items": {
"type": "string",
"examples": [
"The current price list is authoritative and will not change during the engagement"
]
},
"examples": [
[
"The current price list is authoritative"
]
]
},
"client_responsibilities": {
"type": "array",
"items": {
"type": "string",
"examples": [
"Name one person with authority to accept deliverables"
]
},
"examples": [
[
"Name one person with authority to accept deliverables"
]
]
},
"change_control": {
"type": "string",
"examples": [
"Any change to scope, deliverables, dates or fees takes a written change order signed by both parties before that work starts."
]
},
"intellectual_property": {
"type": "string",
"description": "Who owns the delivered work, and what the Provider keeps. The clause a generated SOW usually forgets, and the one that is argued about later.",
"examples": [
"On payment in full of the fees for a milestone, the deliverables in that milestone become the Client's property. The Provider keeps its pre-existing tools and libraries and grants the Client a perpetual licence to use them inside the deliverables."
]
},
"confidentiality": {
"type": "string",
"description": "What each side may say about the other's information, and for how long.",
"examples": [
"Each party keeps the other's commercial and customer information in confidence for three years from the effective date, and uses it only for this engagement."
]
},
"warranty": {
"type": "string",
"description": "What the Provider stands behind after acceptance, and for how long.",
"examples": [
"The Provider warrants the delivered work will perform as described for 30 days after acceptance and will correct defects in that window at no charge. Everything else is provided as is."
]
},
"governing_law": {
"type": "string",
"description": "Which state's law applies and where a dispute is heard.",
"examples": [
"Rhode Island law governs this statement of work, and the parties submit to the courts of Providence County."
]
},
"term": {
"type": "string",
"examples": [
"This statement of work begins on the effective date and ends on acceptance of the final deliverable."
]
},
"signature_note": {
"type": "string",
"examples": [
"By signing below each party agrees to this statement of work."
]
},
"footer": {
"type": "string",
"description": "Replaces the default \"not legal advice\" line.",
"examples": [
"Have your own counsel review the terms before you sign."
]
}
}
}