---
title: "Execute a swap"
method: POST
path: "/money/swaps"
tags: ["money", "swaps", "customer-session"]
---

# Execute a swap

`POST /money/swaps`

## Request

- Base URL: `https://api.stablesea.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.stablesea.com/money/swaps`
- Auth: none declared. Required headers: `Idempotency-Key`

Executes a firm swap quote (POST /money/swap_quotes) in the business's Go Account and answers the swap's transaction with outcome=created. The swap is final once transaction.status is completed; it reads failed, with no money moved, when the provider refuses or kills the order. A quote executes once, before its expires_ts.

Every check the quote ran runs again, then the business must not be archived or locked and must have signed its service agreements. Refusals: quote_not_found (404), quote_expired, swap_quote_used (409, the quote already executed), and the quote's own codes. Requires kyb_locked, and assets_buy to swap USDC out or assets_sell to swap USDT into USDC. A business whose swap money movement type is off is refused with 403 money_movement_type_disabled.

Requires an Idempotency-Key. A key already used with the same body is refused with 409 duplicate_idempotency_key, and with a different body with 400 idempotency_key_body_mismatch. After a lost response, GET /money/swap_submissions finds the swap by the key; never execute the quote again under a new key.

## Headers

- `Idempotency-Key` string, required: Required client idempotency key; a duplicate submission with the same key is rejected with 409. Keep it: GET /money/swap_submissions finds the swap by it.

## Request body

- SwapsCreateSwapInput
  - `quote_id` string, required: The firm quote to execute (POST /money/swap_quotes). A quote executes once, before its expires_ts.

## Response `200`

OK

