Errors
Every error response has the same JSON body:
{
"error": "Unauthorized",
"message": "A valid API key is required.",
"code": "unauthenticated",
"requestId": "0196f0a3-1d2e-7f40-8a5b-6c7d8e9f0a1b"
}
erroris the HTTP status text.messageexplains the problem. Do not parse it; the wording can change.codeis a stable, machine-readable value, present on every error. Branch oncode, not onmessage.requestIdidentifies the request in Harmony's logs.
Every response, successful or not, also carries the request ID in the x-request-id header. Include it when you contact Harmony support about a failed request.
Codes
unauthenticated(401): the API key is missing, unknown, or revoked.not_found(404): the operation or the resource does not exist.internal(500): Harmony failed to handle the request.
Other errors use the status text as their code, such as bad_request for an invalid request body. New codes can be added, so handle codes you do not recognize by their HTTP status.
Status codes
400: the request is invalid. Fix it before sending it again.401,404: see the codes above.5xx: Harmony failed to handle the request. Retrying with a delay is safe for reads, and for imports withoutassignmentOptions.workflowId. Don't retry an import that enrolls contacts automatically, since it can place two calls: first check what arrived withGET /api/v1/contacts?assignedWorkflowId=<workflowId>, then resend only the missing contacts.