Statuses
Each workspace has its own list of lead statuses, in order. An entry has a value, a label and a color:
valueis what leads store instatus: 1 to 50 characters, exact and case-sensitive, unique in the list. Surrounding spaces are removed.labelis the name the dashboard shows, at most 50 characters. Leave it empty to keep the built-in name of a default status, or to show the value itself.coloris one ofgrey,blue,green,red,violet,amber,pinkorteal.
A workspace starts with five defaults: new (grey), contacted (blue), qualified (green), disqualified (red) and converted (violet).
Exports and webhooks carry the value, not the label, so renaming a status in the dashboard never breaks a scenario.
A lead may hold a value that is not in the list. It keeps it, and the list reports it as unlisted. The API accepts any status up to 50 characters.
List statuses
Section titled “List statuses”GET /statusesAny member and any API key that can read leads can list the statuses.
Response 200 OK:
{ "statuses": [ { "value": "new", "label": "", "color": "grey", "count": 120 }, { "value": "contacted", "label": "", "color": "blue", "count": 48 }, { "value": "meeting", "label": "Meeting booked", "color": "amber", "count": 9 } ], "unlisted": [{ "value": "lost", "count": 3 }]}statuses is the list in order, with the number of leads that hold each value. unlisted holds the values leads hold that the list does not name, with their counts.
Replace statuses
Section titled “Replace statuses”PUT /statusesReplaces the whole list with the entries you send, in their order. Only the workspace owner and its admins can replace it; on the Free plan, only the owner.
{ "statuses": [ { "value": "new", "label": "", "color": "grey" }, { "value": "contacted", "label": "Reached out", "color": "blue" }, { "value": "meeting", "label": "Meeting booked", "color": "amber" } ]}Rules:
- 1 to 30 entries.
newmust stay in the list: it is the status of leads created without one.- Values are unique;
Newandneware two different values.
A list that breaks a rule returns 400 with a message naming it.
To rename a status, change its label and keep its API value. Sending a different value in PUT removes the old entry and adds a new one; it does not rename the value on existing leads. Those leads keep the old value, which is reported as unlisted if you omit it from the replacement list. Replacing the list never changes a lead. No webhook fires.
Response 200 OK: the new list, as GET /statuses returns it.
Sort leads by status
Section titled “Sort leads by status”GET /leads?sort_by=status lists leads in the order of your status list, then the unlisted values, by value. sort_order=desc reverses that order.
Endpoint reference
Section titled “Endpoint reference”Paths include the /api/v1 prefix. Schema fields marked required must be present; other fields may be omitted. Nullable values are shown explicitly.
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/statuses |
List lead statuses |
| PUT | /api/v1/statuses |
Replace lead statuses |
GET /api/v1/statuses
Section titled “GET /api/v1/statuses”The workspace’s status list in order, each entry with its lead count, then the values leads hold that the list does not name. A workspace that never replaced its list gets the five defaults. With filter, counts cover all leads matching the same filters as GET /leads, across all pages. unlisted contains only status values held by those matching leads. The configured entries and their order do not change.
Accepted authentication: ApiKey or BearerKey.
| Parameter | In | Required | Schema | Description |
|---|---|---|---|---|
filter |
query | no | {"type":"array","items":{"type":"string"}} |
Optional. The filter expressions of GET /leads, with the same rules and the same 400 for an invalid one. Without it, counts cover every lead of the workspace. |
| Status | Description | Content type / schema | Headers |
|---|---|---|---|
| 200 | Success | application/json: LeadStatuses |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 400 | Request rejected. | application/json: Error400 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 401 | Invalid or missing credentials. | application/json: Error401 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 403 | Permission denied. Create lead also returns leads_limit_reached when the storage quota is reached. lead_access_required: an admin without lead access from the workspace owner, on the dashboard or an assistant connection. That admin can still manage API keys, webhooks and scoring rules. API keys never get it. workspace_read_only: the workspace is read-only because its owner owns another Free workspace ranked before it (their first workspace, otherwise the oldest), and only one Free workspace per owner stays editable. Editing resumes when this workspace moves to Pro or Scale, or when its owner no longer owns any Free workspace ranked before it. Every change to leads, scoring rules and the status list is refused, from an API key, the dashboard or an assistant connection. Reading, export, members, API keys, webhooks and assistant connections still work. | application/json: Error403 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers.; WWW-Authenticate: {"type":"string"} Present for MCP insufficient_scope. |
| 413 | Body exceeds 1 MiB (10 MiB for /leads/batch). | application/json: Error413 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 429 | Rate limit exceeded. Retry-After is always present. Quota exhaustion (computed or cached) includes all four X-RateLimit-* headers. The earlier per-key admission-work refusal can omit those quota headers. | application/json: Error429 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows. Present on computed/cached quota exhaustion; may be absent on earlier admission-work refusal.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window. Present on computed/cached quota exhaustion; may be absent on earlier admission-work refusal.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds. Present on computed/cached quota exhaustion; may be absent on earlier admission-work refusal.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers.; Retry-After: {"type":"integer"} Seconds until retry. Early admission refusals may omit the quota headers. |
| 500 | Internal error. | application/json: Error500 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 503 | Authentication unavailable. | application/json: Error503 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
PUT /api/v1/statuses
Section titled “PUT /api/v1/statuses”Replaces the whole list. Values are trimmed, 1 to 50 characters, distinct and case-sensitive; labels at most 50 characters; at most 30 entries; new must stay. Leads keep their values: a value removed from the list shows as unlisted. Returns the new list as GET does.
Accepted authentication: ApiKey or BearerKey.
| Request content type | Required | Schema |
|---|---|---|
application/json |
yes | ReplaceLeadStatusesRequest |
| Status | Description | Content type / schema | Headers |
|---|---|---|---|
| 200 | Success | application/json: LeadStatuses |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 400 | Request rejected. | application/json: Error400 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 401 | Invalid or missing credentials. | application/json: Error401 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 403 | Permission denied. Create lead also returns leads_limit_reached when the storage quota is reached. lead_access_required: an admin without lead access from the workspace owner, on the dashboard or an assistant connection. That admin can still manage API keys, webhooks and scoring rules. API keys never get it. workspace_read_only: the workspace is read-only because its owner owns another Free workspace ranked before it (their first workspace, otherwise the oldest), and only one Free workspace per owner stays editable. Editing resumes when this workspace moves to Pro or Scale, or when its owner no longer owns any Free workspace ranked before it. Every change to leads, scoring rules and the status list is refused, from an API key, the dashboard or an assistant connection. Reading, export, members, API keys, webhooks and assistant connections still work. | application/json: Error403 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers.; WWW-Authenticate: {"type":"string"} Present for MCP insufficient_scope. |
| 413 | Body exceeds 1 MiB (10 MiB for /leads/batch). | application/json: Error413 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 429 | Rate limit exceeded. Retry-After is always present. Quota exhaustion (computed or cached) includes all four X-RateLimit-* headers. The earlier per-key admission-work refusal can omit those quota headers. | application/json: Error429 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows. Present on computed/cached quota exhaustion; may be absent on earlier admission-work refusal.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window. Present on computed/cached quota exhaustion; may be absent on earlier admission-work refusal.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds. Present on computed/cached quota exhaustion; may be absent on earlier admission-work refusal.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers.; Retry-After: {"type":"integer"} Seconds until retry. Early admission refusals may omit the quota headers. |
| 500 | Internal error. | application/json: Error500 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
| 503 | Authentication unavailable. | application/json: Error503 |
X-RateLimit-Limit: {"type":"integer"} Request budget of the binding limit named by X-RateLimit-Scope. Window: 10 minutes. Per credential: Free 250, Pro 2500, Scale 5000. Per account: Free 2500, Pro 62500, Scale 250000, or more when the account keeps more keys and assistant connections than its plan allows.; X-RateLimit-Remaining: {"type":"integer"} Remaining requests in the current window.; X-RateLimit-Reset: {"type":"integer"} Window reset, Unix seconds.; X-RateLimit-Scope: {"type":"string","enum":["credential","account"]} Which limit the other X-RateLimit-* headers describe: credential (the API key, assistant connection or dashboard session) or account. Present with the other X-RateLimit-* headers. |
Schemas and errors
Section titled “Schemas and errors”Schema names in the endpoint tables refer to the definitions below. oneOf means exactly one alternative; anyOf means at least one. Error alternatives list the exact error and code values.
Error400
Section titled “Error400”{"oneOf":[{"type":"object","properties":{"error":{"const":"bad_request"},"code":{"const":"bad_request"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false},{"type":"object","properties":{"error":{"const":"invalid_scoring_expression"},"code":{"const":"invalid_scoring_expression"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false},{"type":"object","properties":{"error":{"const":"scoring_rules_limit_reached"},"code":{"const":"scoring_rules_limit_reached"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false},{"type":"object","properties":{"error":{"const":"assignee_not_member"},"code":{"const":"assignee_not_member"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false}]}
Error401
Section titled “Error401”{"oneOf":[{"type":"object","properties":{"error":{"const":"unauthorized"},"code":{"const":"unauthorized"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false},{"type":"object","properties":{"error":{"const":"invalid_token"},"code":{"const":"invalid_token"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false}]}
Error403
Section titled “Error403”{"oneOf":[{"type":"object","properties":{"error":{"const":"forbidden"},"code":{"const":"forbidden"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false},{"type":"object","properties":{"error":{"const":"insufficient_scope"},"code":{"const":"insufficient_scope"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false},{"type":"object","properties":{"error":{"const":"leads_limit_reached"},"code":{"const":"leads_limit_reached"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false},{"type":"object","properties":{"error":{"const":"lead_access_required"},"code":{"const":"lead_access_required"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false},{"type":"object","properties":{"error":{"const":"workspace_read_only"},"code":{"const":"workspace_read_only"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false}]}
Error413
Section titled “Error413”{"oneOf":[{"type":"object","properties":{"error":{"const":"payload_too_large"},"code":{"const":"payload_too_large"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false}]}
Error429
Section titled “Error429”{"oneOf":[{"type":"object","properties":{"error":{"const":"rate_limit_exceeded"},"code":{"const":"rate_limit_exceeded"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false}]}
Error500
Section titled “Error500”{"oneOf":[{"type":"object","properties":{"error":{"const":"internal_error"},"code":{"const":"internal_error"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false}]}
Error503
Section titled “Error503”{"oneOf":[{"type":"object","properties":{"error":{"const":"internal_error"},"code":{"const":"internal_error"},"message":{"type":"string"}},"required":["error","code","message"],"additionalProperties":false}]}
LeadStatus
Section titled “LeadStatus”{"type":"object","description":"One entry of the workspace's status list.","additionalProperties":false}
| Field | Required | Schema |
|---|---|---|
value |
yes | {"type":"string","minLength":1,"maxLength":50,"description":"The value leads store in status. Exact and case-sensitive; surrounding spaces are removed."} |
label |
no | {"type":"string","maxLength":50,"description":"The name the dashboard shows. Empty: the built-in name of a default status, or the value itself."} |
color |
yes | {"type":"string","enum":["grey","blue","green","red","violet","amber","pink","teal"]} |
LeadStatuses
Section titled “LeadStatuses”{"type":"object","additionalProperties":false}
| Field | Required | Schema |
|---|---|---|
statuses |
yes | {"type":"array","items":{"$ref":"#/components/schemas/ListedLeadStatus"},"description":"The workspace's list, in order."} |
unlisted |
yes | {"type":"array","description":"Values held by leads that the list does not name, with their lead counts, in value order.","items":{"type":"object","properties":{"value":{"type":"string"},"count":{"type":"integer"}},"required":["value","count"],"additionalProperties":false}} |
ListedLeadStatus
Section titled “ListedLeadStatus”{"type":"object","description":"A list entry with the number of the workspace's leads that hold its value.","additionalProperties":false}
| Field | Required | Schema |
|---|---|---|
value |
yes | {"type":"string","minLength":1,"maxLength":50,"description":"The value leads store in status. Exact and case-sensitive; surrounding spaces are removed."} |
label |
yes | {"type":"string","maxLength":50,"description":"The name the dashboard shows. Empty: the built-in name of a default status, or the value itself."} |
color |
yes | {"type":"string","enum":["grey","blue","green","red","violet","amber","pink","teal"]} |
count |
yes | {"type":"integer"} |
ReplaceLeadStatusesRequest
Section titled “ReplaceLeadStatusesRequest”{"type":"object"}
| Field | Required | Schema |
|---|---|---|
statuses |
yes | {"type":"array","maxItems":30,"items":{"$ref":"#/components/schemas/LeadStatus"},"description":"The whole list, in order: 1 to 30 entries with distinct values, including new."} |