Skip to content

Contracts API

All authenticated endpoints require a valid Cloudflare Access JWT. Public signing endpoints use a token-based URL instead.

Base paths:

  • Authenticated: /api/contracts
  • Public (no auth): /api/contracts/sign

Returns the contract info and the signer’s assigned fields for the signing page.

Response

{
"contract": {
"id": "string",
"title": "string",
"contract_type": "employment_agreement",
"status": "pending"
},
"signer": {
"id": "string",
"name": "string",
"email": "string",
"role_label": "string",
"status": "viewed",
"sign_order": 1,
"signed_at": null
},
"fields": [
{
"id": "string",
"type": "signature",
"label": "Employee Signature",
"signer_role_id": "role_1",
"page": 1,
"x_pct": 0.1,
"y_pct": 0.8,
"w_pct": 0.3,
"h_pct": 0.06,
"required": true
}
]
}

Streams the base PDF bytes from R2.


Records that the signer has viewed the document (viewed_at, activity log). No body required.


Submits the signer’s completed field values.

Body

{
"field_values": {
"field-id-1": { "type": "typed", "value": "Jane Smith" },
"field-id-2": "2026-03-07",
"field-id-3": true
}
}

For signature fields, the value is { type: "typed" | "drawn", value: string } where drawn signatures use a base64 PNG data URL.

Response { "ok": true }

On success: marks the signer as signed, sends the next signer’s email (if any), or triggers contract completion.


Declines the signing request.

Body { "reason": "optional string" }

Response { "ok": true }


List active contract templates.

Response { "templates": ContractTemplate[] }


Create a new template. Accepts multipart/form-data.

FieldTypeDescription
namestringTemplate name
descriptionstring?Optional description
contract_typestringemployment_agreement | msa | nda | npa | other
signer_rolesJSON string[{ id, label }]
fields_schemaJSON stringFieldDef[]
google_doc_idstring?Google Drive file ID to export as PDF
google_doc_urlstring?Google Docs URL to export as PDF
pdfFile?Direct PDF upload

Exactly one of google_doc_id, google_doc_url, or pdf is required.

Response { "id": "string" }


Get a single template including fields_schema and signer_roles.


Update template metadata and/or field layout.

Body

{
"name": "string?",
"description": "string?",
"contract_type": "string?",
"signer_roles": "SignerRole[]?",
"fields_schema": "FieldDef[]?"
}

Soft-deletes the template (is_active = 0). Existing contracts are not affected.


Streams the template’s base PDF from R2.


Lists Google Docs from Drive. Requires a Google Workspace connection with drive.readonly scope.

Query params

  • query — optional text search (name contains)
  • folder_id — optional folder filter (defaults to contracts_drive_folder_id org setting if set)

Response { "files": DriveFile[], "defaultFolderId": string | null }


List contracts. Scoped by access level:

  • executive/head: all contracts
  • manager: own contracts + contracts linked to direct reports
  • lead/employee: contracts linked to own person record

Query paramsstatus, person_id (optional filters)

Response { "contracts": Contract[] }


Create a new contract. Accepts multipart/form-data.

FieldTypeDescription
titlestringContract title
contract_typestringContract type enum
template_idstring?Template to base on (omit for one-off)
fields_schemaJSON stringFieldDef[] (one-off only)
signer_rolesJSON stringSignerRole[] (one-off only)
signersJSON stringSignerInput[]
person_idstring?Link to an employee
google_doc_idstring?Drive file (one-off)
google_doc_urlstring?Google Docs URL (one-off)
pdfFile?Direct PDF upload (one-off)

SignerInput

{
"name": "string",
"email": "string",
"signer_role_id": "role_1",
"role_label": "Employee",
"sign_order": 1,
"return_to_sender": false
}

Response { "id": "string" }


Get full contract detail including signers and activity log.

Response ContractDetail (extends Contract with signers: ContractSigner[] and activity: ContractActivity[])


Send the contract to the first signer. Sets status to pending and emails the first signer.

Response { "ok": true }


Void the contract.

Body { "reason": "optional string" }

Response { "ok": true }


Resend the signing email to the current pending signer.

Response { "ok": true }


Streams the signed PDF (if completed) or base PDF.


Get the activity log for a contract.

Response { "activity": ContractActivity[] }


interface FieldDef {
id: string;
type: "signature" | "text" | "date" | "checkbox" | "textarea";
label: string;
signer_role_id: string;
page: number; // 1-indexed
x_pct: number; // 0–1 relative to page width (top-left origin)
y_pct: number; // 0–1 relative to page height (top-left origin)
w_pct: number;
h_pct: number;
required: boolean;
placeholder?: string;
}
draft → pending → completed
voided