Signal failures are now returned in the response body
The Signals API now returns HTTP 200 for any retrievable signal, including failed ones, and conveys failure in the response body with a new retryable field instead of a 422 or 500 status code.
The Signals API now returns HTTP 200 for any signal it can retrieve — including failed ones — and conveys failure in the response body instead of an error status code.
What changed
GETandPOST /v1/companies/signals(and/:id), and the contacts equivalents, now return HTTP200whenever the signal is retrievable, regardless of its processing state.- A failed signal is reported in the body as
status: "failed"together with a newretryableboolean:retryable: true— transient failure; the request may succeed if retried (previously surfaced as HTTP500).retryable: false— non-retryable failure such as validation or a rate limit; do not retry (previously surfaced as HTTP422).
- Failed signals no longer return
422or500. Genuine request errors — malformed body, bad input, authentication, or not-found — still return their normal400,401,404, and422codes.
{
"id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"status": "failed",
"retryable": false,
"error": "LinkedIn data is currently unavailable due to rate limits.",
"errorCode": "LINKEDIN_RATE_LIMIT_EXCEEDED"
}Who is affected
Developers and RevOps teams that call the Signals API directly and branch on the HTTP status code to detect failed signals.
Customer action
If your integration treats a 422 or 500 from a signal endpoint as a signal failure, update it to:
- Treat a
200as a successful retrieval of the signal, then inspectbody.status. - When
body.statusis"failed", readbody.retryableto decide whether to retry: retry only whenretryableistrue, using your existing backoff. - Continue to handle
400,401,404, and422as genuine request errors — these are unchanged.
This is a single coordinated cut with no backward-compatibility shim, so make the change before relying on the new behavior.