Skip to main content

Errors

Every error from Kudos CRM uses the same JSON envelope:

{
"errors": [
{
"status": "401",
"code": "signature_invalid",
"title": "Unauthorized",
"detail": "X-Kudos-Signature did not match any active signing secret on this source.",
"meta": { "source_id": "src_…" }
}
]
}
FieldNotes
statusStringified HTTP status code. Mirrors the response line.
codeStable machine-readable identifier. Safe to switch on.
titleShort human label.
detailOne-sentence reason. Safe to surface in operator logs. Never carries tenant PII.
metaOptional structured context. Shape varies per code.

Multiple errors per response are possible on validation paths; the array always contains at least one entry.

Status code reference​

200 / 202 — Accepted​

The ingest endpoint returns 202 on first acceptance and on idempotent replay. The body distinguishes:

{ "data": { "received": true, "event_id": "evt_…", "duplicate": false } }
{ "data": { "received": true, "event_id": "evt_…", "duplicate": true } }

Treat both as success; do not retry on duplicate: true.

400 — Bad Request​

Malformed envelope: missing required field, invalid JSON, schema_version not understood. Discard the event; do not retry.

codeCause
invalid_jsonThe body is not parseable JSON.
envelope_invalidRequired envelope field missing or wrong type.
schema_version_invalidschema_version is not an integer or not understood.

401 — Unauthorized​

Authentication failed.

codeCause
signature_missingX-Kudos-Signature header absent.
signature_malformedHeader present but does not parse.
signature_invalidHMAC did not match any active signing secret on the source.
signature_stale|now - t| > 300. Re-sign with fresh timestamp and retry.
bearer_missing(Pull / reverse channel) Authorization header absent.
bearer_invalidBearer present but does not match an active key.
bearer_expiredBearer matched a key whose expires_at has passed.

403 — Forbidden​

Authentication succeeded, but the credential lacks the required scope.

codeCause
scope_missingBearer scopes do not include the one this endpoint requires.

404 — Not Found​

The route resolved to no resource. For ingest specifically:

codeCause
source_not_foundsource_id in the URL does not match any registered source. Returned even when the source_id is wrong but the signature would otherwise verify, so attackers cannot enumerate valid source_ids.

409 — Conflict​

The resource is in a state that does not permit the operation. On the management endpoints, e.g.:

codeCause
sync_not_configuredThe source has no sync_base_url or sync_api_key; pull-channel operations not possible.
source_inactiveThe source was deactivated by an operator. Reactivate or register a new one.

413 — Payload Too Large​

Body exceeds 1 MiB. Discard; do not retry with a larger body.

415 — Unsupported Media Type​

Content-Type is not application/json; charset=utf-8 (or equivalent). Discard.

422 — Unprocessable Entity​

Envelope is structurally valid but contents fail business rules.

codeCause
event_type_not_in_catalogevent_type is not one of the 36 documented types.
event_type_not_allowedevent_type is in the catalog but the source's allowed_event_types list excludes it.
tenant_external_ref_missingAn event that requires a tenant reference omitted tenant.external_ref.

429 — Too Many Requests​

You hit the per-source ingest rate limit (default 100 req/s, configurable per source). Honour Retry-After and back off.

502 — Bad Gateway​

Kudos CRM tried to call a downstream (your /v1/sync/manifest for example) and got a non-2xx or unreachable. Retry from the operator side or address the downstream issue.

503 — Service Unavailable​

Kudos CRM is degraded or in maintenance. The Retry-After header is set. Honour it and retry.

What to log​

For every non-2xx your producer sees, log at least:

  • the request event_id (or X-Kudos-Idempotency-Key for reverse channel)
  • the response status and code
  • the detail text
  • the URL

That four-field log line is enough for support to triage 99 % of integration tickets without asking you to re-run anything.