Operations and their lifecycle

For integration engineers. The token operation types, the states an operation passes through, which states are terminal, and how failures are classified.

Follow an instruction to its outcome

A request to issue, move, redeem or reserve tokens becomes an instruction that your team must track. Quant Flow can accept it before settlement is complete. It may still be waiting for a configured approval, signing or the network outcome.

Operations teams should distinguish submitted, waiting, settled and failed work. Only a confirmed settlement establishes that the token movement completed. A delayed response or missing notification leaves the outcome unresolved; it is not a reason to submit another payment automatically.

Keep one bank-side record for the business instruction and its eventual result. Use that record to reconcile balances, investigate exceptions and avoid duplicate cash postings. The exact operation types, states and failure classifications below support the engineering and support teams.

Operations

An operation is one business instruction against a token: issue, redeem, move, or commit funds. In the API the resource is called a transaction. "Transaction" there means one business operation, which is different from a ledger transaction.

txTypeWhat it doesFields it carries
MINTIssues tokens to accountRef.assetId, accountRef, amount
BURNRedeems tokens from accountRef.assetId, accountRef, amount
TRANSFERMoves tokens from accountRef to counterpartyRef.assetId, accountRef, counterpartyRef, amount
LOCKCommits part of accountRef's balance. Two-party if counterpartyRef is named.assetId, accountRef, amount, optional counterpartyRef, optional params.expiry and params.lockRef
RELEASECompletes a lock by paying its destination, or returning the funds if none was named.params.lockId only
CANCELCompletes a lock by returning the funds to the source. Works after the lock has expired.params.lockId only
FREEZE, UNFREEZEChange account controls without moving value.Submit through POST /api/accounts/{accountRef}/controls, not POST /api/transactions. operation is FREEZE or UNFREEZE; reason is required for a freeze and optional for an unfreeze, up to 100 characters.
DEPLOYDeploys and registers an asset's token contract.Submit through POST /api/contracts, not POST /api/transactions.

Locks, releases and cancellations are covered in Transfers, locks and releases.

Map the operation to your application's status

Store one durable record per business instruction and update it as the platform reports progress. Use the returned transactionId for reads and retain txHash when it appears; they identify different things. One is the platform operation, the other is its settling ledger transaction.

Platform factSuitable application behaviour
Submission returned 202Show submitted or processing; retain the identifier.
Operation awaits approvalShow awaiting sign-off and link to the related approval workflow.
Signed or submitted to the networkKeep processing; neither proves settlement.
CONFIRMEDMark the token operation settled and perform the workflow's bank-side booking or reconciliation step.
FAILED or CANCELLEDRetain the reason and apply the flow-specific recovery procedure.
No definitive outcomeShow an unresolved instruction and investigate; a client deadline does not change platform state.

Keep customer-facing messages understandable, while retaining the exact state and failure codes for support. Process repeated reads and events idempotently so a confirmed operation does not cause a second cash posting.

The lifecycle

Submission is asynchronous. POST /api/transactions returns 202 when the request is well formed and the accounts it names are usable. The operation then moves through the configured policy and settlement path. Policy is disabled in the shipped configuration: an operation starts in BATCHED when policy is disabled or its type is excluded. When enabled for the type, it starts in POLICY_PENDING. You find out where it got to by reading it back, or from webhooks.

stateDiagram-v2
    [*] --> POLICY_PENDING: 202, policy enabled for this type
    [*] --> BATCHED: 202, policy disabled or type excluded
    POLICY_PENDING --> VALIDATED: COMPLETED
    POLICY_PENDING --> AWAITING_APPROVAL: PENDING
    POLICY_PENDING --> FAILED: REJECTED or EXPIRED
    POLICY_PENDING --> CANCELLED: CANCELLED
    AWAITING_APPROVAL --> VALIDATED: COMPLETED
    AWAITING_APPROVAL --> FAILED: REJECTED or EXPIRED
    AWAITING_APPROVAL --> CANCELLED: CANCELLED
    VALIDATED --> HELD: Insufficient balance gate
    VALIDATED --> BATCHED
    BATCHED --> PREPARED
    PREPARED --> SIGNED
    PREPARED --> AWAITING_APPROVAL: Custody approval pending
    SIGNED --> SUBMITTED
    SUBMITTED --> CONFIRMED
    PREPARED --> FAILED
    SUBMITTED --> FAILED
    CONFIRMED --> [*]
    FAILED --> [*]
    CANCELLED --> [*]

The same model as a table:

StateStageMeaningTerminal
POLICY_PENDINGPolicyAwaiting a policy decision.No
VALIDATEDPolicy outcomeCleared by policy.No
HELDPolicy outcomeParked at the insufficient-balance gate; this is different from waiting for an approver.No
AWAITING_APPROVALPolicy outcomeWaiting for an approver.No
BATCHEDSettlementSettlement in progress.No
PREPAREDSettlementSettlement in progress.No
SIGNEDSettlementSettlement in progress.No
SUBMITTEDSettlementSent to the ledger. txHash is present; blockNumber is not yet.No
CONFIRMEDOutcomeSettled. Balances now reflect it.Yes
FAILEDOutcomeEnded badly. failureCode says why.Yes
CANCELLEDOutcomeWithdrawn.Yes
RECEIVEDRetiredNo longer used. Operations submitted before it was retired may still report it.No

CONFIRMED, FAILED and CANCELLED are terminal. They will not change again. Every other state may have moved on since you read it.

The diagram shows the documented policy and settlement paths, not every internal retry transition. When policy is enabled, the shipped judged types are MINT, BURN, TRANSFER and LOCK; RELEASE and CANCEL are excluded. The environment's configuration can change this set. A policy CANCELLED decision cancels the operation; cancellation while awaiting approval also cancels its lock.

Do not rely on an automatic policy timeout. The configured response deadline is not currently enforced. An unanswered operation can remain POLICY_PENDING until an operator acts; alert and investigate rather than submitting another operation. Approval-request expiry is a separate policy-engine mechanism.

  • Use the states returned by transaction reads rather than assuming that every intermediate state will be observed. Out-of-order pipeline events can advance the reported state; only the documented terminal states establish the final platform outcome.
  • Confirm the caller's account-control and cancellation entitlements before exposing these actions in your application.

Reading progress

GET /api/transactions/{transactionId} returns the operation as it stood at the moment of the read, dated by updatedAt.

FieldPresent when
failureCodeThe operation ended badly. Absent, not null, while in flight and when confirmed.
reasonCodeA more specific reason was reported, such as a revert reason. Absent otherwise.
txHashThe operation has been submitted for settlement. Absent permanently if it failed before then.
blockNumberThe ledger transaction has been mined.

txHash without blockNumber means in flight on the ledger. Both present means settled or reverted: read state to tell which.

On a CANCELLED operation, failureCode may carry a free-text reason instead of a code. Do not validate it against the enumeration in that case.

Webhook event types include transaction.confirmed, transaction.failed, transaction.rejected, transaction.cancelled and transaction.awaiting_approval. Treat events as notifications and read the operation for its authoritative state and failure details. Do not derive a terminal state from transaction.rejected alone. See Webhooks.

Failure codes

failureCodeMeaning (from the API Reference)
VALIDATION_REJECTEDValidation, screening or policy refused it.
APPROVAL_REJECTEDAn approver refused it.
SIGNING_REJECTEDSigning refused it.
CHAIN_FAILEDSettlement failed in a way not worth retrying.
RETRY_EXHAUSTEDThe attempt budget ran out.
UNPROCESSABLESomething the operation depends on is missing, such as an active contract or account. Also the result of a lock expiry in the past or not a valid instant.
POLICY_EXPIREDThe policy decision was not made in time.
POLICY_TIMEOUTNo policy decision arrived within the time allowed.

A failed signing or broadcast can be redispatched up to the configured maximum of five chain-transaction attempts by default. Retry eligibility depends on configured reason-code lists. RETRY_EXHAUSTED means this budget ran out. Confirm your environment's settings with Quant Network; do not assume a per-organisation setting.

When an operation is interrupted

A timeout, restart or server error leaves the outcome uncertain until you recover evidence. Keep the original request body, idempotency key and any returned transaction ID. Idempotency replays a recorded operation; it does not establish that every failure across storage, messaging, signing and the ledger was rolled back.

Progression is event-driven. The service documentation states that there is no general sweep or automatic re-drive for a lost operation announcement. An operation that stops progressing can require operator intervention. Do not create a replacement simply because it has waited too long.

ObservationWhat it establishesRecovery
No response or a submission 5xxAcceptance and downstream progress are unknown.Recover using the original key and unchanged body within a bounded retry budget. Read the returned operation and investigate unresolved evidence with the operator.
Recorded operation, no later progressThe operation exists; a stalled notification is not proof of rejection.Read its state and the breaks queue. Ask the operator to diagnose and recover stalled work.
Signing requested, no answerCustody may still be processing the request.Retain signing/operation evidence and coordinate with the custody owner. Do not create another payment intent.
Ledger submission without confirmationThe transaction may still be included.Reconcile the hash/nonce and ledger result with the operator; do not submit a replacement.
CONFIRMED, webhook missingThe API reports completed settlement.Read the operation and recover the delivery through the webhook history/redelivery API.

A signed ledger transaction has fixed content and a nonce. Re-sending that same signed transaction differs from creating a new operation with a new key. Bank cash postings are a separate record and must be reconciled with the established token outcome.

