<!-- x-generated: Generated by the Hyperscale artifact pipeline; do not edit by hand -->

# Trade settlement

> Two-party escrow swap that funds, releases, and claws back whole.

A trade settlement holds one SAR amount from each of exactly two parties in one escrow. Funding, cancellation, release reservation, maturity posting, and dispute clawback each execute as one linked ledger batch. Service fees are charged on top at funding and never enter the clawback multiset.

- Instrument id: `trade_settlement`
- Initial state: `created`
- Terminal states: `settled`, `cancelled`, `abandoned`, `clawed_back`
- Composed by: [asset_backed_membership](../programs/asset_backed_membership.md), [escrow_marketplace_sandbox](../programs/escrow_marketplace_sandbox.md)

## Lifecycle

The diagram draws only the transitions a composing Product exposes as an action. A cell reading "no step any Product exposes" means no drawn edge enters or leaves that state, so the move belongs to a lifecycle step none of the composing Products exposes. Terminal states read "none" under Left by, because stopping there is the declared design rather than a missing step. Where an unexposed step carries a price it is listed under Steps no Product exposes, below.

```mermaid
stateDiagram-v2
    [*] --> created: create
    created --> abandoned: abandon
    funded --> cancelled: cancel
    released --> clawed_back: dispute
    created --> funded: fund
    funded --> released: release
    settled --> [*]
    cancelled --> [*]
    abandoned --> [*]
    clawed_back --> [*]
```

| State | Kind | Entered by | Left by |
| --- | --- | --- | --- |
| `created` | initial | create | abandon, fund |
| `funded` | intermediate | fund | cancel, release |
| `released` | intermediate | release | dispute |
| `settled` | terminal | no step any Product exposes | none |
| `cancelled` | terminal | cancel | none |
| `abandoned` | terminal | abandon | none |
| `clawed_back` | terminal | dispute | none |

## Fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `sideAAmount` | money<SAR> (minor_unit_integer_string) | yes | Amount side A holds against the whole exchange, in SAR minor units |
| `sideBAmount` | money<SAR> (minor_unit_integer_string) | yes | Amount side B holds against the whole exchange, in SAR minor units |
| `sideAServiceFeeAmount` | money<SAR> (minor_unit_integer_string) | yes | Side A custody fee charged on top and never placed in escrow |
| `sideBServiceFeeAmount` | money<SAR> (minor_unit_integer_string) | yes | Side B custody fee charged on top and never placed in escrow |
| `currency` | text | yes | One currency for both trade legs and both fees |
| `clawbackAt` | datetime | no | Machine-owned absolute end of the release clawback window |

## References

- `sideAAccountId`: `account`, required
- `sideBAccountId`: `account`, required
- `platformAccountId`: `account`, required

## Actions

### abandon

Abandon the trade before its atomic funding batch

- From: `created`
- To: `abandoned`
- Hints: readOnly=false, destructive=true, idempotent=true, moneyMovement=false
- Handle key: `tradeSettlementId`

Exposed as:

| Program | Public action | Route |
| --- | --- | --- |
| [escrow_marketplace_sandbox](../programs/escrow_marketplace_sandbox.md) | `abandonMarketplaceTrade` | `POST /v1/operations/trade_settlement.abandonMarketplaceTrade`, scopes trade_settlement:write, idempotency required, receipt yes |

Input:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `tradeSettlementId` | ref<trade_settlement> | yes | Trade settlement instance ID |

This action records no effect rows.

Errors beyond the 18 shared with every action on this instrument:

