Preflight a transfer
POST/v1/transfers/preflight
Check whether the calling bank's liquidity and limits would cover a transfer of the given
asset and amount to the receiving bank if it were submitted now, without creating a
transfer, reserving funds or moving value. INTERBANK and BANK_ROUTED are supported.
Requires scope connector:transfers:create, and the calling principal must hold the
maker role for the bank (otherwise 403 UNAUTHORIZED_ROLE).
The answer depends only on the two banks, the asset and the amount. The receiving bank is the only counterparty input:
transfer_kind | You send | Receiving bank |
|---|---|---|
INTERBANK | asset_id, amount, destination.bank_id; source is optional | destination.bank_id |
BANK_ROUTED | receiving_bank_id, asset_id, amount (the same body as POST /v1/transfers) | receiving_bank_id |
Preflight does not validate accounts. For INTERBANK, the account fields
(external_account_id, alias, expected_holder_name) may be sent, so you can reuse the
body you will submit, but they are ignored and do not change the result. An unregistered
account is only detected on submit, where the transfer ends FAILED. For the same banks,
asset and amount, both kinds return the same result.
The check covers:
- Sender capacity: the sending bank's eligible liquidity, including headroom to issue its own tokens under its mint limit.
- Receiver acceptance: the receiving bank's exposure limit toward the sender's tokens.
A blocking constraint is reported as 200 with would_succeed: false, not as an error.
Problems that would make the request itself invalid (ineligible bank or asset, malformed
input) are returned as errors:
| Status | code | When |
|---|---|---|
400 | (none) | amount.value is not a positive integer, a bank is terminated, or there is no eligible liquidity route between the two banks for the asset (title no eligible liquidity positions found for the source bank, destination holder, and settlement asset). The reason is in title. |
403 | UNAUTHORIZED_SCOPE, UNAUTHORIZED_ROLE, BANK_SCOPE_MISMATCH | Missing scope or maker role; source.bank_id is not the calling bank; the receiving bank is the calling bank. |
422 | (none) | Body does not match the schema, including an unknown transfer_kind, missing receiving_bank_id, or account fields on a BANK_ROUTED request (title Invalid request body). |
422 | VALIDATION_ERROR | destination.bank_id is missing on an INTERBANK request, or the supplied receiving bank id (destination.bank_id or receiving_bank_id) is not a UUID. |
422 | BANK_NOT_ELIGIBLE, ASSET_NOT_ELIGIBLE | A bank or the asset is not eligible for the transfer. |
This endpoint has no side effects and takes no Idempotency-Key; repeating a call is
always safe. It remains available while the network refuses new transfers
(OUTBOUND_HALTED or READ_ONLY). The result is a point-in-time estimate; see
TransferPreflight for its limits.
Request
Responses
- 200
- 400
- 401
- 403
- 422
- 429
- 503
Preflight result. blocking_constraint, remediation and available_headroom are
always present and are null when would_succeed is true.
Invalid input, a terminated bank, or no eligible liquidity route between the two
banks. The reason is in title; these errors carry no code.
The bearer token is missing, malformed, expired, signed by an unknown key, or was not issued by the platform IAM for the Lyriq Connector. Obtain a new token and retry. See the Authentication section.
Missing scope (UNAUTHORIZED_SCOPE), missing maker role (UNAUTHORIZED_ROLE), or a
bank identifier that conflicts with the calling bank (BANK_SCOPE_MISMATCH).
Body does not match the schema, including a missing receiving_bank_id on a
BANK_ROUTED request (title Invalid request body); destination.bank_id is missing
on an INTERBANK request or the supplied receiving bank id is malformed
(VALIDATION_ERROR); or a bank or asset is ineligible
(BANK_NOT_ELIGIBLE, ASSET_NOT_ELIGIBLE).
The request was refused because a rate limit was reached (code RATE_LIMITED). No
Retry-After header is sent; retry with exponential backoff.
The request could not be served right now. Either the network is not fully operational
(OUTBOUND_HALTED or READ_ONLY: mutations are refused while read endpoints keep
working; OPERATIONAL_STATE_UNKNOWN: the state could not be determined), or a platform
dependency is temporarily unavailable. No Retry-After header is sent; retry later with
backoff. When retrying a mutation, reuse the same Idempotency-Key and body.