- MoneyMovementsCreateMoneyMovementOutput
  - `money_movement_id` string
  - `outcome` 'created' | 'approval_pending'
  - `transaction` MoneyMovementsMoneyMovementView
    - `automation_id` string, nullable
    - `complete` boolean, required
    - `completed_ts` string, date-time
    - `controls` WithdrawaltraceEvaluation[]: Last recorded customer-visible evaluations for this withdrawal. Missing evidence does not imply that a control was disabled.
      - `evaluated_ts` string, date-time, required
      - `result` 'passed' | 'waiting', required
      - `type` 'rail_access' | 'agreements' | 'destination' | 'withdrawal_limit' | 'business_eligibility' | 'approval' | 'release_delay' | 'destination_cooloff' | 'destination_authorization', required
    - `created_by` string, required
    - `created_ts` string, date-time, required
    - `estimated_execution_ts` string, date-time: Estimated time the trade of a movement with execution=after_funding is placed, while it has not been placed yet and that time has not passed. An estimate, not a commitment.
    - `execution` 'after_funding'
    - `failed_ts` string, date-time
    - `fee` MoneyfmtMoneyAmountView
      - `float` number, double, required
      - `formatted` MoneyfmtFormattedMoneyAmountView, required
        - `compact` string, required
        - `currency_sign` string, required
        - `currency_sign_position` string, required
        - `full` string, required
      - `precise` string, required
      - `symbol` string, required
      - `zero` boolean, required
    - `fund_symbol` string
    - `group_id` string, required
    - `id` string, required
    - `input` MoneyMovementsTransactionSideView, required
      - `amount` MoneyfmtMoneyAmountView, required
        - `float` number, double, required
        - `formatted` MoneyfmtFormattedMoneyAmountView, required
          - `compact` string, required
          - `currency_sign` string, required
          - `currency_sign_position` string, required
          - `full` string, required
        - `precise` string, required
        - `symbol` string, required
        - `zero` boolean, required
      - `amount_estimated` boolean, required: Whether amount is still an estimate — the leg's quoted subtotal, carried because the leg's figure is not final. True means the figure can still move and must be presented as an estimate rather than as a settled one. False means it can no longer change, either because the leg reached a terminal state or because it carries the figure the customer named at order entry (a fund buy's dollars, a fund sell's shares); it does not promise the figure was observed.
      - `money_account_id` string, required
      - `money_symbol` string, required
      - `payment_rail` string
      - `quoted_amount` MoneyfmtMoneyAmountView
        - `float` number, double, required
        - `formatted` MoneyfmtFormattedMoneyAmountView, required
          - `compact` string, required
          - `currency_sign` string, required
          - `currency_sign_position` string, required
          - `full` string, required
        - `precise` string, required
        - `symbol` string, required
        - `zero` boolean, required
    - `metadata` MoneyMovementsMovementMetadataView, required
      - `created_by` string, required
      - `created_ts` string, date-time, required
      - `updated_ts` string, date-time, required
    - `net_amount_estimated` boolean: Whether net_amount_view can still move. True while the cash leg it is computed from is neither final nor the figure the customer named at order entry, in which case the settled net is for now the quoted one. Always false on a fund buy, whose cash figure the customer fixed when placing the order; a BTC trade order gets no such exemption in either direction. False when there is no net amount at all, so read it only alongside net_amount_view.
    - `net_amount_view` MoneyfmtMoneyAmountView
      - `float` number, double, required
      - `formatted` MoneyfmtFormattedMoneyAmountView, required
        - `compact` string, required
        - `currency_sign` string, required
        - `currency_sign_position` string, required
        - `full` string, required
      - `precise` string, required
      - `symbol` string, required
      - `zero` boolean, required
    - `occurred_ts` string, date-time, required
    - `offramp_amounts` MoneyMovementsOfframpAmountsView
      - `bank_fee_usd` string, required
      - `collected_platform_fee_usdc` string, required
      - `collection_status` 'not_needed' | 'pending' | 'collected' | 'failed', required
      - `payout_delivered` boolean, required
      - `payout_estimated` boolean, required
      - `payout_usd` string, required
      - `platform_fee_usdc` string, required
      - `total_debit_usdc` string, required
    - `onchain_transactions` MoneyMovementsOnchainTransactionView[]
      - `chain` string
      - `explorer_url` string
      - `tx_hash` string, required
    - `onramp_amounts` MoneyMovementsOnrampAmountsView
      - `collected_platform_fee_usdc` string, required
      - `collection_status` 'not_needed' | 'pending' | 'collected' | 'failed' | 'insufficient_proceeds', required
      - `first_observed_ts` string, date-time, nullable
      - `gross_deposit_usd` string, required
      - `gross_proceeds_usdc` string, required
      - `net_usdc` string, required
      - `platform_fee_usdc` string, required
      - `pricing_basis` string, nullable
      - `pricing_ts` string, date-time, nullable
      - `proceeds_available` boolean, required
      - `proceeds_estimated` boolean, required
    - `output` MoneyMovementsTransactionSideView, required
      - `amount` MoneyfmtMoneyAmountView, required
        - `float` number, double, required
        - `formatted` MoneyfmtFormattedMoneyAmountView, required
          - `compact` string, required
          - `currency_sign` string, required
          - `currency_sign_position` string, required
          - `full` string, required
        - `precise` string, required
        - `symbol` string, required
        - `zero` boolean, required
      - `amount_estimated` boolean, required: Whether amount is still an estimate — the leg's quoted subtotal, carried because the leg's figure is not final. True means the figure can still move and must be presented as an estimate rather than as a settled one. False means it can no longer change, either because the leg reached a terminal state or because it carries the figure the customer named at order entry (a fund buy's dollars, a fund sell's shares); it does not promise the figure was observed.
      - `money_account_id` string, required
      - `money_symbol` string, required
      - `payment_rail` string
      - `quoted_amount` MoneyfmtMoneyAmountView
        - `float` number, double, required
        - `formatted` MoneyfmtFormattedMoneyAmountView, required
          - `compact` string, required
          - `currency_sign` string, required
          - `currency_sign_position` string, required
          - `full` string, required
        - `precise` string, required
        - `symbol` string, required
        - `zero` boolean, required
    - `price_per_unit_estimated` boolean: Whether price_per_unit_view was derived from a leg whose figure is not final, so the price can still move. True until both the cash leg and the share leg are final, because a fund trade prices at the net asset value struck at settlement; either leg alone is enough. False when there is no price at all, so read it only alongside price_per_unit_view.
    - `price_per_unit_view` MoneyfmtMoneyAmountView
      - `float` number, double, required
      - `formatted` MoneyfmtFormattedMoneyAmountView, required
        - `compact` string, required
        - `currency_sign` string, required
        - `currency_sign_position` string, required
        - `full` string, required
      - `precise` string, required
      - `symbol` string, required
      - `zero` boolean, required
    - `quoted_net_amount_view` MoneyfmtMoneyAmountView
      - `float` number, double, required
      - `formatted` MoneyfmtFormattedMoneyAmountView, required
        - `compact` string, required
        - `currency_sign` string, required
        - `currency_sign_position` string, required
        - `full` string, required
      - `precise` string, required
      - `symbol` string, required
      - `zero` boolean, required
    - `quoted_price_per_unit_view` MoneyfmtMoneyAmountView
      - `float` number, double, required
      - `formatted` MoneyfmtFormattedMoneyAmountView, required
        - `compact` string, required
        - `currency_sign` string, required
        - `currency_sign_position` string, required
        - `full` string, required
      - `precise` string, required
      - `symbol` string, required
      - `zero` boolean, required
    - `ramp_fee_returns` MoneyMovementsRampFeeReturnsView
      - `original_movement_id` string, nullable
      - `refund_movement_ids` string[], nullable, required
      - `refunded` boolean, required
      - `refunded_usdc` string, required
      - `waived` boolean, required
    - `settlement_commission_view` MoneyfmtMoneyAmountView
      - `float` number, double, required
      - `formatted` MoneyfmtFormattedMoneyAmountView, required
        - `compact` string, required
        - `currency_sign` string, required
        - `currency_sign_position` string, required
        - `full` string, required
      - `precise` string, required
      - `symbol` string, required
      - `zero` boolean, required
    - `settlement_pathway` string
    - `settlement_ts` string, date-time
    - `status` 'pending' | 'completed' | 'failed', required
    - `swap` MoneyMovementsSwapTradeView
      - `chain` 'arbitrum' | 'base' | 'ethereum' | 'polygon' | 'solana' | 'stellar', required
      - `rate` string, required: The rate the trade filled at, to the asset received per one asset sent, before the swap fee: a decimal string at eight places.
      - `trade_booked` boolean, required: Whether the swap's trade is booked: both of its legs completed. A pending swap with a booked trade is waiting on its fee transfer. A failed swap with a booked trade moved the trade's funds; a failed one without moved nothing.
    - `transaction_count` integer, required
    - `type` string, required
  - `transfer_approval` MoneyMovementsTransferApprovalView
    - `also_required_ind_id` string, nullable
    - `also_required_name` string
    - `also_required_satisfied` boolean
    - `amount_usd` MoneyfmtMoneyAmountView
      - `float` number, double, required
      - `formatted` MoneyfmtFormattedMoneyAmountView, required
        - `compact` string, required
        - `currency_sign` string, required
        - `currency_sign_position` string, required
        - `full` string, required
      - `precise` string, required
      - `symbol` string, required
      - `zero` boolean, required
    - `approvals_received` integer
    - `composed_policy` MoneyMovementsApprovalPolicyView
      - `action_allowed` boolean
      - `business_policy_revision` string, nullable
      - `permission_allowed` boolean
      - `requirements` MoneyMovementsApprovalClauseView[], nullable
        - `approvals_received` integer
        - `count` integer
        - `excluded_individual_ids` string[]
        - `individual_id` string
        - `individual_name` string
        - `kind` 'ordinary_quorum' | 'additional_named' | 'selected_member'
        - `progress_available` boolean
        - `satisfied` boolean
        - `source` 'business' | 'member'
      - `revision` string
      - `valuation` MoneyMovementsApprovalPolicyValuationView
        - `amount_usd` string, nullable
        - `amount_usd_view` union
          - MoneyfmtMoneyAmountView
            - `float` number, double, required
            - `formatted` MoneyfmtFormattedMoneyAmountView, required
              - …
            - `precise` string, required
            - `symbol` string, required
            - `zero` boolean, required
          - unknown
        - `status` 'valued' | 'unavailable'
    - `controls` WithdrawaltraceEvaluation[]: Last recorded customer-visible control evaluations. Missing or empty evidence does not imply that a control was disabled.
      - `evaluated_ts` string, date-time, required
      - `result` 'passed' | 'waiting', required
      - `type` 'rail_access' | 'agreements' | 'destination' | 'withdrawal_limit' | 'business_eligibility' | 'approval' | 'release_delay' | 'destination_cooloff' | 'destination_authorization', required
    - `current_approver_names` string[], nullable: Current eligible approver display names excluding the requester; null when roster progress is unavailable.
    - `decided_by` string, nullable
    - `decided_ts` string, date-time, nullable
    - `decider_name` string: Historical tenant member display name of the final decider; omitted when no person decided.
    - `decision_comment` string: Optional comment from a recorded execution recovery decision, attributed to decided_by and decided_ts. Original vote comments remain on vote rows. The legacy decision_note can repeat a successful final decision's comment or contain a system outcome note.
    - `decision_note` string
    - `expires_ts` string, date-time
    - `flow_label` string
    - `group_id` string
    - `human_approval` 'unknown' | 'none' | 'required', required: Whether the saved request requires human approval. Unknown when historical requirements cannot be read.
    - `id` string
    - `money_movement_id` string, nullable
    - `native_asset` MoneyMovementsTransferApprovalAssetDisplay
      - `amount` string
      - `network` string
      - `symbol` string
    - `progress_available` boolean
    - `rail` string
    - `ramp_fees` MoneyMovementsRampFeeDisclosure
      - `bank_fee_usd` string, required
      - `platform_fee_usdc` string, required
      - `total_debit_usdc` string, required
    - `release_ts` string, date-time, nullable: Earliest permitted execution time. Passing this time does not confirm execution; status and money_movement_id report the outcome.
    - `request_summary` MoneyMovementsTransferApprovalInstructions
      - `action` 'buy' | 'sell' | 'withdrawal'
      - `amount` MoneyfmtMoneyAmountView
        - `float` number, double, required
        - `formatted` MoneyfmtFormattedMoneyAmountView, required
          - `compact` string, required
          - `currency_sign` string, required
          - `currency_sign_position` string, required
          - `full` string, required
        - `precise` string, required
        - `symbol` string, required
        - `zero` boolean, required
      - `asset_symbol` string
      - `destination` MoneyMovementsTransferApprovalDestination
        - `account_id` string
        - `masked_account` string
        - `masked_address` string
      - `fund_route` MoneyMovementsTransferApprovalFundRoute
        - `pathway` 'standard' | 'express'
        - `pathway_defaulted` boolean
        - `source` 'platform' | 'stellar' | 'solana'
        - `source_defaulted` boolean
        - `source_network` 'ethereum' | 'stellar' | 'solana'
    - `requested_by` string
    - `requested_ts` string, date-time
    - `requester_name` string
    - `required_approvals` integer
    - `selected_approver_name` string
    - `selected_approver_satisfied` boolean
    - `status` 'pending' | 'approved' | 'denied' | 'cancelled' | 'expired' | 'policy_changed' | 'failed'
    - `valuation_unavailable` boolean
    - `votes` MoneyMovementsTransferApprovalVoteView[], nullable
      - `approver` string
      - `approver_name` string: Approver full name from historical business membership; a team member when identity is unavailable. Display only, independent of current voting eligibility.
      - `decision` 'approved' | 'denied'
      - `note` string: Optional plain-text comment recorded with this immutable decision.
      - `voted_ts` string, date-time

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not Found
- `409`: Conflict
- `503`: Service Unavailable
- `default`: Error response.

