CommonPaper API Docs
Documentation

Custom Templates

Custom templates let you define your own agreement Cover Page as a YAML document. The YAML describes the sections and fields of your agreement, and Common Paper renders it as a fillable form, a web agreement, a PDF, and a Word export. Custom templates must be enabled for your organization; the endpoints below return 404 otherwise.

Working with custom templates via the API

EndpointWhat it does
GET /v1/custom_templatesList your organization's custom templates.
POST /v1/custom_templatesCreate a template from a YAML definition.
GET /v1/custom_templates/{id}Get one template, including its current YAML as current_definition.
POST /v1/custom_templates/{id}/versionsPublish a new version from a YAML definition.
PATCH /v1/custom_templates/{id}Rename a template or change its linked custom terms.
DELETE /v1/custom_templates/{id}Archive a template. Agreements already created from it keep rendering; they pin their version.

Creating a template and publishing a version both take a definition (the YAML) and a user_email or user_id identifying the user in your organization to record as the creator.

TerminalCode
curl -X POST "https://api.commonpaper.com/v1/custom_templates" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Consulting Agreement", "user_email": "you@example.com", "definition": "title: Consulting Agreement\nsections:\n - heading: Payment\n fields:\n payment_terms:\n label: Payment terms\n input: text\n default: Net 30\n" }'

Every publish creates a new version and makes it current immediately. Agreements pin the version they were created from, so publishing never changes an agreement that is already in flight.

Creating agreements from a custom template

Pass the custom template's UUID as template_id to POST /v1/agreements, and put field values in agreement.custom_field_values, keyed by the field keys in the YAML definition. Template defaults fill any fields you omit. A required field with no default and no submitted value returns a 400 naming the field.

Submitted values are validated against each field's input type, and an invalid value returns a 400 naming the field:

InputValues must be
select, radioOne of the field's options
multiselectAn array of selections, each one of the field's options
number, currencyNumeric
dateA valid date in YYYY-MM-DD format
emailA valid email address
TerminalCode
curl -X POST "https://api.commonpaper.com/v1/agreements" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_id": "CUSTOM_TEMPLATE_UUID", "owner_email": "you@example.com", "signer_email": "you@example.com", "agreement": { "recipient_name": "Art Vandelay", "recipient_email": "art@example.com", "custom_field_values": { "payment_terms": "Net 45", "start_date": "2026-01-01" } } }'

Fields with a mapping value, like address and rate inputs, take an object using the same component keys as their YAML defaults. Set draft to true to save without sending, the same as any other agreement.

Custom terms

Custom terms are the standard terms that follow the Cover Page. Attach terms to a template by passing custom_term_id when creating or updating it (an empty string unlinks them), and they carry over to agreements created from the template. Changing a template's terms publishes a new template version recording the terms it now references; pass user_id on the update to record who made the change. Renaming alone does not create a version.

EndpointWhat it does
GET /v1/custom_termsList your organization's custom terms. Ids and metadata only; the terms text is omitted because it can be very large.
GET /v1/custom_terms/{id}Get one term, including the full terms text of its released version as body.
POST /v1/custom_termsCreate terms. Text terms take a JSON body whose markdown body is published as released version 1; file terms take multipart/form-data with term_type=file and a docx file part.
POST /v1/custom_terms/{id}/versionsPublish a new version. The new body (or docx file part for file terms) immediately becomes the released version; existing versions are immutable.
PATCH /v1/custom_terms/{id}Rename terms. Only the name changes here; content changes go through publishing a version.

Creating terms and publishing versions take a user_email or user_id identifying the user in your organization to record as the creator. File term uploads convert to a pdf asynchronously; poll the term's conversion_status until it is ready. File uploads are REST only and are not available over MCP.

TerminalCode
curl -s -X POST "https://api.commonpaper.com/v1/custom_terms" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Standard Terms", "user_email": "you@example.com", "body": "## 1. Services\n\nProvider will make the services available to Customer..." }' | jq

To start a new page inside text terms, put \pagebreak on its own line in the markdown body. The PDF and Word export break the page there, and the line itself does not appear in the terms.

MarkdownCode
## 1. Services Provider will make the services available to Customer... \pagebreak ## 2. Exhibit A

The basic shape

A template has a title and a list of sections. Each section groups related fields.

YAMLCode
title: Consulting Agreement sections: - heading: Services fields: services_description: label: Description of services input: textarea - heading: Payment fields: payment_terms: label: Payment terms input: text default: Net 30

Field keys (like services_description) are internal identifiers. They must start with a lowercase letter and contain only lowercase letters, numbers, and underscores. Each key must be unique across the whole template, and a duplicate key anywhere in the YAML is rejected as a validation error. These keys are also the keys you use in custom_field_values when creating agreements.

Top-level settings

All of these are optional except title.

KeyWhat it does
titleThe display name of the agreement, shown as the heading on the agreement, PDF, and Word export. Required.
terms_labelRenames the "Cover Page" heading. Use this when your agreement calls its terms something else, like Key Terms, Order Form, or Statement of Work. In the Word export it also appears uppercased in the page header.
terms_sublabelSmaller text under the terms label in the Word export, such as "The key legal terms of this Agreement are as follows:".
info_boxExplanatory text shown in a highlighted box above the Cover Page, like the framework explanation on Common Paper standard agreements.
terms_headingA heading row rendered at the top of the terms table, such as "Key Terms".
terms_subheadingSmaller text under the terms heading.
signing_disclaimerThe sentence above the signature blocks. Defaults to "By signing this Cover Page, each party agrees to enter into the Agreement."
footerText shown at the bottom of every page in PDF and Word exports. Write {terms_version} anywhere in the text to insert the current custom terms version number, for example Acme Terms Version {terms_version}. Defaults to the custom terms name and version number.
partiesRenames the two parties. Takes sender: and recipient: keys, for example Vendor and Client. Defaults are Provider and Customer.

