The error envelope
HeadHoncho API errors all have one shape. The HTTP status says the class of refusal, and the body names the reason:
{
"error": {
"code": "invalid",
"message": "Some fields were refused. See fields.",
"fields": {
"client_phone": "This is required."
},
"docs": "https://headhoncho.app/docs/api/errors#invalid"
}
}
codeis the stable name to branch on.messageis the sentence to show a person.fieldsnames each refused field, on a 422 only.docslinks to the entry for the code on this page.
The MCP server prints the same code. A refusal always names its reason.
Every error code
Each code is an anchor, so https://headhoncho.app/docs/api/errors#invalid goes straight to its entry.
missing_key
Status 401. Send your key as Authorization: Bearer hh_live_... Every endpoint can return it.
unknown_key
Status 401. That key is not one we issued, or it was revoked. Every endpoint can return it.
expired_token
Status 401. That token has expired. Refresh it, or connect the app again. Every endpoint can return it.
no_access
Status 403. This credential does not reach that. Ask the person who made it for access. Returned by 15 of the 16 endpoints.
read_only
Status 403. This credential may read this area but not change it. Returned by 6 of the 16 endpoints.
not_found
Status 404. No such record in the companies this credential reaches. Returned by 15 of the 16 endpoints.
out_of_scope
Status 404. No such company in the companies this credential reaches. Returned by 7 of the 16 endpoints.
unknown_endpoint
Status 404. No such endpoint. GET /api/v1/ lists every one. Returned by 0 of the 16 endpoints.
unknown_command
Status 404. No such command. GET /api/v1/ lists every one. Returned by 0 of the 16 endpoints.
invalid
Status 422. Some fields were refused. See fields. Returned by 15 of the 16 endpoints.
missing_idempotency_key
Status 400. Send an Idempotency-Key header on every command. Returned by 6 of the 16 endpoints.
idempotency_mismatch
Status 409. This Idempotency-Key was used with a different body. Returned by 6 of the 16 endpoints.
rate_limited
Status 429. Too many calls this minute. Wait and try again. Every endpoint can return it.
not_connected
Status 409. This company has not connected that provider yet. Returned by 3 of the 16 endpoints.
Rate limits
Every call counts against the allowance of the key or connected app that made it. The allowance is per minute and depends on the cost of the call:
| Cost | Calls a minute | Endpoints |
|---|---|---|
| read | 300 | Whoami, List jobs, Get job, Get job history, List tables, Read table, Get job conversion, Get click id report |
| write | 60 | Create job, Update job, Change job status, Assign worker, Unassign worker, Add job note |
| export | 10 | Export table, Export click id report |
Every answer carries the headers that tell you where you stand:
X-RateLimit-Limit: the calls a minute this credential may make at this cost.X-RateLimit-Remaining: how many are left in the current minute.Retry-After: on a 429, the seconds to wait before trying again.
Over the limit, the call is refused with status 429 and `rate_limited`. Wait for Retry-After and send it again. A command is safe to resend with the same Idempotency-Key; see the model. Keys and their access are on API keys.