Appearance
Create a template
POST /api/v1/templates
From text with fill-ins and signing fields, or copied from a library entry. It emails no one, so it needs no approval. Needs the documents permission.
| Permission | documents |
| MCP tool | create_template |
| Retries | Safe with an Idempotency-Key |
Request
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | No | Makes a retried call safe: the same key returns the first result instead of creating or sending again. Matches ^[A-Za-z0-9_-]{8,100}$. |
Body
Give content and a title, or a library_entry to copy, not both.
| Field | Type | Required | Description |
|---|---|---|---|
title | string | No | The template's name: needed with content, and a library entry's own name by default. 1–255 characters. |
content | string | No | The template's text, in blocks separated by a blank line: # Heading (## and ### for smaller ones), a list whose every line starts with "- " or "1. ", --- for a rule, and anything else a paragraph. Inside text: **bold** for bold; {{key}} or {{key|Label}} for a fill-in completed for each document (key: lowercase letters, numbers and _, starting with a letter); [[type:role]] for a signing field and [[type:role?]] for an optional one, either with |Label to name it (type: signature, initials, date_signed, text, checkbox, full_name; role: lowercase letters, numbers and -). 1–500000 characters. |
fill_ins | array of objects | No | Labels for fill-ins in the text. Without one, a fill-in takes its first written label, or one made from its key. Up to 200 items. |
fill_ins[].key | string | Yes | Matches ^[a-z][a-z0-9_]{0,39}$. |
fill_ins[].label | string | Yes | 1–100 characters. |
roles | array of string | No | Who signs, by role. A listed role with no field in the text gets a Signature, Name and Date block at the end. By default, the roles of the text's fields. 1–20 items. |
library_entry | mutual-nda or consulting-agreement or service-agreement or client-proposal or founder-agreement or offer-letter or business-acknowledgment or master-services-agreement or w9-request or vendor-information-form or property-agreement or commission-agreement or consent-form or activity-waiver or approval-form or event-registration or internal-acknowledgment | No | A library entry to copy instead of writing content, by slug. |
Responses
| Status | Meaning |
|---|---|
201 | The new template. |
400 | The input is invalid. |
401 | No key, or a key that is unknown, expired or revoked, or whose creator is no longer an owner or admin. |
402 | The workspace's plan doesn't allow it: no completed requests left this month, more members than sender seats, more signers than the plan allows, a document that must be bought first, or the workspace's saved templates are at its plan's limit. |
403 | The key lacks the permission, or it is an API key and the workspace isn't on Teams & Platform. |
404 | Not found in the key's workspace (a key works only in the workspace it was made in; get_workspace says which). |
409 | The request is in a state that doesn't allow this, or the Idempotency-Key was used for something else. |
413 | The body is larger than 2 MB, or the template is too long to save. |
429 | More than 120 calls a minute through this key, more than 2000 from one network address (for IPv6, its /56 block) across all keys, or a limit on sending reached: the key's daily sends, the plan's or a recipient's daily requests, or the workspace's waiting approvals. |
Errors share one shape, { "message": "…" }: see Errors and rate limits.
201 body
| Field | Type | Description |
|---|---|---|
id | string (uuid) | — |
title | string | — |
source_type | string | — |
status | string | — |
draft_revision | integer | — |
fill_ins | array of objects | — |
fill_ins[].key | string | — |
fill_ins[].label | string | — |
fill_ins[].value | string or null | — |
team_access | string | — |
created_at | string (date-time) or null | — |
updated_at | string (date-time) or null | — |
roles | array of string | Who signs, by role, in the order the fields appear: a signing request names a recipient for each. |
form | object or null | The intake form whose answers fill the template, if it has fill-ins. |
Example
json
{
"id": "5d0f8c3a-6b1e-4f2a-9c7d-3e8b1a2f4c6d",
"title": "Mutual NDA",
"source_type": "template",
"status": "draft",
"draft_revision": 4,
"fill_ins": [
{
"key": "client_name",
"label": "Client name",
"value": null
},
{
"key": "effective_date",
"label": "Effective date",
"value": null
}
],
"team_access": "view",
"created_at": "2026-10-02T14:03:19.000Z",
"updated_at": "2026-10-28T09:12:44.000Z",
"roles": [
"client"
],
"form": {
"version": 1,
"title": "Mutual NDA",
"steps": [
{
"id": "parties",
"title": "The other party",
"questions": [
{
"key": "client_name",
"label": "Client name",
"type": "text",
"required": true,
"fills": [
"client_name"
]
},
{
"key": "effective_date",
"label": "Effective date",
"type": "date",
"required": true,
"fills": [
"effective_date"
]
}
]
}
]
}
}Examples
bash
curl -X POST https://tryjustdocs.com/api/v1/templates \
-H "Authorization: Bearer $JUSTDOCS_API_KEY" \
-H "Idempotency-Key: deal-4821-create-template" \
-H "Content-Type: application/json" \
-d '{
"title": "Mutual NDA",
"content": "# Mutual NDA\n\nThis agreement between Northwind Ltd and {{client_name}} starts on {{effective_date}}.\n\n- Each party keeps the other'\''s confidential information private.\n- Either party may end it with 30 days'\'' notice.\n\n**Client**\nSignature: [[signature:client]]\nDate: [[date_signed:client]]"
}'js
const response = await fetch("https://tryjustdocs.com/api/v1/templates", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.JUSTDOCS_API_KEY}`,
"Idempotency-Key": "deal-4821-create-template",
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Mutual NDA",
content: "# Mutual NDA\n\nThis agreement between Northwind Ltd and {{client_name}} starts on {{effective_date}}.\n\n- Each party keeps the other's confidential information private.\n- Either party may end it with 30 days' notice.\n\n**Client**\nSignature: [[signature:client]]\nDate: [[date_signed:client]]"
}),
});
if (!response.ok) throw new Error((await response.json()).message);
const result = await response.json();python
import os
import requests
response = requests.post(
"https://tryjustdocs.com/api/v1/templates",
headers={"Authorization": f"Bearer {os.environ['JUSTDOCS_API_KEY']}", "Idempotency-Key": "deal-4821-create-template"},
json={
"title": "Mutual NDA",
"content": "# Mutual NDA\n\nThis agreement between Northwind Ltd and {{client_name}} starts on {{effective_date}}.\n\n- Each party keeps the other's confidential information private.\n- Either party may end it with 30 days' notice.\n\n**Client**\nSignature: [[signature:client]]\nDate: [[date_signed:client]]",
},
timeout=30,
)
response.raise_for_status()
result = response.json()