Skip to content

Documents

Documents live inside containers and have a version lifecycle: DRAFT → ACTIVE → ARCHIVED. Each document always has one active version at most. Signing requests are sent against a specific version.

DRAFT ──(publish)──► ACTIVE ──(archive)──► ARCHIVED
(new-draft)
DRAFT (v2)

A new document starts with version 1 in DRAFT. Publishing transitions it to ACTIVE. Creating a new draft from an active document increments the version number.

MethodPathDescription
GET/api/v1/documents?containerId=List documents in a container
POST/api/v1/documentsCreate a document
GET/api/v1/documents/:idGet a document with versions
PUT/api/v1/documents/:id/draftUpdate the latest draft
POST/api/v1/documents/:id/publishPublish the latest draft
POST/api/v1/documents/:id/archiveArchive the active version
POST/api/v1/documents/:id/new-draftCreate a new draft from active

GET /api/v1/documents?containerId={uuid}

Query parameters:

ParameterTypeRequiredDescription
containerIdUUIDYesFilter documents by container

Response 200:

{
"data": [
{
"id": "018e1234-abcd-7000-8000-000000000010",
"name": "Terms of Service",
"description": null,
"container_id": "018e1234-abcd-7000-8000-000000000001",
"created_by": "018e1234-abcd-7000-8000-000000000002",
"created_at": "2026-02-01T09:00:00.000Z",
"updated_at": "2026-02-01T09:00:00.000Z"
}
]
}

Error cases:

StatusCodeCause
400BAD_REQUESTcontainerId missing or not a valid UUID
401UNAUTHORIZEDMissing or invalid API key
404NOT_FOUNDContainer not found in this organisation

POST /api/v1/documents

Creates a document with an initial DRAFT version (no clauses yet).

Request body:

FieldTypeRequiredConstraints
containerIdUUIDYesMust belong to your organisation
namestringYes1–100 characters
descriptionstringNoMax 500 characters
{
"containerId": "018e1234-abcd-7000-8000-000000000001",
"name": "Terms of Service",
"description": "Website terms of service document"
}

Response 201: Document object (same shape as list response).

Error cases:

StatusCodeCause
400BAD_REQUESTMissing or invalid fields
401UNAUTHORIZEDMissing or invalid API key
404NOT_FOUNDcontainerId not found in this organisation

GET /api/v1/documents/:id

Returns the document with its versions array.

Response 200:

{
"data": {
"id": "018e1234-abcd-7000-8000-000000000010",
"name": "Terms of Service",
"versions": [
{
"id": "018e1234-abcd-7000-8000-000000000020",
"version_number": 1,
"status": "ACTIVE",
"created_at": "2026-02-01T09:00:00.000Z"
}
]
}
}

PUT /api/v1/documents/:id/draft

Replaces all clauses and settings on the latest DRAFT version. This is a full replacement — send all clauses, not just changed ones.

Request body:

{
"content": {
"clauses": [
{
"id": "clause-1",
"order": 0,
"title": "Acceptable Use",
"content": "{\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"content\":[{\"type\":\"text\",\"text\":\"You agree to use the service only for lawful purposes.\"}]}]}",
"is_mandatory": true,
"default_checked": true,
"slug": "acceptable-use"
},
{
"id": "clause-2",
"order": 1,
"title": "Marketing Communications",
"content": "{\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"content\":[{\"type\":\"text\",\"text\":\"We may send you promotional emails.\"}]}]}",
"is_mandatory": false,
"default_checked": false,
"slug": "marketing-comms"
}
]
},
"settings": {
"expiry_days": 30,
"redirect_url": "https://example.com/thank-you"
}
}

Clause fields:

FieldTypeDescription
idstringStable clause identifier (your choice)
ordernumberDisplay order (0-based)
titlestringClause heading
contentstringTipTap document as JSON string
is_mandatorybooleantrue = signer must accept
default_checkedbooleanPre-checked state shown to signer
slugstringURL-friendly identifier
sectionstringOptional section grouping label

Settings fields:

FieldTypeDescription
expiry_daysnumberDays until signing request expires (0 = never)
redirect_urlstring | nullURL to redirect signer after signing

Error cases:

StatusCodeCause
400BAD_REQUESTInvalid clause structure or settings
404NOT_FOUNDDocument has no DRAFT version (already published or archived)

POST /api/v1/documents/:id/publish

Transitions the latest DRAFT version to ACTIVE. If another version is already ACTIVE, it is automatically archived.

Request: No body.

Response 200: Updated version object with status: "ACTIVE".

Error cases:

StatusCodeCause
404NOT_FOUNDNo DRAFT version found on this document

POST /api/v1/documents/:id/archive

Transitions the ACTIVE version to ARCHIVED. Existing signing requests already sent are unaffected but new ones cannot be created against archived versions.

Request: No body.

Response 200: Updated version object with status: "ARCHIVED".

Error cases:

StatusCodeCause
404NOT_FOUNDNo ACTIVE version found on this document

POST /api/v1/documents/:id/new-draft

Copies the current ACTIVE version’s clauses and settings into a new DRAFT version with an incremented version number. Use this to start revising a published document.

Request: No body.

Response 201: New version object with status: "DRAFT" and incremented version_number.

Error cases:

StatusCodeCause
404NOT_FOUNDNo ACTIVE version to copy from
409CONFLICTA DRAFT version already exists for this document