Create a contract

Create a draft contract from a template: copies its title, content, field placements and prepared PDF, and creates one recipient per template role. Nothing is emailed until you send it.

POST https://api.centerfy.ai/webhooks/inbound/contracts

Headers

HeaderRequiredValueDescription
x-api-keyYesyour sub-account API key (cfy_…)Authenticates the request; or use Authorization: Bearer <key>.

Body parameters

NameTypeRequiredDefaultDescription
template_idstring (uuid)Yes—Template to create the contract from.
titlestringNo—Contract title. Defaults to the template name.
contact_idstring (uuid) | nullNo—CRM contact in this sub-account. Also fills the first signer role (name and email) unless that role is given in recipients.
recipients{ role_key, name, email }[]No—Fill template roles (max 50). role_key must match a recipient_roles[].key; name and email are required. Roles you don’t fill keep the role label as name and an empty email.

Request body

{
  "template_id": "2e4f6a8b-1c3d-4e5f-9a7b-8c9d0e1f2a3b",
  "title": "Service agreement — Jamie Rivera",
  "contact_id": "3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f",
  "recipients": [
    {
      "role_key": "client",
      "name": "Jamie Rivera",
      "email": "[email protected]"
    }
  ]
}

Example

curl -X POST "https://api.centerfy.ai/webhooks/inbound/contracts" \
  -H "x-api-key: $CENTERFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "template_id": "2e4f6a8b-1c3d-4e5f-9a7b-8c9d0e1f2a3b",
  "title": "Service agreement — Jamie Rivera",
  "contact_id": "3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f",
  "recipients": [
    {
      "role_key": "client",
      "name": "Jamie Rivera",
      "email": "[email protected]"
    }
  ]
}'
import { CenterfyClient } from "@centerfy/sdk";

const centerfy = new CenterfyClient({ apiKey: process.env.CENTERFY_API_KEY! });

const result = await centerfy.contracts.create({
  "template_id": "2e4f6a8b-1c3d-4e5f-9a7b-8c9d0e1f2a3b",
  "title": "Service agreement — Jamie Rivera",
  "contact_id": "3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f",
  "recipients": [
    {
      "role_key": "client",
      "name": "Jamie Rivera",
      "email": "[email protected]"
    }
  ]
});
console.log(result);
centerfy contracts create '{"template_id":"2e4f6a8b-1c3d-4e5f-9a7b-8c9d0e1f2a3b","title":"Service agreement — Jamie Rivera","contact_id":"3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f","recipients":[{"role_key":"client","name":"Jamie Rivera","email":"[email protected]"}]}'

MCP tool: centerfy_contracts_create (see MCP server)

Response

{
  "status": "success",
  "contract": {
    "id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
    "title": "Service agreement — Jamie Rivera",
    "contract_number": "CTR-0042",
    "status": "draft",
    "source_type": "pdf",
    "contact_id": "3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f",
    "template_id": "2e4f6a8b-1c3d-4e5f-9a7b-8c9d0e1f2a3b",
    "sequential_signing": false,
    "has_prepared_pdf": true,
    "has_signed_pdf": false,
    "verification_code": null,
    "expires_at": null,
    "sent_at": null,
    "completed_at": null,
    "declined_at": null,
    "voided_at": null,
    "content": [],
    "fields": [
      {
        "id": "f0e1d2c3-b4a5-4968-8776-655443322110",
        "type": "signature",
        "page": 1,
        "x": 12.5,
        "y": 80,
        "w": 25,
        "h": 6,
        "recipientId": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
        "required": true
      }
    ],
    "recipients": [
      {
        "id": "7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d",
        "name": "Jamie Rivera",
        "email": "[email protected]",
        "role": "signer",
        "signing_order": 1,
        "status": "pending",
        "viewed_at": null,
        "signed_at": null,
        "declined_at": null,
        "decline_reason": null
      },
      {
        "id": "8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e",
        "name": "Account manager",
        "email": "",
        "role": "cc",
        "signing_order": 2,
        "status": "pending",
        "viewed_at": null,
        "signed_at": null,
        "declined_at": null,
        "decline_reason": null
      }
    ],
    "created_at": "2026-10-06T10:00:00.000Z",
    "updated_at": "2026-10-06T10:00:00.000Z"
  },
  "ready_to_send": true,
  "blockers": []
}

Errors

  • 400 — if template_id or contact_id is not a UUID, a role_key isn’t one of the template’s roles, or a recipient’s name or email is missing/invalid.
  • 404 — if the template or contact is not in this sub-account.

Notes

Returns 201. blockers lists what still prevents sending (no prepared PDF, no signers, a signer without an email or without a signature field) and ready_to_send is true when it is empty. Builder templates without a prepared PDF can only be sent from the app.

© 2026 Centerfy AI. All rights reserved.