---
title: "Swap funds"
method: POST
path: "/swap"
tags: ["Fund"]
---

# Swap funds

`POST /swap`

## Request

- Base URL: `https://openapi.infini.money/v2/funds`
- URL: `https://openapi.infini.money/v2/funds/swap`
- Auth: API key in header `Authorization`
- TypeScript: <https://skmtc.dev/infini/apis/infini-fund-api/docs/swap/post.ts> (a function with typed inputs; its response is checked against the schema)

Exchanges between two different existing USDC, USDT, or USD WALLET accounts owned by the merchant associated with the API key. Requires `fund.withdraw` permission.

A USD Cash Account must already exist when either currency is USD. USDC/USDT swaps do not require a USD account. This endpoint does not open accounts.

Executes synchronously at the current applicable exchange rate and FX fee. No quote or rate reservation is required. `amount` includes the FX fee, charged in the source currency. A positive effective FX fee is rounded up to the smallest source currency unit (USD 0.01; USDC/USDT 0.000001). Explicit zero-rate merchant policies and exempt currency pairs still charge zero. The net amount is converted and truncated to target currency precision (USD: 2 decimals; USDC/USDT: 6).

`min_output_amount` is optional, non-negative, and denominated in the target currency. If the net rounded output falls below it, or rounds to zero, the swap is rejected without any debit or credit. Omitting it accepts the execution-time rate.

`request_id` is required and must be a UUID. Completed requests are persisted atomically with ledger changes. A retry by the same merchant returns the original output, price, and fee with `is_duplicate=true`, even after API key rotation. Changing either currency, amount, or minimum under the same ID is rejected. IDs are scoped to this operation and merchant. BW/RW identifiers are not supported. Failed attempts do not reserve a price or persist a completed result.

## Headers

- `X-API-Key-ID` string, required
- `X-API-Timestamp` string, required
- `X-API-Nonce` string, required
- `Digest` string, required
- `Authorization` string, required

## Request body

- SwapRequest
  - `request_id` string, uuid, required: Required UUID idempotency key; reuse on retry with unchanged parameters.
  - `source_currency` 'USDC' | 'USDT' | 'USD', required: Source WALLET currency; must differ from target_currency.
  - `target_currency` 'USDC' | 'USDT' | 'USD', required: Target WALLET currency.
  - `amount` string, required: Positive total source debit including FX fee. Plain decimal, no exponent; USD allows 2 decimals, USDC/USDT 6. Minor-unit value must fit a signed 64-bit integer.
  - `min_output_amount` string: Optional non-negative minimum net target amount, using target currency precision and the same minor-unit range. Omission accepts the execution-time output. Zero disables the minimum but zero actual output is always rejected.

## Response `200`

Completed swap or a business error in the standard envelope

- union
  - SwapEnvelope
    - `code` 0, required: Business code. `0` means success.
    - `message` string, required: Response message.
    - `data` SwapResponse, required
      - `request_id` string, uuid, required: Canonical request UUID.
      - `output_amount` string, required: Actual net amount credited to the target WALLET after FX fee and precision truncation.
      - `price` string, required: Executed exchange rate, in target units per one source unit, before deducting FX fee. This is not a guaranteed rate for future requests.
      - `fx_fee` string, required: FX fee included in the total source debit.
      - `fx_fee_currency` 'USDC' | 'USDT' | 'USD', required: Currency of the FX fee, equal to source_currency.
      - `is_duplicate` boolean, required: True when returning the original completed result without exchanging again.
  - ErrorEnvelope
    - `code` integer, required: Non-zero business error code.
    - `message` string, required: Error details.
    - `data` object, nullable, required: Error responses return null.

## Other responses

- `401`: Authentication failed: invalid/disabled credential, signature, timestamp, nonce or digest.
- `403`: Authenticated credential lacks permission or the client IP is not allowed.

## Changes

- **2026-10-23** `b9ee797f5199`: 7 breaking, 1 warning
  - added the new required `header` request parameter `X-API-Key-ID`
  - added the new required `header` request parameter `X-API-Nonce`
  - added the new required `header` request parameter `X-API-Timestamp`
  - the `header` request parameter `Authorization` became required
  - …4 more
- **2026-09-22** `b02cebfd84e4`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/infini/apis/infini-fund-api/changes/swap/post.md)

---

[API](https://skmtc.dev/infini/apis/infini-fund-api.md) - [All operations](https://skmtc.dev/infini/apis/infini-fund-api/llms.txt) - [OpenAPI document](https://skmtc.dev/infini/apis/infini-fund-api/revisions/b9ee797f5199?raw)