## Changes

- **2026-10-29** `e003c8a67b62`: 7 info
  - added the optional property `error/authorization` to the response with the `400` status
  - added the optional property `error/authorization` to the response with the `401` status
  - added the optional property `error/authorization` to the response with the `403` status
  - added the optional property `error/authorization` to the response with the `404` status
  - …3 more
- **2026-10-29** `423f3ae9eca6`: 2 info
  - added the optional property `transaction/controls` to the response with the `200` status
  - added the optional property `transfer_approval/controls` to the response with the `200` status
- **2026-10-28** `025b2fda2a84`: 2 info
  - added the optional property `transfer_approval/release_ts` to the response with the `200` status
  - added the required property `transfer_approval/human_approval` to the response with the `200` status
- **2026-10-26** `d133adcfb3dc`: 1 info
  - api tag `customer-session` added
- **2026-10-26** `60b71ced57db`: 1 info
  - added the required property `transaction/swap/trade_booked` to the response with the `200` status

[Operation history](https://skmtc.dev/stablesea/apis/stable-sea-backend/changes/money/swaps/post.md)

---

[API](https://skmtc.dev/stablesea/apis/stable-sea-backend.md) - [All operations](https://skmtc.dev/stablesea/apis/stable-sea-backend/llms.txt) - [OpenAPI document](https://skmtc.dev/stablesea/apis/stable-sea-backend/revisions/772c80d83658?raw)
