Errors

For engineers writing error handling against the Quant Flow Platform. The error envelope, what each HTTP status means, the documented errors per area with the correct client action, and how a failed operation is reported after acceptance.

Who this is for

Integration engineers building error handling and operational alerting, and reviewers checking that every failure has a defined client response.

There are two kinds of failure:

  1. A refused request. The HTTP call fails with a 4xx or 5xx and the error envelope below. Nothing was accepted.
  2. A failed operation. The HTTP call succeeded (202), and the operation later ended in FAILED or CANCELLED. The failure is reported on the operation and by webhook. No HTTP error is returned. See Failed operations.

The error envelope

Every refused request returns a JSON body with four fields:

FieldTypeMeaning
timestampstringWhen the error was produced, in UTC.
statusintegerThe HTTP status code, repeated in the body.
errorstringThe HTTP reason phrase, for example Bad Request.
messagestringA description for a human reader.
{
  "timestamp": "2026-08-03T09:24:11.482Z",
  "status": 400,
  "error": "Bad Request",
  "message": "The 'Idempotency-Key' header is required."
}

Branch on the HTTP status and, where present, on code or documented extra fields. Never parse message. Its wording is for people and can change.

Variations to handle

VariationWhereWhat to do
timestamp formatMost endpoints use ISO 8601 with a trailing Z. Webhook, delivery history and some identity errors use yyyy-MM-dd HH:mm:ss.SSS in UTC, with no T and no offset.PayScript uses ISO 8601 UTC with fixed milliseconds. Treat timestamp as a string. Parse it only if you need it, and accept both documented formats.
code and detailsPolicy, template and approval endpoints. code is VALIDATION_FAILED on some 400 responses and IDEMPOTENCY_CONFLICT on a 409. details is an array of field-level messages on some VALIDATION_FAILED responses.Use code when present. Show details to the operator.
Conflict bodyPOST /api/customers and POST /api/accounts. A 409 for an existing reference adds customerRef or accountRef, and existingStatus.Use existingStatus to reconcile. See Idempotency and retries.
No token on policy endpointsA request that carries a token that cannot be parsed, or that lacks sub or tenant_id, returns a default error body with a path and no useful message.Branch on the 401 status only.
500Unexpected service failures commonly use System error occurred. Handle the actual returned status/body; gateways and individual endpoints can return a different envelope.Retry with backoff. Quote the timestamp to support.

There is no platform-wide machine-readable error code. Branch on HTTP status and the endpoint's documented structured fields. Preserve unfamiliar fields for diagnostics; do not require one universal error-code field.

Record the request time, endpoint, HTTP status and any returned correlation headers. Also retain transaction or request identifiers from successful submissions; the contract does not guarantee a correlation field on every error.

Status codes and client action

StatusMeaningClient action
400 Bad RequestThe request is invalid: a missing or malformed field, a missing Idempotency-Key, a disallowed state change on some endpoints, or a filter or paging value outside its range. The message names the field.Fix the request. Do not retry unchanged.
401 UnauthorizedNo token, or a token that failed verification. On sign-in, wrong credentials.Use the user refresh or machine-client token-acquisition flow once, then escalate persistent rejection. See Authentication.
403 ForbiddenThe caller is authenticated but lacks the permission, a path names another organisation, or separation of duties blocked the action.Do not retry. Check the caller's role.
404 Not FoundThe resource does not exist in the caller's organisation. A resource in another organisation also returns 404.Do not retry, except for the lock case on POST /api/transactions.
409 ConflictEither the same Idempotency-Key is still being processed, or the resource's current state does not allow the request.In-flight key: wait and retry with the same key. State conflict: read the resource and reconcile.
415 Unsupported Media TypeGET /api/users/{id} without Content-Type: application/json.Send the header.
422 Unprocessable ContentThe request is well-formed but cannot be applied: an idempotency key reused with a different payload, a state transition that is not allowed, a parameter that does not fit its declaration, or an account with no wallet yet.Do not retry unchanged.
429 Too Many RequestsThe organisation's webhook replay budget is exhausted.Retry later. See Rate limits.
500 Internal Server ErrorAn unexpected failure.Use bounded backoff for reads or supported idempotent writes, preserving the original key/body. Reconcile other writes before retrying; a 500 does not prove rollback.
503 Service UnavailableThe LEI registry could not be reached to verify an institution.Retry with backoff.

Error catalogue by area

Each table lists the errors the API Reference documents for that area, beyond common 401 and 500 responses. Bootstrap authority and service enforcement vary as described in Authentication; use the endpoint-specific reference.

Sign-in