| Code | HTTP | Cause | Action | Remediation | Retryable | Idempotency safe |
| --- | --- | --- | --- | --- | --- | --- |
| `instrument_account_not_drained` | 409 | The request contradicts the resource the platform has already durably recorded (`instrument account not drained`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `instrument_instance_not_found` | 404 | No Instrument instance matches the `instrumentInstanceId` this request referenced (`instrument instance not found`). | List Instrument instances in the same tenant, product, and environment, then retry with the `instrumentInstanceId` that read returns. | Create or select the Instrument instance in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `invalid_instrument_transition` | 409 | The request contradicts the resource the platform has already durably recorded (`invalid instrument transition`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |

### cancel

Cancel and refund both funded trade sides atomically

- From: `funded`
- To: `cancelled`
- Hints: readOnly=false, destructive=true, idempotent=true, moneyMovement=true
- Handle key: `tradeSettlementId`

Exposed as:

| Program | Public action | Route |
| --- | --- | --- |
| [escrow_marketplace_sandbox](../programs/escrow_marketplace_sandbox.md) | `cancelMarketplaceTrade` | `POST /v1/operations/trade_settlement.cancelMarketplaceTrade`, scopes trade_settlement:write, transfer:write, idempotency required, receipt yes |

Input:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `tradeSettlementId` | ref<trade_settlement> | yes | Trade settlement instance ID |

Effects:

- moves:
  - `moves.transfer.internal` from `moves[0]`
  - `moves.transfer.internal` from `moves[1]`

Errors beyond the 18 shared with every action on this instrument:

| Code | HTTP | Cause | Action | Remediation | Retryable | Idempotency safe |
| --- | --- | --- | --- | --- | --- | --- |
| `account_frozen` | 409 | The account is frozen. Debits always refuse while frozen; some freezes also refuse credits. The error message carries the only reason wording Hyperscale exposes. | Use a different account for this transfer leg, or have the freeze lifted before retrying. | Unfreeze the account through its lifecycle surface if you imposed the freeze; a freeze you cannot lift was imposed by the platform and clears only when the platform lifts it. | no | yes |
| `account_ledger_mapping_conflict` | 409 | The request contradicts the Account the platform has already durably recorded (`account ledger mapping conflict`). | Re-read the Account with `account.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Account as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `account_not_found` | 404 | No Account matches the `accountId` this request referenced (`account not found`). | List Accounts in the same tenant, product, and environment, then retry with the `accountId` that read returns. | Create or select the Account in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `cross_tenant_transfer_forbidden` | 409 | The request contradicts the resource the platform has already durably recorded (`cross tenant transfer forbidden`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `currency_invalid` | 500 | The platform could not durably complete the `currency invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `currency_mismatch` | 400 | The currency on the request does not match the settlement currency of the account or transfer it targets. Hyperscale never converts between currencies, so the two must be identical. | Read the target account's currency (for example with `account.balance.retrieve`) and resend with that same currency and a minor-unit amount denominated in it. | This is deterministic. Retrying with the same currency fails identically. Correct the request's currency field, or move the money through an account already denominated in the required currency, then retry. | no | yes |
| `customer_access_compliance_forbidden` | 403 | The request contradicts the Customer access the platform has already durably recorded (`customer access compliance forbidden`). | Re-read the Customer access with `customer_access.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Customer access as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `customer_access_required` | 403 | The operation cannot run against this Customer access until the `customer access required` prerequisite exists. | Supply the field, capability, evidence, or configuration the error details name for this Customer access, then call the operation again. | Complete the prerequisite through the surface that owns it -- the operation reference for this Customer access names it -- and the same call then succeeds unchanged. | no | yes |
| `customer_not_found` | 404 | No Customer matches the `customerId` this request referenced (`customer not found`). | List Customers in the same tenant, product, and environment, then retry with the `customerId` that read returns. | Create or select the Customer in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `customer_status_forbidden` | 403 | The Customer's current lifecycle state does not allow this transition (`customer status forbidden`). | Read the Customer with `customer.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Customer's current status permits. The reference itself is still valid, so no new Customer is needed. | no | yes |
| `destination_account_status_forbidden` | 400 | The destination (credit) account is not open. It is frozen or closed, so Hyperscale will not credit it. | Use a destination account whose status is `open`, or unfreeze the intended account, before retrying. | Read the account status, unfreeze it (or select an open account in the same currency and product), then resend the transfer. | no | yes |
| `entity_not_found` | 404 | No Entity matches the `entityId` this request referenced (`entity not found`). | List Entities in the same tenant, product, and environment, then retry with the `entityId` that read returns. | Create or select the Entity in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `entity_status_forbidden` | 403 | The Entity's current lifecycle state does not allow this transition (`entity status forbidden`). | Read the Entity with `entity.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Entity's current status permits. The reference itself is still valid, so no new Entity is needed. | no | yes |
| `instrument_instance_not_found` | 404 | No Instrument instance matches the `instrumentInstanceId` this request referenced (`instrument instance not found`). | List Instrument instances in the same tenant, product, and environment, then retry with the `instrumentInstanceId` that read returns. | Create or select the Instrument instance in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `insufficient_balance` | 409 | The source (debit) account's available balance is below the transfer amount, so the ledger refused the transfer. No money moved. The transfer was not created and its charge/transfer rows are recorded as failed. | Fund the source (debit) account so its available balance in minor units covers the full amount, or lower the amount, then retry. Confirm the shortfall first with `account.balance.retrieve`. | This is a definitive refusal, not a transient failure: replaying the exact request with the same Idempotency-Key safely returns this same refusal and never double-charges, so rotating to a fresh key is not the fix. Funding is. Top up the source account (or reduce the amount), then submit the transfer as a new request. | no | yes |
| `invalid_instrument_transition` | 409 | The request contradicts the resource the platform has already durably recorded (`invalid instrument transition`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_account_rejected` | 500 | The platform could not durably complete the `ledger account rejected` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_account_result_missing` | 500 | The platform could not durably complete the `ledger account result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_address_missing` | 500 | The platform could not durably complete the `ledger address missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_amount_invalid` | 500 | The platform could not durably complete the `ledger amount invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_invalid` | 500 | The platform could not durably complete the `ledger cluster id invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_missing` | 500 | The platform could not durably complete the `ledger cluster id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_missing` | 500 | The platform could not durably complete the `ledger effect missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_not_declared` | 500 | The platform could not durably complete the `ledger effect not declared` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_evidence_missing` | 500 | The platform could not durably complete the `ledger evidence missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_linked_transfer_chain_open` | 500 | The platform could not durably complete the `ledger linked transfer chain open` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_lookup_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger lookup confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_mapping_missing` | 500 | The platform could not durably complete the `ledger mapping missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_pending_transfer_id_missing` | 500 | The platform could not durably complete the `ledger pending transfer id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_invalid` | 500 | The platform could not durably complete the `ledger timeout invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_phase_invalid` | 500 | The platform could not durably complete the `ledger timeout phase invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_conflict` | 500 | The platform could not durably complete the `ledger transfer lookup conflict` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_request_missing` | 500 | The platform could not durably complete the `ledger transfer lookup request missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_rejected` | 409 | The request contradicts the resource the platform has already durably recorded (`ledger transfer rejected`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_transfer_result_count_mismatch` | 500 | The platform could not durably complete the `ledger transfer result count mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_result_missing` | 500 | The platform could not durably complete the `ledger transfer result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_unavailable` | 503 | The platform could not durably complete the `ledger unavailable` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | yes | no |
| `source_account_status_forbidden` | 400 | The source (debit) account is not open. It is frozen or closed, so Hyperscale will not debit it. | Use a source account whose status is `open`, or unfreeze the intended account, before retrying. | Read the account status, unfreeze it (or select an open account in the same currency and product), then resend the transfer. | no | yes |
| `source_operation_not_found` | 404 | No resource matches the `id` this request referenced (`source operation not found`). | List the collection this request referenced in the same tenant, product, and environment, then retry with an `id` that listing returns. | Create or select the resource in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `tenant_code_invalid` | 500 | The platform could not durably complete the `tenant code invalid` step, so the Company may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the Company was written. | Treat the Company's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `transfer_destination_role_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer destination role forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_lineage_conflict` | 409 | The request contradicts the resource the platform has already durably recorded (`transfer lineage conflict`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `transfer_not_found` | 404 | No resource matches the `id` this request referenced (`transfer not found`). | List the collection this request referenced in the same tenant, product, and environment, then retry with an `id` that listing returns. | Create or select the resource in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `transfer_role_pair_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer role pair forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_source_role_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer source role forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_status_forbidden` | 409 | The transfer is not in the state this operation requires (for example, posting needs a reserved transfer; returning or reversing needs a posted one). The current and required states are described in the error message. | Read the transfer's current status and call the operation that is valid for that status. | Follow the transfer lifecycle (reserve → post, then return/reverse) and issue the operation matching the transfer's current state instead of the rejected one. | no | yes |

### create

Create a two-party trade settlement

- From: none
- To: no state change
- Hints: readOnly=false, destructive=false, idempotent=true, moneyMovement=false

Exposed as:

| Program | Public action | Route |
| --- | --- | --- |
| [asset_backed_membership](../programs/asset_backed_membership.md) | `openMemberExchange` | `POST /v1/operations/trade_settlement.openMemberExchange`, scopes trade_settlement:write, idempotency required, receipt yes |
| [escrow_marketplace_sandbox](../programs/escrow_marketplace_sandbox.md) | `createMarketplaceTrade` | `POST /v1/operations/trade_settlement.createMarketplaceTrade`, scopes trade_settlement:write, idempotency required, receipt yes |

Input:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `sideAAccountId` | ref<account> | yes | First trade party and funder |
| `sideBAccountId` | ref<account> | yes | Second trade party and funder |
| `platformAccountId` | ref<account> | yes | Product revenue or customer balance account collecting trade service fees |
| `sideAAmount` | money<SAR> (minor_unit_integer_string) | yes | Amount side A holds against the whole exchange, in SAR minor units |
| `sideBAmount` | money<SAR> (minor_unit_integer_string) | yes | Amount side B holds against the whole exchange, in SAR minor units |
| `sideAServiceFeeAmount` | money<SAR> (minor_unit_integer_string) | yes | Side A custody fee charged on top and never placed in escrow |
| `sideBServiceFeeAmount` | money<SAR> (minor_unit_integer_string) | yes | Side B custody fee charged on top and never placed in escrow |
| `currency` | text | yes | One currency for both trade legs and both fees |

This action records no effect rows.

Errors beyond the 18 shared with every action on this instrument:

| Code | HTTP | Cause | Action | Remediation | Retryable | Idempotency safe |
| --- | --- | --- | --- | --- | --- | --- |
| `account_ledger_mapping_conflict` | 409 | The request contradicts the Account the platform has already durably recorded (`account ledger mapping conflict`). | Re-read the Account with `account.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Account as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `account_not_found` | 404 | No Account matches the `accountId` this request referenced (`account not found`). | List Accounts in the same tenant, product, and environment, then retry with the `accountId` that read returns. | Create or select the Account in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `cross_tenant_transfer_forbidden` | 409 | The request contradicts the resource the platform has already durably recorded (`cross tenant transfer forbidden`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `currency_invalid` | 500 | The platform could not durably complete the `currency invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `currency_mismatch` | 400 | The currency on the request does not match the settlement currency of the account or transfer it targets. Hyperscale never converts between currencies, so the two must be identical. | Read the target account's currency (for example with `account.balance.retrieve`) and resend with that same currency and a minor-unit amount denominated in it. | This is deterministic. Retrying with the same currency fails identically. Correct the request's currency field, or move the money through an account already denominated in the required currency, then retry. | no | yes |
| `customer_access_compliance_forbidden` | 403 | The request contradicts the Customer access the platform has already durably recorded (`customer access compliance forbidden`). | Re-read the Customer access with `customer_access.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Customer access as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `customer_access_required` | 403 | The operation cannot run against this Customer access until the `customer access required` prerequisite exists. | Supply the field, capability, evidence, or configuration the error details name for this Customer access, then call the operation again. | Complete the prerequisite through the surface that owns it -- the operation reference for this Customer access names it -- and the same call then succeeds unchanged. | no | yes |
| `customer_not_found` | 404 | No Customer matches the `customerId` this request referenced (`customer not found`). | List Customers in the same tenant, product, and environment, then retry with the `customerId` that read returns. | Create or select the Customer in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `customer_status_forbidden` | 403 | The Customer's current lifecycle state does not allow this transition (`customer status forbidden`). | Read the Customer with `customer.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Customer's current status permits. The reference itself is still valid, so no new Customer is needed. | no | yes |
| `entity_not_found` | 404 | No Entity matches the `entityId` this request referenced (`entity not found`). | List Entities in the same tenant, product, and environment, then retry with the `entityId` that read returns. | Create or select the Entity in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `entity_status_forbidden` | 403 | The Entity's current lifecycle state does not allow this transition (`entity status forbidden`). | Read the Entity with `entity.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Entity's current status permits. The reference itself is still valid, so no new Entity is needed. | no | yes |
| `financial_address_write_failed` | 500 | The platform could not durably complete the `financial address write failed` step, so the Financial address may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the Financial address was written. | Treat the Financial address's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `instrument_retired` | 409 | The request contradicts the resource the platform has already durably recorded (`instrument retired`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `insufficient_balance` | 409 | The source (debit) account's available balance is below the transfer amount, so the ledger refused the transfer. No money moved. The transfer was not created and its charge/transfer rows are recorded as failed. | Fund the source (debit) account so its available balance in minor units covers the full amount, or lower the amount, then retry. Confirm the shortfall first with `account.balance.retrieve`. | This is a definitive refusal, not a transient failure: replaying the exact request with the same Idempotency-Key safely returns this same refusal and never double-charges, so rotating to a fresh key is not the fix. Funding is. Top up the source account (or reduce the amount), then submit the transfer as a new request. | no | yes |
| `kyc_tier_insufficient` | 403 | Opening an account of this role requires the owning customer's entity to have ATTAINED a KYC tier it has not reached: either required fields are missing or the profile is not verified. | Complete and verify the entity's KYC profile to the tier this account role requires, then retry. The error details name the required tier and the entity's attained tier. | Submit the missing fields (`entity.kyc.submit`), run verification (`entity.kyc.verification.start`), and once the outcome is verified at the required tier the account open succeeds unchanged. `entity.kyc.retrieve` shows exactly which fields stand between the entity and the required tier. | no | yes |
| `ledger_account_rejected` | 500 | The platform could not durably complete the `ledger account rejected` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_account_result_missing` | 500 | The platform could not durably complete the `ledger account result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_address_missing` | 500 | The platform could not durably complete the `ledger address missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_amount_invalid` | 500 | The platform could not durably complete the `ledger amount invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_invalid` | 500 | The platform could not durably complete the `ledger cluster id invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_missing` | 500 | The platform could not durably complete the `ledger cluster id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_missing` | 500 | The platform could not durably complete the `ledger effect missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_not_declared` | 500 | The platform could not durably complete the `ledger effect not declared` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_evidence_missing` | 500 | The platform could not durably complete the `ledger evidence missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_linked_transfer_chain_open` | 500 | The platform could not durably complete the `ledger linked transfer chain open` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_lookup_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger lookup confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_mapping_missing` | 500 | The platform could not durably complete the `ledger mapping missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_pending_transfer_id_missing` | 500 | The platform could not durably complete the `ledger pending transfer id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_invalid` | 500 | The platform could not durably complete the `ledger timeout invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_phase_invalid` | 500 | The platform could not durably complete the `ledger timeout phase invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_conflict` | 500 | The platform could not durably complete the `ledger transfer lookup conflict` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_request_missing` | 500 | The platform could not durably complete the `ledger transfer lookup request missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_rejected` | 409 | The request contradicts the resource the platform has already durably recorded (`ledger transfer rejected`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_transfer_result_count_mismatch` | 500 | The platform could not durably complete the `ledger transfer result count mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_result_missing` | 500 | The platform could not durably complete the `ledger transfer result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_unavailable` | 503 | The platform could not durably complete the `ledger unavailable` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | yes | no |
| `tenant_code_invalid` | 500 | The platform could not durably complete the `tenant code invalid` step, so the Company may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the Company was written. | Treat the Company's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |

### dispute

Voids both pending cross-payments first, then returns each principal to its original funder in the same linked ledger batch. Service fees remain posted because they paid for custody already provided.

- From: `released`
- To: `clawed_back`
- Hints: readOnly=false, destructive=true, idempotent=true, moneyMovement=true
- Handle key: `tradeSettlementId`

Exposed as:

| Program | Public action | Route |
| --- | --- | --- |
| [escrow_marketplace_sandbox](../programs/escrow_marketplace_sandbox.md) | `disputeMarketplaceTrade` | `POST /v1/operations/trade_settlement.disputeMarketplaceTrade`, scopes trade_settlement:write, transfer:write, idempotency required, receipt yes |

Input:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `tradeSettlementId` | ref<trade_settlement> | yes | Trade settlement instance ID |
| `actorAccountId` | ref<account> | yes | Account of the party taking this action, asserted by the deciding tenant backend and checked against the instance's party bindings |

Effects:

- decides:
  - `decides.tenant_port` from `port`
- moves:
  - `moves.transfer.internal` from `moves[0]`
  - `moves.transfer.internal` from `moves[1]`
  - `moves.transfer.internal` from `moves[2]`
  - `moves.transfer.internal` from `moves[3]`
- schedules:
  - `schedules.deadline` from `deadline`

Errors beyond the 18 shared with every action on this instrument:

| Code | HTTP | Cause | Action | Remediation | Retryable | Idempotency safe |
| --- | --- | --- | --- | --- | --- | --- |
| `account_frozen` | 409 | The account is frozen. Debits always refuse while frozen; some freezes also refuse credits. The error message carries the only reason wording Hyperscale exposes. | Use a different account for this transfer leg, or have the freeze lifted before retrying. | Unfreeze the account through its lifecycle surface if you imposed the freeze; a freeze you cannot lift was imposed by the platform and clears only when the platform lifts it. | no | yes |
| `account_ledger_mapping_conflict` | 409 | The request contradicts the Account the platform has already durably recorded (`account ledger mapping conflict`). | Re-read the Account with `account.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Account as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `account_not_found` | 404 | No Account matches the `accountId` this request referenced (`account not found`). | List Accounts in the same tenant, product, and environment, then retry with the `accountId` that read returns. | Create or select the Account in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `cross_tenant_transfer_forbidden` | 409 | The request contradicts the resource the platform has already durably recorded (`cross tenant transfer forbidden`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `currency_invalid` | 500 | The platform could not durably complete the `currency invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `currency_mismatch` | 400 | The currency on the request does not match the settlement currency of the account or transfer it targets. Hyperscale never converts between currencies, so the two must be identical. | Read the target account's currency (for example with `account.balance.retrieve`) and resend with that same currency and a minor-unit amount denominated in it. | This is deterministic. Retrying with the same currency fails identically. Correct the request's currency field, or move the money through an account already denominated in the required currency, then retry. | no | yes |
| `customer_access_compliance_forbidden` | 403 | The request contradicts the Customer access the platform has already durably recorded (`customer access compliance forbidden`). | Re-read the Customer access with `customer_access.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Customer access as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `customer_access_required` | 403 | The operation cannot run against this Customer access until the `customer access required` prerequisite exists. | Supply the field, capability, evidence, or configuration the error details name for this Customer access, then call the operation again. | Complete the prerequisite through the surface that owns it -- the operation reference for this Customer access names it -- and the same call then succeeds unchanged. | no | yes |
| `customer_not_found` | 404 | No Customer matches the `customerId` this request referenced (`customer not found`). | List Customers in the same tenant, product, and environment, then retry with the `customerId` that read returns. | Create or select the Customer in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `customer_status_forbidden` | 403 | The Customer's current lifecycle state does not allow this transition (`customer status forbidden`). | Read the Customer with `customer.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Customer's current status permits. The reference itself is still valid, so no new Customer is needed. | no | yes |
| `destination_account_status_forbidden` | 400 | The destination (credit) account is not open. It is frozen or closed, so Hyperscale will not credit it. | Use a destination account whose status is `open`, or unfreeze the intended account, before retrying. | Read the account status, unfreeze it (or select an open account in the same currency and product), then resend the transfer. | no | yes |
| `entity_not_found` | 404 | No Entity matches the `entityId` this request referenced (`entity not found`). | List Entities in the same tenant, product, and environment, then retry with the `entityId` that read returns. | Create or select the Entity in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `entity_status_forbidden` | 403 | The Entity's current lifecycle state does not allow this transition (`entity status forbidden`). | Read the Entity with `entity.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Entity's current status permits. The reference itself is still valid, so no new Entity is needed. | no | yes |
| `instrument_instance_not_found` | 404 | No Instrument instance matches the `instrumentInstanceId` this request referenced (`instrument instance not found`). | List Instrument instances in the same tenant, product, and environment, then retry with the `instrumentInstanceId` that read returns. | Create or select the Instrument instance in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `insufficient_balance` | 409 | The source (debit) account's available balance is below the transfer amount, so the ledger refused the transfer. No money moved. The transfer was not created and its charge/transfer rows are recorded as failed. | Fund the source (debit) account so its available balance in minor units covers the full amount, or lower the amount, then retry. Confirm the shortfall first with `account.balance.retrieve`. | This is a definitive refusal, not a transient failure: replaying the exact request with the same Idempotency-Key safely returns this same refusal and never double-charges, so rotating to a fresh key is not the fix. Funding is. Top up the source account (or reduce the amount), then submit the transfer as a new request. | no | yes |
| `invalid_instrument_transition` | 409 | The request contradicts the resource the platform has already durably recorded (`invalid instrument transition`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_account_rejected` | 500 | The platform could not durably complete the `ledger account rejected` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_account_result_missing` | 500 | The platform could not durably complete the `ledger account result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_address_missing` | 500 | The platform could not durably complete the `ledger address missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_amount_invalid` | 500 | The platform could not durably complete the `ledger amount invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_invalid` | 500 | The platform could not durably complete the `ledger cluster id invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_missing` | 500 | The platform could not durably complete the `ledger cluster id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_missing` | 500 | The platform could not durably complete the `ledger effect missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_not_declared` | 500 | The platform could not durably complete the `ledger effect not declared` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_evidence_missing` | 500 | The platform could not durably complete the `ledger evidence missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_linked_transfer_chain_open` | 500 | The platform could not durably complete the `ledger linked transfer chain open` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_lookup_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger lookup confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_mapping_missing` | 500 | The platform could not durably complete the `ledger mapping missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_pending_transfer_id_missing` | 500 | The platform could not durably complete the `ledger pending transfer id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_invalid` | 500 | The platform could not durably complete the `ledger timeout invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_phase_invalid` | 500 | The platform could not durably complete the `ledger timeout phase invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_conflict` | 500 | The platform could not durably complete the `ledger transfer lookup conflict` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_request_missing` | 500 | The platform could not durably complete the `ledger transfer lookup request missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_rejected` | 409 | The request contradicts the resource the platform has already durably recorded (`ledger transfer rejected`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_transfer_result_count_mismatch` | 500 | The platform could not durably complete the `ledger transfer result count mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_result_missing` | 500 | The platform could not durably complete the `ledger transfer result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_unavailable` | 503 | The platform could not durably complete the `ledger unavailable` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | yes | no |
| `port_actor_not_allowed` | 409 | The request contradicts the resource the platform has already durably recorded (`port actor not allowed`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `source_account_status_forbidden` | 400 | The source (debit) account is not open. It is frozen or closed, so Hyperscale will not debit it. | Use a source account whose status is `open`, or unfreeze the intended account, before retrying. | Read the account status, unfreeze it (or select an open account in the same currency and product), then resend the transfer. | no | yes |
| `source_operation_not_found` | 404 | No resource matches the `id` this request referenced (`source operation not found`). | List the collection this request referenced in the same tenant, product, and environment, then retry with an `id` that listing returns. | Create or select the resource in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `tenant_code_invalid` | 500 | The platform could not durably complete the `tenant code invalid` step, so the Company may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the Company was written. | Treat the Company's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `transfer_destination_role_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer destination role forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_lineage_conflict` | 409 | The request contradicts the resource the platform has already durably recorded (`transfer lineage conflict`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `transfer_not_found` | 404 | No resource matches the `id` this request referenced (`transfer not found`). | List the collection this request referenced in the same tenant, product, and environment, then retry with an `id` that listing returns. | Create or select the resource in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `transfer_role_pair_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer role pair forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_source_role_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer source role forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_status_forbidden` | 409 | The transfer is not in the state this operation requires (for example, posting needs a reserved transfer; returning or reversing needs a posted one). The current and required states are described in the error message. | Read the transfer's current status and call the operation that is valid for that status. | Follow the transfer lifecycle (reserve → post, then return/reverse) and issue the operation matching the transfer's current state instead of the rejected one. | no | yes |

### fund

Fund both trade sides and collect both custody fees atomically

- From: `created`
- To: `funded`
- Hints: readOnly=false, destructive=false, idempotent=true, moneyMovement=true
- Handle key: `tradeSettlementId`

Exposed as:

| Program | Public action | Route |
| --- | --- | --- |
| [asset_backed_membership](../programs/asset_backed_membership.md) | `fundMemberExchange` | `POST /v1/operations/trade_settlement.fundMemberExchange`, scopes trade_settlement:write, transfer:write, idempotency required, receipt yes |
| [escrow_marketplace_sandbox](../programs/escrow_marketplace_sandbox.md) | `fundMarketplaceTrade` | `POST /v1/operations/trade_settlement.fundMarketplaceTrade`, scopes trade_settlement:write, transfer:write, idempotency required, receipt yes |

Input:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `tradeSettlementId` | ref<trade_settlement> | yes | Trade settlement instance ID |

Effects:

- moves:
  - `moves.collection.pay_in` from `moves[0]`
  - `moves.collection.pay_in` from `moves[1]`
  - `moves.transfer.internal` from `moves[2]`
  - `moves.transfer.internal` from `moves[3]`

Errors beyond the 18 shared with every action on this instrument:

| Code | HTTP | Cause | Action | Remediation | Retryable | Idempotency safe |
| --- | --- | --- | --- | --- | --- | --- |
| `account_frozen` | 409 | The account is frozen. Debits always refuse while frozen; some freezes also refuse credits. The error message carries the only reason wording Hyperscale exposes. | Use a different account for this transfer leg, or have the freeze lifted before retrying. | Unfreeze the account through its lifecycle surface if you imposed the freeze; a freeze you cannot lift was imposed by the platform and clears only when the platform lifts it. | no | yes |
| `account_ledger_mapping_conflict` | 409 | The request contradicts the Account the platform has already durably recorded (`account ledger mapping conflict`). | Re-read the Account with `account.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Account as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `account_not_found` | 404 | No Account matches the `accountId` this request referenced (`account not found`). | List Accounts in the same tenant, product, and environment, then retry with the `accountId` that read returns. | Create or select the Account in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `cross_tenant_transfer_forbidden` | 409 | The request contradicts the resource the platform has already durably recorded (`cross tenant transfer forbidden`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `currency_invalid` | 500 | The platform could not durably complete the `currency invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `currency_mismatch` | 400 | The currency on the request does not match the settlement currency of the account or transfer it targets. Hyperscale never converts between currencies, so the two must be identical. | Read the target account's currency (for example with `account.balance.retrieve`) and resend with that same currency and a minor-unit amount denominated in it. | This is deterministic. Retrying with the same currency fails identically. Correct the request's currency field, or move the money through an account already denominated in the required currency, then retry. | no | yes |
| `customer_access_compliance_forbidden` | 403 | The request contradicts the Customer access the platform has already durably recorded (`customer access compliance forbidden`). | Re-read the Customer access with `customer_access.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Customer access as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `customer_access_required` | 403 | The operation cannot run against this Customer access until the `customer access required` prerequisite exists. | Supply the field, capability, evidence, or configuration the error details name for this Customer access, then call the operation again. | Complete the prerequisite through the surface that owns it -- the operation reference for this Customer access names it -- and the same call then succeeds unchanged. | no | yes |
| `customer_not_found` | 404 | No Customer matches the `customerId` this request referenced (`customer not found`). | List Customers in the same tenant, product, and environment, then retry with the `customerId` that read returns. | Create or select the Customer in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `customer_status_forbidden` | 403 | The Customer's current lifecycle state does not allow this transition (`customer status forbidden`). | Read the Customer with `customer.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Customer's current status permits. The reference itself is still valid, so no new Customer is needed. | no | yes |
| `destination_account_status_forbidden` | 400 | The destination (credit) account is not open. It is frozen or closed, so Hyperscale will not credit it. | Use a destination account whose status is `open`, or unfreeze the intended account, before retrying. | Read the account status, unfreeze it (or select an open account in the same currency and product), then resend the transfer. | no | yes |
| `entity_not_found` | 404 | No Entity matches the `entityId` this request referenced (`entity not found`). | List Entities in the same tenant, product, and environment, then retry with the `entityId` that read returns. | Create or select the Entity in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `entity_status_forbidden` | 403 | The Entity's current lifecycle state does not allow this transition (`entity status forbidden`). | Read the Entity with `entity.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Entity's current status permits. The reference itself is still valid, so no new Entity is needed. | no | yes |
| `instrument_instance_not_found` | 404 | No Instrument instance matches the `instrumentInstanceId` this request referenced (`instrument instance not found`). | List Instrument instances in the same tenant, product, and environment, then retry with the `instrumentInstanceId` that read returns. | Create or select the Instrument instance in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `insufficient_balance` | 409 | The source (debit) account's available balance is below the transfer amount, so the ledger refused the transfer. No money moved. The transfer was not created and its charge/transfer rows are recorded as failed. | Fund the source (debit) account so its available balance in minor units covers the full amount, or lower the amount, then retry. Confirm the shortfall first with `account.balance.retrieve`. | This is a definitive refusal, not a transient failure: replaying the exact request with the same Idempotency-Key safely returns this same refusal and never double-charges, so rotating to a fresh key is not the fix. Funding is. Top up the source account (or reduce the amount), then submit the transfer as a new request. | no | yes |
| `invalid_instrument_transition` | 409 | The request contradicts the resource the platform has already durably recorded (`invalid instrument transition`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_account_rejected` | 500 | The platform could not durably complete the `ledger account rejected` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_account_result_missing` | 500 | The platform could not durably complete the `ledger account result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_address_missing` | 500 | The platform could not durably complete the `ledger address missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_amount_invalid` | 500 | The platform could not durably complete the `ledger amount invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_invalid` | 500 | The platform could not durably complete the `ledger cluster id invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_missing` | 500 | The platform could not durably complete the `ledger cluster id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_missing` | 500 | The platform could not durably complete the `ledger effect missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_not_declared` | 500 | The platform could not durably complete the `ledger effect not declared` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_evidence_missing` | 500 | The platform could not durably complete the `ledger evidence missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_linked_transfer_chain_open` | 500 | The platform could not durably complete the `ledger linked transfer chain open` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_lookup_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger lookup confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_mapping_missing` | 500 | The platform could not durably complete the `ledger mapping missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_pending_transfer_id_missing` | 500 | The platform could not durably complete the `ledger pending transfer id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_invalid` | 500 | The platform could not durably complete the `ledger timeout invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_phase_invalid` | 500 | The platform could not durably complete the `ledger timeout phase invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_conflict` | 500 | The platform could not durably complete the `ledger transfer lookup conflict` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_request_missing` | 500 | The platform could not durably complete the `ledger transfer lookup request missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_rejected` | 409 | The request contradicts the resource the platform has already durably recorded (`ledger transfer rejected`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_transfer_result_count_mismatch` | 500 | The platform could not durably complete the `ledger transfer result count mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_result_missing` | 500 | The platform could not durably complete the `ledger transfer result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_unavailable` | 503 | The platform could not durably complete the `ledger unavailable` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | yes | no |
| `source_account_status_forbidden` | 400 | The source (debit) account is not open. It is frozen or closed, so Hyperscale will not debit it. | Use a source account whose status is `open`, or unfreeze the intended account, before retrying. | Read the account status, unfreeze it (or select an open account in the same currency and product), then resend the transfer. | no | yes |
| `source_operation_not_found` | 404 | No resource matches the `id` this request referenced (`source operation not found`). | List the collection this request referenced in the same tenant, product, and environment, then retry with an `id` that listing returns. | Create or select the resource in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `tenant_code_invalid` | 500 | The platform could not durably complete the `tenant code invalid` step, so the Company may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the Company was written. | Treat the Company's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `transfer_destination_role_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer destination role forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_lineage_conflict` | 409 | The request contradicts the resource the platform has already durably recorded (`transfer lineage conflict`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `transfer_not_found` | 404 | No resource matches the `id` this request referenced (`transfer not found`). | List the collection this request referenced in the same tenant, product, and environment, then retry with an `id` that listing returns. | Create or select the resource in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `transfer_role_pair_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer role pair forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_source_role_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer source role forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_status_forbidden` | 409 | The transfer is not in the state this operation requires (for example, posting needs a reserved transfer; returning or reversing needs a posted one). The current and required states are described in the error message. | Read the transfer's current status and call the operation that is valid for that status. | Follow the transfer lifecycle (reserve → post, then return/reverse) and issue the operation matching the transfer's current state instead of the rejected one. | no | yes |

### release

The tenant backend confirms the entire two-sided exchange. Both cross-payments become pending reservations in one linked batch; neither party can spend them before maturity.

- From: `funded`
- To: `released`
- Hints: readOnly=false, destructive=false, idempotent=true, moneyMovement=true
- Handle key: `tradeSettlementId`

Exposed as:

| Program | Public action | Route |
| --- | --- | --- |
| [asset_backed_membership](../programs/asset_backed_membership.md) | `releaseMemberExchange` | `POST /v1/operations/trade_settlement.releaseMemberExchange`, scopes trade_settlement:write, transfer:write, idempotency required, receipt yes |
| [escrow_marketplace_sandbox](../programs/escrow_marketplace_sandbox.md) | `releaseMarketplaceTrade` | `POST /v1/operations/trade_settlement.releaseMarketplaceTrade`, scopes trade_settlement:write, transfer:write, idempotency required, receipt yes |

Input:

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `tradeSettlementId` | ref<trade_settlement> | yes | Trade settlement instance ID |
| `actorAccountId` | ref<account> | yes | Account of the party taking this action, asserted by the deciding tenant backend and checked against the instance's party bindings |

Effects:

- decides:
  - `decides.tenant_port` from `port`
- holds:
  - `holds.reserve` from `moves[0]`
  - `holds.reserve` from `moves[1]`
- moves:
  - `moves.transfer.internal` from `moves[0]`
  - `moves.transfer.internal` from `moves[1]`

Errors beyond the 18 shared with every action on this instrument:

| Code | HTTP | Cause | Action | Remediation | Retryable | Idempotency safe |
| --- | --- | --- | --- | --- | --- | --- |
| `account_frozen` | 409 | The account is frozen. Debits always refuse while frozen; some freezes also refuse credits. The error message carries the only reason wording Hyperscale exposes. | Use a different account for this transfer leg, or have the freeze lifted before retrying. | Unfreeze the account through its lifecycle surface if you imposed the freeze; a freeze you cannot lift was imposed by the platform and clears only when the platform lifts it. | no | yes |
| `account_ledger_mapping_conflict` | 409 | The request contradicts the Account the platform has already durably recorded (`account ledger mapping conflict`). | Re-read the Account with `account.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Account as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `account_not_found` | 404 | No Account matches the `accountId` this request referenced (`account not found`). | List Accounts in the same tenant, product, and environment, then retry with the `accountId` that read returns. | Create or select the Account in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `cross_tenant_transfer_forbidden` | 409 | The request contradicts the resource the platform has already durably recorded (`cross tenant transfer forbidden`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `currency_invalid` | 500 | The platform could not durably complete the `currency invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `currency_mismatch` | 400 | The currency on the request does not match the settlement currency of the account or transfer it targets. Hyperscale never converts between currencies, so the two must be identical. | Read the target account's currency (for example with `account.balance.retrieve`) and resend with that same currency and a minor-unit amount denominated in it. | This is deterministic. Retrying with the same currency fails identically. Correct the request's currency field, or move the money through an account already denominated in the required currency, then retry. | no | yes |
| `customer_access_compliance_forbidden` | 403 | The request contradicts the Customer access the platform has already durably recorded (`customer access compliance forbidden`). | Re-read the Customer access with `customer_access.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Customer access as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `customer_access_required` | 403 | The operation cannot run against this Customer access until the `customer access required` prerequisite exists. | Supply the field, capability, evidence, or configuration the error details name for this Customer access, then call the operation again. | Complete the prerequisite through the surface that owns it -- the operation reference for this Customer access names it -- and the same call then succeeds unchanged. | no | yes |
| `customer_not_found` | 404 | No Customer matches the `customerId` this request referenced (`customer not found`). | List Customers in the same tenant, product, and environment, then retry with the `customerId` that read returns. | Create or select the Customer in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `customer_status_forbidden` | 403 | The Customer's current lifecycle state does not allow this transition (`customer status forbidden`). | Read the Customer with `customer.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Customer's current status permits. The reference itself is still valid, so no new Customer is needed. | no | yes |
| `destination_account_status_forbidden` | 400 | The destination (credit) account is not open. It is frozen or closed, so Hyperscale will not credit it. | Use a destination account whose status is `open`, or unfreeze the intended account, before retrying. | Read the account status, unfreeze it (or select an open account in the same currency and product), then resend the transfer. | no | yes |
| `entity_not_found` | 404 | No Entity matches the `entityId` this request referenced (`entity not found`). | List Entities in the same tenant, product, and environment, then retry with the `entityId` that read returns. | Create or select the Entity in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `entity_status_forbidden` | 403 | The Entity's current lifecycle state does not allow this transition (`entity status forbidden`). | Read the Entity with `entity.retrieve` and pick the lifecycle operation its current status allows. | Apply a transition the Entity's current status permits. The reference itself is still valid, so no new Entity is needed. | no | yes |
| `instrument_instance_not_found` | 404 | No Instrument instance matches the `instrumentInstanceId` this request referenced (`instrument instance not found`). | List Instrument instances in the same tenant, product, and environment, then retry with the `instrumentInstanceId` that read returns. | Create or select the Instrument instance in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `insufficient_balance` | 409 | The source (debit) account's available balance is below the transfer amount, so the ledger refused the transfer. No money moved. The transfer was not created and its charge/transfer rows are recorded as failed. | Fund the source (debit) account so its available balance in minor units covers the full amount, or lower the amount, then retry. Confirm the shortfall first with `account.balance.retrieve`. | This is a definitive refusal, not a transient failure: replaying the exact request with the same Idempotency-Key safely returns this same refusal and never double-charges, so rotating to a fresh key is not the fix. Funding is. Top up the source account (or reduce the amount), then submit the transfer as a new request. | no | yes |
| `invalid_instrument_transition` | 409 | The request contradicts the resource the platform has already durably recorded (`invalid instrument transition`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_account_rejected` | 500 | The platform could not durably complete the `ledger account rejected` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_account_result_missing` | 500 | The platform could not durably complete the `ledger account result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_address_missing` | 500 | The platform could not durably complete the `ledger address missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_amount_invalid` | 500 | The platform could not durably complete the `ledger amount invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_invalid` | 500 | The platform could not durably complete the `ledger cluster id invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_cluster_id_missing` | 500 | The platform could not durably complete the `ledger cluster id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_missing` | 500 | The platform could not durably complete the `ledger effect missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_effect_not_declared` | 500 | The platform could not durably complete the `ledger effect not declared` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_evidence_missing` | 500 | The platform could not durably complete the `ledger evidence missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_linked_transfer_chain_open` | 500 | The platform could not durably complete the `ledger linked transfer chain open` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_lookup_confirmation_mismatch` | 500 | The platform could not durably complete the `ledger lookup confirmation mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_mapping_missing` | 500 | The platform could not durably complete the `ledger mapping missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_pending_transfer_id_missing` | 500 | The platform could not durably complete the `ledger pending transfer id missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_invalid` | 500 | The platform could not durably complete the `ledger timeout invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_timeout_phase_invalid` | 500 | The platform could not durably complete the `ledger timeout phase invalid` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_conflict` | 500 | The platform could not durably complete the `ledger transfer lookup conflict` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_lookup_request_missing` | 500 | The platform could not durably complete the `ledger transfer lookup request missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_rejected` | 409 | The request contradicts the resource the platform has already durably recorded (`ledger transfer rejected`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `ledger_transfer_result_count_mismatch` | 500 | The platform could not durably complete the `ledger transfer result count mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_transfer_result_missing` | 500 | The platform could not durably complete the `ledger transfer result missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `ledger_unavailable` | 503 | The platform could not durably complete the `ledger unavailable` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | yes | no |
| `port_actor_not_allowed` | 409 | The request contradicts the resource the platform has already durably recorded (`port actor not allowed`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `source_account_status_forbidden` | 400 | The source (debit) account is not open. It is frozen or closed, so Hyperscale will not debit it. | Use a source account whose status is `open`, or unfreeze the intended account, before retrying. | Read the account status, unfreeze it (or select an open account in the same currency and product), then resend the transfer. | no | yes |
| `source_operation_not_found` | 404 | No resource matches the `id` this request referenced (`source operation not found`). | List the collection this request referenced in the same tenant, product, and environment, then retry with an `id` that listing returns. | Create or select the resource in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `tenant_code_invalid` | 500 | The platform could not durably complete the `tenant code invalid` step, so the Company may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the Company was written. | Treat the Company's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `transfer_destination_role_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer destination role forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_expiry_invalid` | 400 | The submitted value is not one this resource accepts (`transfer expiry invalid`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_expiry_past` | 400 | The operation refused the request on its `transfer expiry past` contract condition. | Read the error details, then the operation reference for this resource, before retrying. | Correct the request against the generated SDK models and a fresh read of the resource; if the shape is already right, the product may be missing the capability this operation needs. | no | yes |
| `transfer_expiry_too_large` | 400 | The operation refused the request on its `transfer expiry too large` contract condition. | Read the error details, then the operation reference for this resource, before retrying. | Correct the request against the generated SDK models and a fresh read of the resource; if the shape is already right, the product may be missing the capability this operation needs. | no | yes |
| `transfer_lineage_conflict` | 409 | The request contradicts the resource the platform has already durably recorded (`transfer lineage conflict`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `transfer_not_found` | 404 | No resource matches the `id` this request referenced (`transfer not found`). | List the collection this request referenced in the same tenant, product, and environment, then retry with an `id` that listing returns. | Create or select the resource in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `transfer_role_pair_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer role pair forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_source_role_forbidden` | 400 | The submitted value is not one this resource accepts (`transfer source role forbidden`). | Replace the rejected value with one this resource allows, as listed in the API reference or set by product policy. | Rebuild the request from the generated SDK types for this resource, which carry the allowed values as unions rather than free strings. | no | yes |
| `transfer_status_forbidden` | 409 | The transfer is not in the state this operation requires (for example, posting needs a reserved transfer; returning or reversing needs a posted one). The current and required states are described in the error message. | Read the transfer's current status and call the operation that is valid for that status. | Follow the transfer lifecycle (reserve → post, then return/reverse) and issue the operation matching the transfer's current state instead of the rejected one. | no | yes |

## Steps no Product exposes

The cost table prices 1 lifecycle step that no Product in this catalog exposes as an action, so none of them is callable through a Product API. They run inside the instrument. The IR carries only their price, so price is all this page can state about them.

### post

| Action | Effect | Meter | Rate | Table version |
| --- | --- | --- | --- | --- |
| `post` | `moves.transfer.internal` | `transfer.internal.volume_sar` | 75+11bps | 2026-09-02.1 |
| `post` | `schedules.due` | `instrument.event.count` | 0 | 2026-09-02.1 |

## Reads

- `trade_settlement.list` as `trade_settlement_list`: List trade settlements
  - Route: `GET /v1/trade-settlements`, scopes trade_settlement:read, idempotency not_required, receipt yes
  - Output: items, nextCursor, statusCounts
- `trade_settlement.retrieve` as `trade_settlement_retrieve`: Retrieve a trade settlement
  - Route: `GET /v1/trade-settlements/{tradeSettlementId}`, scopes trade_settlement:read, idempotency not_required, receipt yes
  - Output: tradeSettlementId, tenantId, productId, instrumentId, status, fields, refs, createdAt, updatedAt

## Cost

| Action | Effect | Meter | Rate | Table version |
| --- | --- | --- | --- | --- |
| `cancel` | `moves.transfer.internal` | `transfer.internal.volume_sar` | 75+11bps | 2026-09-02.1 |
| `dispute` | `decides.tenant_port` | `instrument.event.count` | 0 | 2026-09-02.1 |
| `dispute` | `moves.transfer.internal` | `transfer.internal.volume_sar` | 75+11bps | 2026-09-02.1 |
| `dispute` | `schedules.deadline` | `instrument.event.count` | 0 | 2026-09-02.1 |
| `fund` | `moves.collection.pay_in` | `collection.pay_in.volume_sar` | 250+16bps | 2026-09-02.1 |
| `fund` | `moves.transfer.internal` | `transfer.internal.volume_sar` | 75+11bps | 2026-09-02.1 |
| `post` | `moves.transfer.internal` | `transfer.internal.volume_sar` | 75+11bps | 2026-09-02.1 |
| `post` | `schedules.due` | `instrument.event.count` | 0 | 2026-09-02.1 |
| `release` | `decides.tenant_port` | `instrument.event.count` | 0 | 2026-09-02.1 |
| `release` | `holds.reserve` | `instrument.event.count` | 0 | 2026-09-02.1 |
| `release` | `moves.transfer.internal` | `transfer.internal.volume_sar` | 75+11bps | 2026-09-02.1 |

## Errors on every action

The 18 errors every action on this instrument declares. An action's own section lists only what it adds beyond these.

| Code | HTTP | Cause | Action | Remediation | Retryable | Idempotency safe |
| --- | --- | --- | --- | --- | --- | --- |
| `invalid_credentials` | 401 | Hyperscale could not accept the account or credential request. Signup, login, and bearer authentication use one 401 for every case they reject, so the response exposes no credential-specific reason or registered-email verdict. The single exception is a key that is real but homed in the other environment: because the presented secret already matched a stored key, the message names the mismatch instead of leaving a working credential looking unknown. | For signup or login, re-check the submitted account details. For API calls, re-check the `Authorization: Bearer <key>` API key and whether it matches the target environment (sandbox vs live). | For signup, verify the submitted details or use login or password reset for an existing account. For login, re-enter the credentials or reset the password. For API or MCP calls, use an active key for the target environment, set HYPERSCALE_API_KEY, and retry. When the message reports an environment mismatch, `details.keyEnvironment` names where the key does work: send that environment's key, or set `X-Hyperscale-Environment` to it. | no | yes |
| `local_evidence_output_key_missing` | 500 | The platform could not durably complete the `local evidence output key missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `local_evidence_reference_missing` | 500 | The platform could not durably complete the `local evidence reference missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `local_evidence_resource_missing` | 500 | The platform could not durably complete the `local evidence resource missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `mfa_verification_required` | 403 | This tenant surface requires a session that completed TOTP at login. Tenant operations demand it while the organization's require-MFA policy (tenant.security.configure) is on; user.mfa.totp.disable demands it unconditionally, because removing a factor is the act that factor exists to guard. | Enroll and confirm a TOTP factor (user.mfa.totp.enrollment.begin, then user.mfa.totp.enrollment.confirm), then log in again and complete user.login.mfa.verify before retrying. | MFA verification is a mint-time session fact, so enrolling a factor mid-session never upgrades the current session. After the factor is active, a fresh login returns an MFA challenge; completing it mints the verified session this surface demands. Identity self-operations (logout, TOTP enrollment) stay open to a password-only session, so a factorless member is never locked out of enrolling. Disabling a factor is the exception: sign in again and complete the challenge first. | no | yes |
| `operation_insert_failed` | 500 | The platform could not durably complete the `operation insert failed` step, so the Operation may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the Operation was written. | Treat the Operation's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `operation_not_finalized` | 409 | The request contradicts the Operation the platform has already durably recorded (`operation not finalized`). | Re-read the Operation with `operation.retrieve` and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the Operation as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `product_not_found` | 404 | No Product matches the `productId` this request referenced (`product not found`). | List Products in the same tenant, product, and environment, then retry with the `productId` that read returns. | Create or select the Product in the environment the call runs against; ids never carry across tenants, or across sandbox and live. | no | yes |
| `session_expired` | 401 | The operation refused the request on its `session expired` contract condition. | Read the error details, then the operation reference for this resource, before retrying. | Correct the request against the generated SDK models and a fresh read of the resource; if the shape is already right, the product may be missing the capability this operation needs. | no | yes |
| `session_required` | 401 | The operation cannot run against this resource until the `session required` prerequisite exists. | Supply the field, capability, evidence, or configuration the error details name for this resource, then call the operation again. | Complete the prerequisite through the surface that owns it -- the operation reference for this resource names it -- and the same call then succeeds unchanged. | no | yes |
| `session_revoked` | 401 | The operation refused the request on its `session revoked` contract condition. | Read the error details, then the operation reference for this resource, before retrying. | Correct the request against the generated SDK models and a fresh read of the resource; if the shape is already right, the product may be missing the capability this operation needs. | no | yes |
| `tenant_code_missing` | 500 | The platform could not durably complete the `tenant code missing` step, so the Company may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the Company was written. | Treat the Company's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `usage_amount_missing` | 500 | The platform could not durably complete the `usage amount missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `usage_currency_mismatch` | 500 | The platform could not durably complete the `usage currency mismatch` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `usage_meter_missing` | 500 | The platform could not durably complete the `usage meter missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `usage_source_conflict` | 409 | The request contradicts the resource the platform has already durably recorded (`usage source conflict`). | Re-read the resource this request referenced and compare the submitted ids, currency, product, tenant, and expected state against what comes back. | Rebuild the request from the resource as it now stands, then retry under a NEW idempotency key -- reuse the original key only when you are deliberately replaying the original mutation. | no | yes |
| `usage_tenant_missing` | 500 | The platform could not durably complete the `usage tenant missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
| `usage_transfer_missing` | 500 | The platform could not durably complete the `usage transfer missing` step, so the resource may or may not have been written. | Capture the request id and the receipt or operation id before retrying or escalating; do not re-send under a fresh key until you know whether the resource was written. | Treat the resource's side effects as unknown unless a terminal receipt says otherwise; retry only operations documented as retryable, and replay them with the SAME idempotency key. | no | no |
