Submit a token operation

Submits a token operation (a mint, burn, transfer, lock, release or cancel) and returns it. The operation then settles asynchronously; nothing further is required of the caller.

Acceptance and settlement

A 202 is acceptance, not completion. It means the request was well-formed and the accounts it names are usable. Every operation is then subject to the organisation's transaction policy, which may refuse it or hold it for an approver.

That outcome is not reported on this endpoint; read the operation back with GET /api/transactions/{transactionId} to see where it got to.

Supported token operations

txType decides the operation. MINT issues tokens to accountRef; BURN redeems tokens from it; TRANSFER moves tokens from accountRef to counterpartyRef, and is the one type that requires a counterparty; LOCK commits part of the account's balance; RELEASE and CANCEL complete a lock.

A release pays the lock's destination, or returns the funds if none was named, while a cancellation always returns them to the source and, unlike a release, still works once the lock has expired.

Related endpoints

FREEZE and UNFREEZE are not accepted here. They are account-control operations, raised through POST /api/accounts/{accountRef}/controls; sending either as a txType on this endpoint is a 400. DEPLOY is not accepted here either: a contract deployment is raised through POST /api/contracts, which shapes the factory call's arguments itself.

Account and contract requirements

Both accountRef and counterpartyRef name accounts, never customers. Each named account must exist, hold the operation's assetId, and be ACTIVE. The asset must have an ACTIVE contract; a missing one is a 400 on this endpoint, though the same condition is a 404 when registering an account.

Lock destinations

A lock is one-party or two-party, decided by counterpartyRef alone: named, and releasing the lock pays that account; absent, and the funds can only return to accountRef. This is fixed when the lock is created.

Completing a lock

A RELEASE or CANCEL carries txType and params.lockId, and nothing else. The asset, account and amount are read from the lock. Supplying assetId, accountRef or amount is a 400 for each. The lock must exist and currently be ACTIVE; a second completion while one is already in flight is a 400.

A lock that does not exist is a 404, and that one is worth retrying; see the 404 response below.

Returned call arguments

The response echoes the operation's call arguments in params, including those the service supplies itself. A LOCK is assigned its lockId here, and this response is where a caller obtains it: it is the identifier a release or cancel must name. A caller cannot choose it: a lockId supplied on a LOCK is a 400.

Balance checks

Balances are not checked at submission. An operation for more than the account holds is accepted here and fails during settlement.

Recipes
Mint tokens and confirm settlement
Open Recipe
Transfer tokens and track the outcome
Open Recipe
Burn tokens for redemption
Open Recipe
Lock funds then release or cancel
Open Recipe
Recover a lost response or delayed outcome
Open Recipe
Body Params

The organisation is taken from the access token; there is no field for it here.
Only txType is always required. What else is required depends on it.
This endpoint accepts only MINT, BURN, TRANSFER, LOCK, RELEASE and CANCEL. The shared TxType vocabulary also describes read responses: FREEZE and UNFREEZE are submitted through account controls, and DEPLOY through contract deployment. Submitting those three here is a 400.

A MINT, BURN, TRANSFER or LOCK must carry assetId, accountRef and amount.
A RELEASE or CANCEL must carry none of the three; each one supplied is a 400. It names only the lock it completes, in params.lockId. All three are still recorded on the operation and returned by every read of it.

string
enum
required

The token operation. MINT issues tokens to an account; BURN redeems them from it; TRANSFER moves them between two accounts; LOCK commits part of an account's balance; RELEASE and CANCEL complete a lock, a release paying the lock's destination and a cancellation returning the funds to the source. FREEZE and UNFREEZE move no value at all — they change whether the contract will accept anything else against the account. DEPLOY creates the asset's contract itself; it is raised through POST /api/contracts, names no account and carries no amount.

string
length ≤ 16

The asset the operation is denominated in. Case-insensitive, and must have an ACTIVE contract.
Required for a MINT, BURN, TRANSFER or LOCK; rejected on a RELEASE or CANCEL, which take the asset from the lock they name.

string
length ≤ 128
[A-Za-z0-9._:-]+

The originating account, never a customer, since a customer may hold several accounts for one asset. Must exist, hold this assetId, and be ACTIVE.
Required for a MINT, BURN, TRANSFER or LOCK; rejected on a RELEASE or CANCEL, which take the account from the lock they name.

string | null
[A-Za-z0-9._:-]+

The receiving account. Required for a TRANSFER, optional for a LOCK, rejected for every other type.
On a lock, its presence makes the lock two-party. Named, and the release pays that account. Absent, and the funds can only return to accountRef.
Where supplied it is held to the same standard as accountRef: it must exist, hold the same asset, and be ACTIVE.

string
^[0-9]{1,60}(\.[0-9]{1,18})?$

The amount in currency units, as a decimal string. "10.50" is ten pounds fifty. Must be greater than zero and at most 60 digits before the decimal point.
No finer than the currency's own minor unit: two decimal places for GBP, none for JPY, three for BHD, taken from ISO 4217. "10.505" is rejected rather than rounded.
The field binds to a BigDecimal, so an unquoted JSON number parses too and is not refused. Send the string anyway: a number travels through the caller's own stack as a float, and a value that has already lost precision there arrives here looking perfectly valid.
Send it as a string. A JSON number is accepted but is not the supported form: a client whose JSON library holds numbers as doubles can corrupt the value before it is sent.
Required for a MINT, BURN, TRANSFER or LOCK; rejected on a RELEASE or CANCEL, which take the amount from the lock they name. A lock is always completed in full.

params
object | null

Additional named arguments the operation needs beyond the fields above.
Values must be scalar: a string, a boolean, or a whole number. A nested object or a fractional number is rejected with 400. Send large integers as strings; any number sent is returned as a string.
lockId is the one name the service interprets. A RELEASE or CANCEL must carry it, naming the lock to complete; the value is the one the LOCK's own response reported. A LOCK must not carry it: the identifier is assigned on submission and returned, so supplying one is a 400.
The other names a LOCK recognises are expiry and lockRef. expiry is an ISO-8601 instant and must be in the future; omit it for a lock that never expires. Sub-second precision is truncated. lockRef is the bank's own payment reference.
An expiry in the past, or one that is not a valid instant, is not refused here. The operation is accepted with a 202 and later ends FAILED with UNPROCESSABLE.

Headers
string
required
^\d+\.\d+\.\d+$

The version of the Quant Flow API the request follows, as major.minor.patch (for example 1.0.0). The request is interpreted, and the response shaped, according to that version.

string
required
length ≤ 255

Caller-supplied key making the write at-most-once. Replay semantics are endpoint-specific: customer and account registry writes replay the original response and reject a changed payload with 422; transaction and deployment submissions return the current operation with 200 and ignore a changed payload. See the operation's response documentation. Use one key per intent. Missing, blank or longer than 255 characters is a 400.

Responses

Language
Credentials
Bearer
JWT
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json