EndpointStatusCauseClient action
POST /api/auth/login, new-password, activate400Body failed validation (Invalid Request parameter. {field} or Malformed JSON request).Fix the request.
Same401Wrong credentials, no organisation, or user not ACTIVE. Always Invalid credentials.Check credentials and user status. Do not loop.
POST /api/auth/refresh401Refresh token expired or revoked, or account disabled.Sign in again.

Organisation access: team members, roles and approval groups

StatusCauseClient action
400A path id is not a UUID, an unknown filter value, a name that is blank or too long, an unknown permission name (Unknown permissions: {names}.), editing a platform role, removing or changing yourself or the organisation owner.Fix the request.
401No usable token, or the caller's own status is not ACTIVE (Your access has been revoked.).Sign in again, or contact your administrator.
403The path organisation is not the caller's own (Invalid tenant id), the caller lacks the permission (for example member:remove, role:create, group:manage), or the change would grant a permission the caller does not hold.Do not retry. Use a user with the permission.
404No such user, role, group or organisation.Do not retry.
409Email already registered, role name reserved or in use, group key in use, or the approval group is deactivated.Reconcile with the existing record.
500A sort parameter named a property that does not exist.Use only the documented sort properties. See Pagination and filtering.

Customers and accounts

EndpointStatusCauseClient action
POST /api/customers400Missing or invalid field, or Idempotency-Key missing, blank or over 255 characters.Fix the request.
409customerRef already registered (body has existingStatus), or the same key is still running (has Retry-After).Reconcile, or wait and retry with the same key.
422Key reused with a different payload.Use a new key for a new intent.
PATCH /api/customers/{customerRef}400status missing or unknown, or key invalid.Fix the request.
404No such customer.Do not retry.
409Same key still running (Retry-After).Wait and retry with the same key.
422Key reused with a different payload.New key.
POST /api/accounts400Missing or invalid field, or key invalid.Fix the request.
404Customer does not exist, or the asset has no active contract.Register the customer or contract first.
409accountRef already registered and not FAILED (body has existingStatus), or the same key is still running (Retry-After).Reconcile, or wait and retry.
422Customer is INACTIVE, or key reused with a different payload.Reactivate the customer, or use a new key.
PATCH /api/accounts/{accountRef}400status missing or not ACTIVE/INACTIVE (reported against settableStatus), or key invalid.Fix the request.
404No such account.Do not retry.
409Same key still running (Retry-After).Wait and retry.
422Transition not allowed from the current status (including reactivating an account whose customer is INACTIVE), or key reused.Read the account and correct.
GET lists400Invalid paging or unknown status.Fix the request.
GET by reference404No such customer or account.Do not retry.

Token contracts

EndpointStatusCauseClient action
POST /api/contracts400Missing or invalid field.Fix the request.
PATCH /api/contracts/{assetId}400Missing or invalid field.Fix the request.
404No contract for that assetId.Register it first.
GET /api/contracts400Invalid paging or unknown status.Fix the request.

Token operations and balances

EndpointStatusCauseClient action
POST /api/transactions400Key missing, blank or over 255 characters; counterpartyRef on a type other than TRANSFER or LOCK, or missing on a transfer; assetId not a recognised ISO 4217 code; amount not positive or finer than the currency's minor unit; no ACTIVE contract for the asset; a named account missing, holding another asset or not ACTIVE; a non-scalar params value; params.lockId on a LOCK; a RELEASE or CANCEL with no valid lockId, a lock that is not ACTIVE, a completion already in flight, or with assetId, accountRef or amount supplied.Fix the request.
404No lock yet for the params.lockId on a RELEASE or CANCEL.Retry. The lock becomes visible shortly after its LOCK is submitted.
GET /api/transactions400Negative page, size outside 1 to 100, or unknown state or txType.Fix the request.
GET /api/transactions/breaks400from not before to, negative page, or size outside 1 to 100.Fix the request.
GET /api/transactions/{transactionId}400Path id is not a UUID.Fix the request.
404No such operation.Do not retry.
GET /api/accounts/{accountRef}/balances404No such account, or its asset has no ACTIVE contract.Do not retry.
422The account has not finished provisioning (PENDING or FAILED) and has no wallet address.Wait for account.provisioned, or re-register a FAILED account.
500The balance could not be read. A failed read always returns an error. It is never reported as a zero balance.Retry with backoff.

Balances are not checked at submission. An operation for more than the account holds is accepted with 202 and fails during settlement. See Failed operations. The ledger transaction reverts. The example in the breaks queue reference shows such a case as CHAIN_FAILED, with the revert reason balance below amount in its detail. Read the terminal operation and its break record for the actual codes. Do not derive a stable reasonCode from the human-readable revert message.

Policies, templates and approvals

