DocMake
The PDF DocMake makes from the Statement of Work template

The first page of the document DocMake makes from the sample values on this page.

Sales

Statement of Work

A statement of work says what will be built, by when, and what counts as finished. It sits under a master services agreement: the master agreement carries the legal terms that rarely change, the statement of work carries the scope and the money, which change with every engagement.

Acceptance criteria are the section arguments hinge on. Putting them in a column beside each deliverable, instead of a paragraph at the end, forces the awkward conversation before the work starts rather than at the invoice.

Exclusions do the same job in reverse. Naming what the engagement does not cover costs a sentence now and saves a negotiation in month three.

Once a deal closes, the deliverables and rates already exist in the proposal that won it. Generating the statement of work from that same data means nothing is retyped between the pitch and the signature, and the numbers in the contract match the numbers in the forecast.

Blanks to fill

sow_number Statement number
project_name Project
start_date Start date
completion_date Target completion
client_name Client
client_contact Client contact
supplier_name Supplier
supplier_contact Supplier contact
master_agreement Master agreement
client_project_manager Client project manager
supplier_project_manager Supplier project manager
background Background
total_payments Total payments
invoicing_schedule Invoicing
change_process How a change is agreed
day_rate Day rate
deliverables[] One per item, so a row is added for every item in the list
milestones[] One per item, so a row is added for every item in the list
exclusions[] One per item, so a row is added for every item in the list

The data behind the preview

This is the exact JSON that produced the document above. Change the values, POST them to the API, and you get your version back as DOCX or PDF. Lists grow and shrink with your data; the layout adapts.

  1. 01 Sign up free and duplicate this template into your workspace.
  2. 02 Adjust the wording and branding in the visual editor.
  3. 03 Fill it in the app, share it as a form link, or call the API.
sample-data.json
{
  "sow_number": "SOW-2026-031",
  "project_name": "Claims portal, phase one",
  "client_name": "Redhill Mutual Insurance",
  "client_contact": "Dana Achterberg, Head of Operations",
  "supplier_name": "Larkspur Data Ltd",
  "supplier_contact": "Gareth Okafor, Delivery Lead",
  "master_agreement": "Master services agreement dated March 4, 2025",
  "start_date": "September 14, 2026",
  "completion_date": "December 18, 2026",
  "background": "Redhill Mutual takes claims by telephone and keys them into a system that is no longer supported. Phase one replaces the way a claim is opened and tracked, and leaves payment and reserving on the existing system until phase two.",
  "deliverables": [
    {
      "deliverable": "Claim intake form",
      "description": "One form for all claim types, with the questions the handlers ask today.",
      "due_date": "October 9, 2026",
      "accepted_when": "A handler opens a claim of each type on staging with no critical issue open."
    },
    {
      "deliverable": "Claim tracking screen",
      "description": "Status, history and documents for one claim, wired to the existing records.",
      "due_date": "November 6, 2026",
      "accepted_when": "The screen matches the approved design at three widths and loads in under two seconds."
    },
    {
      "deliverable": "Handover and training",
      "description": "Written notes, two training sessions and four weeks of support after launch.",
      "due_date": "December 4, 2026",
      "accepted_when": "Both sessions are held and the notes are accepted by the client project manager."
    }
  ],
  "milestones": [
    {
      "milestone": "Kickoff and discovery signed off",
      "date": "September 18, 2026",
      "payment": "$18,000.00"
    },
    {
      "milestone": "Claim intake accepted",
      "date": "October 9, 2026",
      "payment": "$24,000.00"
    },
    {
      "milestone": "Claim tracking accepted",
      "date": "November 6, 2026",
      "payment": "$22,000.00"
    },
    {
      "milestone": "Final acceptance",
      "date": "December 18, 2026",
      "payment": "$26,000.00"
    }
  ],
  "total_payments": "$90,000.00",
  "exclusions": [
    {
      "not_included": "Payment and reserving, which are planned as phase two"
    },
    {
      "not_included": "Native applications for iOS or Android"
    },
    {
      "not_included": "Writing or translating the wording a customer reads"
    },
    {
      "not_included": "Hosting costs and third party licence fees"
    }
  ],
  "day_rate": "$1,150.00 a developer day",
  "invoicing_schedule": "On acceptance of each milestone, payable 30 days from the invoice date.",
  "change_process": "Any change to the work, the dates or the price is written up as a numbered change request and signed by both project managers before the work on it starts.",
  "client_project_manager": "Dana Achterberg",
  "supplier_project_manager": "Gareth Okafor"
}

