Error responses
JavaScript{
"message": "human-readable summary",
"errors": [
{ "path": "field", "message": "...", "errorCode": "...", "uuid": "..." }
]
}5xx → the body is always
{ "message": "An unexpected error has occurred." }.401,404, and auth failures → empty body, status only.Request that fails schema validation (missing or wrong-typed field, malformed UUID, unknown enum value) →
422.Valid token, insufficient scope →
403.
Status codes in use: 200, 201, 204, 400, 401, 403, 404, 409, 412, 422, 429, 500.
Rate limits
Rate limiting is enforced at the edge:
Roughly 20 requests per second per client IP, with a large burst allowance.
Over the limit →
429with a plain-text body (not JSON).No
Retry-Afterand noRateLimit-*headers. Back off with jitter on any429.Individual requests may run up to a 10-minute server timeout before responding.
The SMS provider has its own rate limits, which the API absorbs internally with retry and backoff — you may occasionally see a slower response instead of an error.
Known limitations
Limitation | Work around it by |
|---|---|
No | Use |
No webhook signature or auth header | Secret-in-URL; treat reference payloads as fetch triggers |
No webhook retry | Acknowledge fast, queue, monitor errors, run a reconciliation poll |
| Idempotency keyed on the message UUID; branch on |
| Page |
No | Use message |
One OAuth client per Leadferno account | Separate accounts for staging vs. production |
Refresh tokens rotate, and the previous one is invalidated immediately | Serialize refreshes; persist the new token every time |
| Always send |
| Back off with jitter |
| Expect the surface to change; watch for deprecation notices |
Getting help
Interactive reference: https://api.leadferno.com/v0/docs/
For anything the reference doesn't answer — a payload shape, a UUID that doesn't look right, a limitation that's blocking you — contact us.