EndpointStatusCauseClient action
Policy and template writes400Body or parameters failed validation.Fix the request. Read code and details.
POST /api/policies404No template with this key is visible to the organisation.Use a visible template key.
POST /api/policies/{policyId}/activate409Another policy already holds this rule type, action and template key.Archive or change the other policy first.
PUT /api/policies/{policyId}/current-version404No such policy or version number.Do not retry.
POST /api/templates409The key already exists.Choose another key.
Template updates and deprecation404No template with this key in scope.Do not retry.
GET /api/approvals/tasks400Unknown task state.Fix the filter.
GET /api/approvals/requests400Unknown status, unparseable instant, or inverted resolvedAt range.Fix the filter.
POST /api/approvals/requests400Body failed validation, an approver expression could not be resolved, or an approver is the caller. code: VALIDATION_FAILED.Fix the request.
POST /api/approvals/requests/{requestId}/cancel409The request is not PENDING.Read the request.
POST /api/approvals/tasks/{taskId}/approve, reject403The caller is not an eligible approver, or is the initiator of the request.Route the task to another approver. This is separation of duties working as designed.
409The task was already acted on, or an earlier step is still pending.Read the request and wait for the earlier step.
POST /api/approvals/tasks/{taskId}/reassign400The expression could not be resolved, or resolved only to the initiator.Choose a different approver.
409The request is not PENDING, the task was acted on, or the approver set is unchanged.Read the request.
Any by id404No such resource in your organisation.Do not retry.

PayScript scripts and automations

EndpointStatusCauseClient action
POST /api/scripts400Validation or compilation failure, duplicate name, a missing dependency, or key missing.Fix the script.
409Same key still being processed.Wait and retry with the same key.
PATCH /api/scripts/{scriptId}400No field provided, invalid name or description, duplicate name, unsupported status, or key missing.Fix the request.
409Unpublishing a script another published script depends on; code sent for an OUTDATED or DEPRECATED script; other state conflicts; or key in flight.Resolve the dependency, or wait and retry.
DELETE /api/scripts/{scriptId}409The script is PUBLISHED, has ACTIVE automations, or other scripts depend on it.Unpublish, deactivate automations or remove dependants first.
GET /api/scripts/{scriptId}/download409The script is deleted.Do not retry.
POST /api/scripts/{scriptId}/clone400Override failed validation, duplicate name, or the source failed compilation.Fix the request.
409Source deleted, or key in flight.Do not retry, or wait and retry.
POST /api/automations400A field failed validation, or key missing.Fix the request.
404No such script.Do not retry.
409The script is not PUBLISHED, or key in flight.Publish the script, or wait and retry.
PATCH /api/automations/{automationId}/status400Status missing, transition not allowed (including to the current status, or away from DELETED), or key missing.Read the automation.
409Key in flight.Wait and retry.
POST /api/automations/{automationId}/executions400Key missing, an override's key blank or value/type missing, or id not a UUID.Fix the request.
409The automation is not ACTIVE or not ON_DEMAND, or key in flight.Activate it, or wait and retry.
422An override does not fit the script's declared parameters.Fix the override.
500The run could not be requested. No partial run is recorded and the key is released.Retry with the same key.
Any by id404No such script or automation, or it was deleted.Do not retry.

Webhooks and delivery history

EndpointStatusCauseClient action
POST /api/webhooks400URL not https, host does not resolve to a public address, unknown signatureScheme, no eventTypes, unknown event type, or key missing.Fix the request.
409The organisation already has this URL registered, or key in flight.Use the existing registration, or wait and retry.
PATCH /api/webhooks/{id}, secret/rotate, test400Invalid body or key missing.Fix the request.
404No such registration. On rotate, also a JWS_ES256 registration, which has no secret.Do not retry.
409Key in flight. On test, also an INACTIVE registration.Wait and retry, or activate it first.
GET /api/webhooks, GET /api/webhook-events400limit outside 1 to 100, a cursor this endpoint did not issue, a cursor replayed with different filters, or from not before to.Restart paging from the first page.
GET /api/webhook-events/{id}404No such event.Do not retry.
POST /api/webhook-events/{id}/redeliver404No such event, no delivery of it to the named destination, or the destination was deleted.Do not retry.
409The latest delivery is still queued, the destination is INACTIVE, the same delivery is already being replayed, or key in flight.Wait for the delivery to settle, or activate the destination.
429Replay budget exhausted. Nothing was queued.Retry later.
POST /api/webhook-events/redeliver400No filter supplied.Supply at least one filter.
409Key in flight.Wait and retry.
429Replay budget exhausted. Nothing was queued.Retry later.

Audit events

EndpointStatusCauseClient action
GET /api/audit/events, export400Inverted occurredAt range, a sort property outside the allowed list, a query over 128 characters, or a date that does not parse.Fix the filter.
GET /api/audit/events/{eventId}400Id is not a UUID.Fix the request.
404No such event in your organisation.Do not retry.