Generate this document via the API

One template plus changing data is the whole point. The list of blanks above is the contract, and every new set of values comes back in the same layout: fill it in the app, hand someone a form link, or POST the JSON and get the file straight back.

The request below carries this page's own values, so it runs as soon as the template exists in your workspace. Swap the values for yours and the response is your document.

make-statement-of-work.sh
curl -X POST https://app.docmake.io/api/v1/render \
  -H "Authorization: Bearer $DOCMAKE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  --output statement-of-work.pdf \
  --data-binary @- <<'JSON'
{
  "template_id": "tmpl_your_template_id",
  "format": "pdf",
  "data": {
    "sow_number": "SOW-2026-031",
    "project_name": "Claims portal, phase one",
    "client_name": "Redhill Mutual Insurance",
    "client_contact": "Dana Achterberg, Head of Operations",
    "supplier_name": "Larkspur Data Ltd",
    "supplier_contact": "Gareth Okafor, Delivery Lead",
    "master_agreement": "Master services agreement dated March 4, 2025",
    "start_date": "September 14, 2026",
    "completion_date": "December 18, 2026",
    "background": "Redhill Mutual takes claims by telephone and keys them into a system that is no longer supported. Phase one replaces the way a claim is opened and tracked, and leaves payment and reserving on the existing system until phase two.",
    "deliverables": [
      {
        "deliverable": "Claim intake form",
        "description": "One form for all claim types, with the questions the handlers ask today.",
        "due_date": "October 9, 2026",
        "accepted_when": "A handler opens a claim of each type on staging with no critical issue open."
      },
      {
        "deliverable": "Claim tracking screen",
        "description": "Status, history and documents for one claim, wired to the existing records.",
        "due_date": "November 6, 2026",
        "accepted_when": "The screen matches the approved design at three widths and loads in under two seconds."
      },
      {
        "deliverable": "Handover and training",
        "description": "Written notes, two training sessions and four weeks of support after launch.",
        "due_date": "December 4, 2026",
        "accepted_when": "Both sessions are held and the notes are accepted by the client project manager."
      }
    ],
    "milestones": [
      {
        "milestone": "Kickoff and discovery signed off",
        "date": "September 18, 2026",
        "payment": "$18,000.00"
      },
      {
        "milestone": "Claim intake accepted",
        "date": "October 9, 2026",
        "payment": "$24,000.00"
      },
      {
        "milestone": "Claim tracking accepted",
        "date": "November 6, 2026",
        "payment": "$22,000.00"
      },
      {
        "milestone": "Final acceptance",
        "date": "December 18, 2026",
        "payment": "$26,000.00"
      }
    ],
    "total_payments": "$90,000.00",
    "exclusions": [
      {
        "not_included": "Payment and reserving, which are planned as phase two"
      },
      {
        "not_included": "Native applications for iOS or Android"
      },
      {
        "not_included": "Writing or translating the wording a customer reads"
      },
      {
        "not_included": "Hosting costs and third party licence fees"
      }
    ],
    "day_rate": "$1,150.00 a developer day",
    "invoicing_schedule": "On acceptance of each milestone, payable 30 days from the invoice date.",
    "change_process": "Any change to the work, the dates or the price is written up as a numbered change request and signed by both project managers before the work on it starts.",
    "client_project_manager": "Dana Achterberg",
    "supplier_project_manager": "Gareth Okafor"
  }
}
JSON

tmpl_your_template_id is a stand-in: build this template in the visual editor and copy the id it shows, or create one with POST /api/v1/templates. Keys, formats, strict mode and batches are in the API reference.

Or let an AI assistant do it

The DocMake MCP server lets Claude and other assistants make this document the same way. Install it once:

claude mcp add docmake \
  --env DOCMAKE_API_KEY=dm_your_api_key \
  -- npx -y @docmake/mcp@latest

Then ask for the document in plain words:

Make a PDF from my Statement of Work template with statement number "SOW-2026-031" and project "Claims portal, phase one".

How the MCP server works →

More sales templates