Contracts API
Create and update contracts
Both endpoints need the write:contracts scope.
POST /api/v1/contracts
Records what was agreed and when it runs out.
POST /api/v1/contracts HTTP/1.1
Host: agentlyleads.com
Authorization: Bearer alk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{ "fromDeal": true, "dealId": "cmq2deal0alk34567890", "status": "ACTIVE", "startsAt": "2026-01-01", "endsAt": "2026-12-31", "autoRenew": true }| Field | Notes |
|---|---|
title | Required unless fromDeal is true. Up to 200 characters |
fromDeal | Copy title, company, owner and value from the deal in dealId. The term is left empty, because only a person knows when it actually starts; anything else you pass wins over the copy |
dealId | The deal it came out of |
companyId | The company holding the contract |
ownerId or ownerEmail | An active workspace member. ownerId: null leaves it unowned |
status | DRAFT (default), ACTIVE, EXPIRED or CANCELLED. Only ACTIVE contracts get a renewal alert |
value | Contract value, zero or more |
startsAt, endsAt | Whole days, YYYY-MM-DD. endsAt cannot be before startsAt |
autoRenew | Whether the term rolls over on its own |
notes | Up to 5000 characters |
A renewal is not a separate record. It is an alert on endsAt, sent once, thirty days out. Each call creates a new contract, so check the list before retrying.
Returns 201 with { "contract": { ... } } in the shape of the Contract object.
POST /api/v1/contracts/{id}/status
Moves a contract between DRAFT, ACTIVE, EXPIRED and CANCELLED, and can reset the term in the same call.
POST /api/v1/contracts/cmq2ctr00alk34567890/status HTTP/1.1
Content-Type: application/json
{ "endsAt": "2027-12-31" }| Field | Notes |
|---|---|
status | The new status |
startsAt, endsAt | YYYY-MM-DD, or null to clear. Checked against the term as it will stand, so moving one end cannot put the end before the start |
autoRenew | |
notes | Replaces the notes. null clears them |
Send at least one field. Moving endsAt is what a renewal looks like from outside, so it clears renewalNotifiedAt and the new term gets its own alert.
Errors
| Status | When |
|---|---|
400 | A missing title, a bad date, an end before the start, or an owner who is not an active workspace member |
403 | The key lacks write:contracts |
404 | No contract with that ID, or a dealId or companyId that is not in your workspace |