Skip to content

Errors, retries, and reconciliation

  1. Check the HTTP status.
  2. Parse the response schema declared by that operation.
  3. Capture ztl-request-id from the header and any ztlRequestId in the body.
  4. Log the operation, safe partner reference, resource ID, failure code, and request ID without secrets or personal data.

Do not assume every operation has one global error shape.

A 400 Bad Request can use a general failure object:

{
"failure": "INVALID_ACCOUNT",
"ztlRequestId": "350eb968-f4cf-474c-8cf2-f8068294d364",
"message": "The provided account was invalid"
}

A 422 Unprocessable Content identifies invalid fields. Some operations return an array:

[
{
"code": "InvalidBBAN",
"reason": "Invalid BBAN",
"path": ".from.account"
},
{
"code": "InvalidDueDate",
"reason": "Due date cannot be in the past",
"path": ".dueDate"
}
]

Other operations declare a single validation object. Follow the generated operation schema before parsing.

A 500 Internal Server Error uses the current general-error fields:

{
"ztlRequestId": "350eb968-f4cf-474c-8cf2-f8068294d364",
"message": "The underlying reason for the error"
}

Do not show raw internal messages to end users.

HTTP status Handling
401 Invalidate the cached token, obtain one replacement, and retry once. Stop if credentials are still rejected.
404 Recheck the environment, operation path, and stored resource ID. Do not create a replacement merely because a status lookup failed.
409 Treat as concurrent or conflicting state. Fetch the latest resource and approval state, reconcile, then use a bounded retry only if the operation remains valid.
5xx Retry safe reads with bounded backoff. Reconcile creates and approvals before any resend because the server may have committed them.

Network timeouts and disconnects are also ambiguous outcomes. Use resource IDs, end-to-end IDs, partner references, status operations, and request IDs to determine what happened. Escalate an unresolved create or approval instead of blindly repeating it.

ZTL can add enum values. Preserve the raw value, map unknown values to a safe fallback in your UI, and continue polling unless the response declares a final state. Do not fail deserialization solely because a new status, reason, or failure code appears.

Continue scheduled reconciliation until non-final resources reach a final state.