Skip to content

Errors, revisions, and safe retries

Read both the HTTP status and response body. Log the operation ID, resource ID, HTTP status, and requestId. Redact tokens and patient data.

{
"error": {
"code": "revision_conflict",
"message": "The package revision has changed.",
"issues": [{ "field": "revision", "message": "Read the current revision." }]
},
"requestId": "synthetic-request-id"
}

This is a synthetic shape example, not an actual response. Match stable error.code values, not translated messages. Field details can appear in error.field and error.issues[].field.

HTTP What to do
400 Correct malformed JSON, path, query, or request shape
401 Verify the token and host; obtain valid authentication
403 Check scope, workspace selection, membership, and role
404 Verify the resource ID and current workspace
409 Read current state before deciding the next action
413 Reduce the request to the documented body limit
415 Use the expected content type
422 Correct business or data validation issues
428 Supply the required revision or idempotency precondition
500, 502, 503 Preserve evidence; determine if an external action occurred before retrying

An edge or network failure can return HTML rather than ApiError. Capture status and safe response headers, including X-Request-ID when present. Do not assume every error body is JSON.

Read a package and retain its ETag. Use the exact value in If-Match for a revision. If the server returns revision_conflict, read the package again and resolve the change. Never overwrite another revision with a guessed ETag.

Validation belongs to one revision and context. An edit invalidates it. A previously valid package can require a new check if its referenced document or context changes.

Use Idempotency-Key where required by the operation. The key must contain 8–128 allowed characters. UUID strings are suitable.

Store the key before you send the request, alongside the exact request bytes and target operation. For a retry, keep the same key, actor, path parameters, and body. With raw JSON input, keep the same bytes.

Situation Safe action
Response received and intent complete Store the result; do not create another intent
Lost response Read the resource; retry only the same intent with the same key when state permits
idempotency_key_reused Stop: the key was used for different content
idempotency_in_progress Wait and inspect state
submission_outcome_unknown or provider_outcome_unknown Reconcile with external evidence
New, deliberately different business intent Create a new key

The contract does not publish an expiry window for reusing confirmed receipts. Never assume an old key becomes available. A new key cannot bypass an Unknown package or provider state.

A timeout can occur after the external system received a request. Keep Unknown blocked until reconciliation. For RIPS, provide a known CUV and attempt ID. For health documents, use the reconciliation operation described in that document’s reference.

Use bounded backoff for reads. The current contract does not promise webhooks or a fixed polling interval. Honor 429 and Retry-After if they occur. These are technical controls; they do not create per-request charges.