Skip to content

Errors and permissions

401 and 403 are not interchangeable, and a 409 is not a retry. Reading the status correctly cuts most investigations to one step.

StatusWho owns the fixFirst check
400The callerA required field is missing — often portalID or the ticket id
401CredentialIs the credential present, unexpired, and bound to this target?
403ConfigurationDoes this identity have the role, the portal and the resource?
404EitherWrong path, or a resource outside the caller’s scope
409StateA run or action already exists; wait or inspect, do not retry
422The callerThe body parsed, but does not match the target’s schema
429CapacityA rate-limited mount; back off
503AdministratorA scope or dependency could not be resolved
CodeMeaning
WEBHOOK_API_KEY_REQUIREDThe route reached the handler without a resolved key policy
WEBHOOK_API_KEY_INVALIDKey unknown or revoked
WEBHOOK_TARGET_FORBIDDENKey exists but is not bound to this target or route
WEBHOOK_MODEL_FORBIDDENKey is bound to a different model id
WEBHOOK_WORKFLOW_FORBIDDENKey is bound to a different workflow
WEBHOOK_EVENT_OVERRIDE_FORBIDDENThe request tried to choose an event; the key decides it
WEBHOOK_POLICY_NOT_ALLOWEDThe profile behind the key is inactive or no longer authorised
WEBHOOK_DELIVERY_PAYLOAD_MISMATCHIdempotency-Key reused with a different body
WEBHOOK_DELIVERY_KEY_MISMATCHIdempotency-Key reused by a different key
CodeMeaning
MAIA_TOKEN_REQUIREDNo MAIA token on a protected surface
MAIA_TOKEN_INVALIDSignature, expiry, or format rejected
MAIA_SESSION_REVOKEDThe token was validly signed but its session was revoked
TECHNICIAN_ROLE_REQUIREDThe identity is not an SDP technician
REQUESTER_ROLE_REQUIREDThe identity is not an SDP requester
FORBIDDENAuthenticated, but not permitted on this record
FEATURE_DISABLEDThe feature is switched off for this installation or portal
CodeMeaning
RUN_ALREADY_ACTIVEOne run per conversation at a time; wait for it to settle
RUN_NOT_FOUNDUnknown run id, or one outside the caller’s scope
ACTION_NOT_FOUND, ACTION_ID_REQUIREDThe approval id is missing or unknown
ACTION_ALREADY_DECIDEDSomeone already approved or rejected it
APPROVAL_DECISION_REQUIREDNeither approve nor reject was supplied
APPROVAL_EXPIREDThe approval outlived its window; the run will not resume
CodeMeaning
SDP_SCOPE_UNAVAILABLEThe ticket-search portal scope could not be resolved
CONVERSATION_NOT_FOUNDUnknown or out-of-scope conversation

The v1 routes answer with { "error": { "code": …, "message": … } }. A strict parser will still break on two families:

  • legacy flow handlers — for example /api/v1/rewriteMessageFromTechnician — can answer { "error": "<string>" };
  • a few internal admin handlers answer { "error": "Internal Server Error" } on an unexpected failure.

Branch on code when it exists, and treat a string error as an opaque message.

A valid credential refused on a valid route means one of four things, in order of likelihood:

  1. Role — the account is not the type this surface serves.
  2. Portal — the record lives in another helpdesk; MAIA re-resolves the portal per request.
  3. Scope — the agent’s knowledge space or the tool’s access scope excludes this actor.
  4. Policy — an approval or automation policy forbids the operation outright.

Never work around a 403 by supplying a different portal identifier. The check exists because the caller asked for something it does not own.

Send: timestamp with timezone, route, status, and the error code. Never send cookies, tokens, keys, full request bodies, or customer content. A code plus a route is enough to reproduce nearly everything on this page.

Authentication · API reference · Troubleshooting: connections · Troubleshooting: permissions