A confirmed operation cannot be rolled back. A correction is a separately authorised compensating instruction, with its own business justification and controls. Establish the original outcome before deciding whether one is needed.

What a client can retry

CaseRetry?
Network failure or 5xx on submissionRecover with the same key and unchanged body, using bounded retries. A recorded-operation replay returns its current state with 200; unresolved server errors still require investigation.
404 on a RELEASE or CANCEL naming a lockIdYes. The lock becomes visible shortly after its LOCK is submitted. This is the one refusal on submission worth retrying.
Any other 4xx on submissionNo. Correct the request.
An operation that ended FAILEDNot by resubmitting the same key: that returns the failed operation. Establish the cause and reconcile any signing or ledger uncertainty before authorising a new instruction with a new key. Handle failures gives the action for each failureCode.

On this endpoint, reusing a key with a different payload does not return 422. It returns the first operation and ignores the new payload. Other write endpoints return 422 in that case. Generate a new key for every new instruction.

Keep a durable instruction journal

Your bank adapter owns the correlation between a business instruction, its original request/key and Quant Flow's operation ID. Update its last observed state and observation time from events and reads without discarding the original intent. Preserve ledger evidence when available; transactionId and txHash identify different layers.

A customer-facing status should distinguish accepted/pending, confirmed and failed. Route unclear outcomes to an investigation state in your application rather than inventing a platform state or submitting another instruction. Quant Flow supplies operation/break reads; the bank owns the investigation queue and cash reconciliation, with operator diagnosis where needed. See Daily operations and monitoring.

Worked example

Read an operation that has settled.

GET /api/transactions/9c4d2f18-73ba-4e6c-8f05-2d17ab903e64 HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer <access token>
API-Version: 1.0.0
HTTP/1.1 200 OK
Content-Type: application/json

{
  "transactionId": "9c4d2f18-73ba-4e6c-8f05-2d17ab903e64",
  "txType": "LOCK",
  "assetId": "GBP",
  "accountRef": "ACC-0001",
  "customerRef": "CUST-0001",
  "counterpartyRef": "ACC-0002",
  "amount": "100.00",
  "params": {
    "expiry": "2027-01-01T00:00:00Z",
    "lockRef": "INV-88421",
    "lockId": "b28f1a4c-9d3e-4f27-8a56-1e0c7b9d42a1",
    "chainLockId": "0x00000000000000000000000000000000b28f1a4c9d3e4f278a561e0c7b9d42a1",
    "destination": "0x8B1cA3D5e07F2b94aC61d8E30f5A7b249C0e6D18"
  },
  "state": "CONFIRMED",
  "txHash": "0x9f2c1d5e4b8a37c06d1e5f9a2b4c7d8e0f1a2b3c4d5e6f708192a3b4c5d6e7f8",
  "blockNumber": 18446744,
  "createdAt": "2026-08-06T09:29:10.285Z",
  "updatedAt": "2026-08-06T09:31:47.902Z"
}

An operation still in flight has no txHash, blockNumber or reasonCode:

{
  "transactionId": "7d1e4c93-2a68-4f51-b0c7-3e95a4d81f26",
  "txType": "MINT",
  "assetId": "GBP",
  "accountRef": "ACC-0001",
  "customerRef": "CUST-0001",
  "counterpartyRef": null,
  "amount": "10.50",
  "params": {},
  "state": "VALIDATED",
  "createdAt": "2026-08-06T09:29:10.285Z",
  "updatedAt": "2026-08-06T09:29:12.041Z"
}

View in API Reference

Errors and edge cases

SituationResponse
transactionId is not a UUID400
No such operation in your organisation404
state or txType filter names a value that does not exist400 on the list endpoint
size outside 1 to 100400. The value is rejected, not clamped.

The operation log (GET /api/transactions) is ordered newest first, with transactionId as a tiebreaker. Account and customer listings are oldest first. The accountRef filter matches operations originating from that account only; an operation naming it as the counterparty is not matched. The log has no date-range filter.

Use webhooks as the primary signal and polling as the fallback. Alert when an expected completion event does not arrive, or when an operation stays in a non-terminal state beyond its expected window. The window is agreed with Quant Network during onboarding. Use a bounded poll interval with backoff and jitter chosen for your environment. After a local deadline, keep the instruction unresolved and alert the operator rather than submitting a replacement.

Follow a Recipe

Step through the code in JavaScript or Python, inspect illustrative responses, and open the connected endpoint schemas.

API Reference

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

Related pages

Implementation resources

Transactions code recipes.

Use Implement a backend client for request handling, durable idempotency and outcome tracking. The developer integration coverage map links every public operation to its API Reference and contract-derived code recipe. Replace example identifiers with values from your assigned environment.


Did this page help you?