Read the status and stable tag
Decode the response by its HTTP status and _tag, not by matching the prose of an error message. For example, an authenticated caller without the required permission receives:
{
"_tag": "Forbidden",
"permission": "project.create"
}Every response carries an x-request-id header. Record that opaque identifier with the operation, status, and time when asking Cantora to investigate; do not attach the API key or an unredacted request body.
Common statuses
| Status | Meaning | Caller action |
|---|---|---|
400 | The path, headers, query, or JSON body failed the published schema. | Correct the request; repeating it unchanged cannot succeed. |
401 | The request did not authenticate a valid ServicePrincipal. | Check the Bearer header and credential lifecycle. |
403 | The principal lacks the named permission at this scope. | Use the intended principal or request the minimum required Grant. |
404 | The addressed resource is absent or cannot be disclosed at this scope. | Verify every parent identifier and the caller's scope. |
409 | The requested create conflicts with current resource state. | Read the existing resource and choose whether to reuse or change the request. |
412 | An optimistic-concurrency precondition no longer matches. | Read the returned current state, decide again, and submit its ETag. |
500 | The server failed unexpectedly before it could return the operation's declared result. | Record the request ID and time, then follow the operation-specific recovery guidance below. |
Re-plan after a precondition failure
Agent Release activation uses a strong ETag so two writers cannot silently overwrite each other. A stale request receives the current release identifier and ETag:
{
"_tag": "PreconditionFailed",
"resource": "agent",
"currentAgentReleaseId": "agent_release_example",
"currentEtag": "\"4\""
}Do not retry with the new ETag automatically. Read the current release, decide whether the requested Agent Version should still replace it, then submit a new conditional activation.
Recover according to the operation
The documented 4xx responses require a caller decision or a corrected request. Do not retry them on a timer. A transport interruption or server-side 5xx may be transient; use bounded exponential backoff with jitter only when the operation can be retried safely.
- Reads can be retried because they do not change server state.
- Publishing the same Agent Version is content-addressed and returns whether it was created or reused. Reissue the exact request when its response is lost.
- Agent Release activation is conditional. Reissuing the exact request either activates it or returns the current release and ETag so the caller can decide again.
- Do not automatically retry a create that mints a new resource identifier. Most create operations have no lookup by caller-supplied key, so a lost response cannot be reconciled safely. Record the request ID and time and ask Cantora to determine whether it committed.
- Never retry a credential-issuing or credential-rotation operation just to recover a response. A committed credential is disclosed once; inspect the current resource state and make a deliberate replacement decision.
See Authentication for credential failures and secret handling.