Example:

YAMLCode
title: Independent Contractor Agreement terms_label: Framework Terms info_box: The Framework Terms have 2 parts... signing_disclaimer: By signing below, both parties accept these Framework Terms. parties: sender: Company recipient: Contractor sections: ...

Sections

Each entry in sections: is one row of the Cover Page, with the heading on the left and its fields on the right.

KeyWhat it does
headingThe section name shown on the left.
subheadingSmaller text under the heading.
required: trueThe section always appears on the agreement and cannot be excluded by the sender.
included: falseThe section is excluded by default. Senders can include it per agreement with a checkbox when creating the agreement.
headerMakes the section a full-width header row instead of a fields row. Use it to divide the Cover Page, for example "Additions and Modifications". A header section has no fields.
importPulls in a ready-made section. See Imports below.
accessWho can edit the section's fields. See Access levels below.
page_breakbefore or after. Starts a new page in the PDF and Word export before or after the section. A page break on a section that is excluded from the agreement is skipped.
YAMLCode
sections: - heading: Optional rider subheading: Only applies to enterprise deals included: false fields: rider_details: label: Rider details input: textarea - heading: Exhibit A page_break: before fields: exhibit_a: label: Exhibit A input: markdown - header: Additions and Modifications

Fields

Fields live in a fields: mapping inside a section. The mapping key is the field key; everything else is configuration.

KeyWhat it does
labelThe name shown above the input and next to the value on the agreement.
inputThe input type. See the table below. Required.
instructionsGuidance shown only on the form while filling it in. It does not appear on the finished agreement.
placeholderPlaceholder text inside the empty input.
required: trueThe field always appears on the agreement, and a value must be entered before the agreement can be sent.
defaultPrefills the field. Senders can change it when creating an agreement.
optionsThe choices for radio, select, multiselect, and rate inputs.
currencyThe currency code for currency and rate inputs. Defaults to USD.
accessWho can edit the field. Overrides the section's access. See Access levels below.

Fields without a value are left off the finished agreement, unless they are required or fixed.

Access levels

By default only organization admins can edit field values when creating an agreement. Add access to a field or a whole section to open it up:

ValueWho can edit
adminOrganization admins only. This is the default.
standardStandard members and admins.
recipientThe agreement recipient, plus standard members and admins.

A field-level access overrides its section's. Locked fields show read-only on the form and keep their template defaults.

Recipients are a special case. While negotiation is enabled they can propose changes to any field as before. access: recipient fields also appear as inputs directly on the recipient's view of the agreement so they can fill them in alongside the signature block. Marking one of these fields required: true means the recipient must fill it in before signing; it does not block the sender from sending.

YAMLCode
sections: - heading: Fees access: standard fields: fee: label: Monthly fee input: currency po_number: label: PO number input: text access: recipient

Input types

InputRenders as
textSingle-line text box
textareaMulti-line text box. Line breaks are preserved on the agreement and its exports.
markdownMulti-line text box with formatting (bold, lists, links) preserved on the agreement
numberNumber input. Decimals are accepted.
currencyMoney input with a currency symbol. Set currency: EUR to change from USD. Values render exactly as entered, including sub-cent precision like 0.0015.
rateA money amount plus a per-unit select, shown on one line like "$500.00 per hour". options lists the units (hour, day, week). Defaults and submitted values use a mapping with amount: and per: keys.
dateDate picker. Values are stored as YYYY-MM-DD and render as long dates on the agreement, like September 1, 2026.
emailEmail input
radioOne choice from options, all visible
selectOne choice from options, in a dropdown
multiselectMultiple choices from options, shown as checkboxes
statesDropdown of US states
addressA full address block (country, street, city, state, ZIP). Defaults and submitted values use a mapping with those component keys.
attachmentPick a PDF from your organization's attachment library. The file is referenced on the agreement and appended to the PDF.
fixedUneditable text set by default. Always appears on the agreement. Use it for standard language that senders should not change. The text renders as markdown. For multi-line markdown like bullet lists or tables, write the default as a block scalar (`default:

Rate example:

YAMLCode
fee: label: Rate input: rate options: - hour - day default: amount: 500 per: hour

Address example:

YAMLCode
contractor_address: label: Contractor address input: address default: country: USA city: New York state: New York

Imports

Imports drop in a ready-made section with one line. Today there is one import available:

YAMLCode
sections: - import: governing_law

This renders a Governing Law & Chosen Courts section backed by the same pickers Common Paper standard agreements use. To preset answers, add a defaults: mapping, and to limit the pickers to specific jurisdictions, add options::

YAMLCode
sections: - import: governing_law options: - New York - Delaware - California defaults: governing_law_region: Delaware chosen_courts_region: Delaware

The state pickers list US states, and options restricts them to a subset. Organizations allowed to use additional courts get the same country selector as standard agreements: pick a country and the region control adapts (US states, Canadian provinces, or a free-text region elsewhere).

Versions

Every publish creates a new version and makes it current immediately. Agreements pin the version they were created from, so they always render exactly what the signer saw. The version history is also available in the template editor in the Common Paper app, where the YAML can be edited alongside a live form preview, and loading an old version there brings back the custom terms it was released with.

A version is the template's YAML plus the custom terms it referenced at publish time, returned as custom_term_id on the version and counted by version_number. Template responses report the current version as current_version_number. Publishing a definition identical to the current version with the same linked terms is a no-op: nothing new is created and the current version comes back with a 200 instead of a 201.

Last modified on