Failed operations

A token operation that was accepted can still fail. Read it with GET /api/transactions/{transactionId} or subscribe to transaction.failed, transaction.rejected and transaction.cancelled. CONFIRMED, FAILED and CANCELLED are terminal.

An operation that ended badly carries two fields:

FieldMeaning
failureCodeClassifies the ending. Absent, not null, while the operation is in flight and on one that confirmed. On a CANCELLED operation it may carry free text instead of a code, so do not validate it against the list below in that case.
reasonCodeThe more specific reason, such as a revert reason, a signing refusal or a submission error, for example EXECUTION_REVERTED. Absent when none was reported.
failureCodeMeaningClient action
VALIDATION_REJECTEDValidation or policy refused the operation.Do not resubmit unchanged. Review the reason with operations.
APPROVAL_REJECTEDAn approver refused it.Resubmit only after a business decision, as a new operation with a new key.
SIGNING_REJECTEDThe custody provider refused to sign. It applies its own policy before signing, independently of the platform. Nothing reached the ledger.Check the custody provider's record of the request against its policy. Do not resubmit unchanged. Escalate through the custody support route agreed for your deployment, with the operation and signing-request identifiers.
CHAIN_FAILEDSettlement failed in a way not worth retrying.Read reasonCode, correct the cause, then submit a new operation with a new key.
RETRY_EXHAUSTEDThe platform retried a temporary failure of a system the operation depends on, and ran out of attempts.Reconcile the terminal operation and break evidence before a new business-authorized instruction. If a hash exists, verify the ledger outcome first; retry exhaustion alone does not prove that a broadcast transaction cannot settle.
UNPROCESSABLESomething the operation depends on is missing, such as an active contract or account, or a lock expiry that was in the past or invalid.Fix the dependency, then submit a new operation with a new key.
POLICY_EXPIREDThe policy decision was not made in time.Resubmit as a new operation if still required.
POLICY_TIMEOUTNo policy decision arrived within the time allowed.Resubmit as a new operation if still required.

Resubmit with a new key. Sending the same Idempotency-Key again returns the failed operation. A new attempt is a new business intent and needs a new key.

A FAILED operation moved no value. If txHash is absent, it never reached the ledger. If txHash and blockNumber are both present, its ledger transaction was included and reverted. Handle failures sets out the full response for each case.

Treat reasonCode as service-specific evidence, not a closed platform-wide enum. Store unfamiliar values and route them for investigation rather than rejecting the operation record.

A failed operation may also appear in the outstanding breaks list, GET /api/transactions/breaks. See Reconcile against your core banking.

Webhook delivery failures

When the platform cannot deliver a webhook to your endpoint, the delivery history records why:

failureClassMeaning
UNREACHABLEThe destination could not be connected to.
TIMEOUTThe destination accepted the connection but did not answer in time.
REJECTEDThe destination answered with a status that is not a success.

See Webhooks.

Worked example

A transfer with an amount finer than sterling's minor unit is refused at submission.

Illustrative example built from the schema.

POST /api/transactions HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer eyJraWQiOiJ...
API-Version: 1.0.0
Content-Type: application/json
Idempotency-Key: 1b9e6d52-0c41-4b7a-a3f2-5e8d9c0f7a16

{
  "txType": "TRANSFER",
  "assetId": "GBP",
  "accountRef": "ACC-000184-GBP",
  "counterpartyRef": "ACC-000207-GBP",
  "amount": "10.505"
}
HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "timestamp": "2026-09-02T11:12:03.884Z",
  "status": 400,
  "error": "Bad Request",
  "message": "Amount '10.505' has 3 decimal places, while GBP allows only 2."
}

An approver who initiated the request tries to approve it:

POST /api/approvals/tasks/7d1e4c93-2a68-4f51-b0c7-3e95a4d81f26/approve HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer <initiator access token>
API-Version: 1.0.0
Content-Type: application/json

{}
HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "timestamp": "2026-08-18T09:00:00.000Z",
  "status": 403,
  "error": "Forbidden",
  "message": "You are not an eligible approver for this task."
}

View in API Reference

Errors and edge cases

  • Two outcomes for one condition. An asset with no active contract is a 400 on POST /api/transactions and a 404 on POST /api/accounts.
  • 404 for another organisation's resource. A resource in another organisation returns 404. This applies to tenant-scoped resources; shared catalogues and the unscoped user-by-ID lookup have distinct rules.
  • sort errors differ. An unknown sort property is a 500 on identity lists and a 400 on audit search.
  • A zero balance is never an error substitute. A balance read that fails returns 500.

API Reference

Open an endpoint for request fields, response examples and the interactive API console.

Related pages


Did this page help you?