> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dakota.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Advanced Flows

> Single-use payouts and swaps, international bank destinations, and other less common Dakota flows.

This page covers flows that branch off the core walkthrough in [Common Flows](/documentation/common-flows). Read that page first — it introduces Customer, Recipient, Destination, and Account. Everything here assumes those are already in place.

**On this page:**

* [One-off Offramp](#one-off-offramp-single-usd-payout)
* [SWIFT Payouts](#swift-payouts-international-wire)
* [One-off Swap](#one-off-swap-single-cross-chain-swap)
* [Developer Fees](#developer-fees)

## One-off Offramp (Single USD Payout)

Use a one-off offramp when you need a single USD payout — a vendor invoice, a customer refund, a scheduled disbursement — and want to embed a human-readable reference on the bank wire. One-offs generate a single-use crypto deposit address that's discarded after the transaction completes.

**What one-off offramps give you over a reusable offramp account:**

* `payment_reference` — text carried into the bank wire. Per-rail constraints:

  * **ACH** — 1 to 18 chars. Letters, digits, and spaces only (no hyphens or punctuation). Delivered as the ACH addenda.
  * **Wire (Fedwire)** — 1 to 140 chars. Delivered as the wire message.
  * **SWIFT** — 5 to 140 chars across at most 4 lines of 35 characters. Letters, digits, spaces, commas, and periods only. Carried as the wire's remittance information; whether the payee sees it depends on the receiving bank and any intermediaries, so do not rely on it for payee-side reconciliation.

  Your recipient sees this on their statement and uses it to reconcile against an invoice number. (SEPA is not currently offered as a payout rail.)
* `destination_payment_rail` — override the rail per transaction (e.g. force `fedwire` instead of the destination's default `ach`).
* `developer_fee_bps` or `developer_fee_fixed` — developer fee for this transaction, as a percentage in basis points or as a fixed amount in the deposited asset. Send one or neither; omitted means no developer fee. The rate is returned when you read the one-off transaction (`developer_fee_bps` is `0` when none was set, and `developer_fee_fixed` is present only when you set it), and the fee actually charged appears as `developer_fee` in each transaction's `receipt` (`client_fee` is its deprecated alias, with the same value). See [Developer Fees](#developer-fees).

```mermaid theme={null}
sequenceDiagram
    participant App as Your App
    participant Blockchain
    participant Dakota
    participant Bank

    App->>Dakota: POST /transactions (transaction_type: one_off)
    Dakota-->>App: crypto_address (single-use)
    App->>Blockchain: Send the amount you want converted to crypto_address
    Blockchain->>Dakota: Stablecoin received
    Dakota->>App: Webhook: transaction.one_off.created
    Dakota->>Bank: Wire USD with payment_reference
    Dakota->>App: Webhook: transaction.one_off.updated (completed)
```

### Create the One-off Transaction

Prerequisite: a bank Destination (`destination_type: "fiat_us"`) already attached to a Recipient for this Customer — see [Add a Bank Destination](/documentation/common-flows#add-a-bank-destination-for-offramps).

```bash theme={null}
curl -X POST https://api.platform.dakota.xyz/transactions \
  -H "X-API-Key: $DAKOTA_API_KEY" \
  -H "X-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_type": "one_off",
    "customer_id": "2LfTd6QQrUyPKwRR9qMMyk7CMHS",
    "amount": "1250.00",
    "source_network_id": "ethereum-mainnet",
    "source_asset": "USDC",
    "destination_id": "2LfYm5KMnRvLFtRP7nJJug4zBAN",
    "destination_asset": "USD",
    "destination_payment_rail": "ach",
    "payment_reference": "INV 2024 042"
  }'
```

**Response:**

```json theme={null}
{
  "id": "2LfZn6LNoSvMGuSQ0pLLof1OneA",
  "resource_type": "one_off",
  "status": "pending",
  "crypto_address": "0xabc...",
  "source_network_id": "ethereum-mainnet",
  "source_asset": "USDC",
  "payment_reference": "INV 2024 042"
}
```

Send the USDC you want converted to `crypto_address`. You choose the amount — Dakota does not return a deposit quote to send against — and Dakota converts what arrives and wires the proceeds to the bank Destination with `INV 2024 042` included as the payment reference. Subscribe to `transaction.one_off.created` and `transaction.one_off.updated` to track status.

<Warning>
  **Send it in a single transfer.** A one-off address accepts exactly one deposit. Anything sent after the first deposit — a second instalment, a top-up, a retry — is refused, and refused does not mean returned: the funds arrive, are held, and can only be recovered by [Dakota support](https://support.dakota.xyz). This applies from the moment the first deposit lands, not from when the transaction completes. If you need to send more, create another one-off transaction.
</Warning>

`amount` on the request is the destination amount you expect. It is optional and used for validation — it does not determine how much you send. When omitted, Dakota still converts and delivers whatever you deposit.

**Reconcile against `receipt.output`.** It reports what Dakota sent to the destination. Do not reconcile against the `destination_amount` field on `transaction.one_off.*` events: that echoes the `amount` you requested (or `0` if you omitted it) and is never updated to the delivered figure. On the `swift` rail, the beneficiary's bank and intermediary banks can deduct their fees from the wire, so the beneficiary can receive less than `receipt.output`. See [SWIFT Payouts](#swift-payouts-international-wire).

The request above sets no `developer_fee_bps`, so nothing is deducted and a 1,250.00 USDC deposit converts in full. When you do set one, it is taken from your deposit before conversion and so reduces what reaches the destination: at 25 bps, a 1,250.00 USDC deposit gives up 3.125 USDC, leaving 1,246.875 USDC to convert and wire. Dakota's own fee is billed separately on your invoice and is not taken out of the deposit. To have a destination receive an exact amount, size the deposit to cover the developer fee yourself. With a fixed fee that is simply `amount` plus the fee; see [Fixed fees on one-off transactions](#fixed-fees-on-one-off-transactions). In each transaction's `receipt`, `developer_fee` is the developer fee that was deducted (the deprecated `client_fee` carries the same value) and `dakota_fee` is the separately-billed amount, recorded for reference.

<Warning>
  Sandbox object-create endpoints reject mainnet network IDs and cap per-request `amount` at \$2 USD. USDT is not yet supported in sandbox (coming soon); USD, USDC, and RD work today. See [Testing — Sandbox restrictions](/documentation/testing#sandbox-restrictions).
</Warning>

***

## SWIFT Payouts (International Wire)

SWIFT is Dakota's international wire rail. Use it to pay recipients whose bank accounts are outside the US domestic rails (ACH, Fedwire, FedNow). SWIFT payouts support USD and foreign currencies. Foreign-currency (FX) payouts require FX access to be enabled for the account and are priced by quote: call [`GET /customers/{customer_id}/fx-currencies`](/api-reference/customers/list-available-swift-fx-currencies) to see which currencies are available and [`POST /fx/quotes`](/api-reference/transactions/request-a-directional-fx-quote-or-estimate) to price one. Fixed (rate-locked) quotes are available on request and are not generally available yet. FX in sandbox is coming and a guide will follow. SWIFT payouts settle in 1–3 business days, and is gated on the customer's `international_wire` capability. If your customer does not have that capability, contact [Dakota support](https://support.dakota.xyz).

<Note>
  **Bank fees are taken out of the wire.** Bank charges on an international wire are deducted from the amount sent, so in effect the sender pays them. The beneficiary's bank, and any intermediary bank on the route, take their fees out of the wire, and the beneficiary receives less than `receipt.output`. Dakota does not control these deductions and is not told about them: they do not appear in `receipt.external_fee`, and the transaction completes as sent. If the beneficiary must receive an exact amount, allow for the charges when you size the payout.
</Note>

### Set up a SWIFT offramp

1. **Create a Recipient with a physical address.** An address is required before adding any fiat destination — see [Destinations & Recipients](/documentation/destinations-recipients#creating-recipients).
2. **Add a `fiat_iban` Destination** to the Recipient with `capabilities: ["swift"]`. Include `iban`, `account_holder_name`, `account_holder_address`, `bank_name`, and `bic`. `bank_address` is required whenever `bic` is provided. See the [IBAN destination fields](/documentation/destinations-recipients#creating-iban-destinations).
3. **Create the offramp Account** pointing at that destination:

```bash theme={null}
curl -X POST https://api.platform.dakota.xyz/accounts \
  -H "X-API-Key: $DAKOTA_API_KEY" \
  -H "X-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "account_type": "offramp",
    "fiat_destination_id": "2LfYm5KMnRvLFtRP7nJJug4zBAN",
    "source_asset": "USDC",
    "source_network_id": "ethereum-mainnet",
    "destination_asset": "USD",
    "rail": "swift"
  }'
```

Each stablecoin deposit to the returned `source_crypto_address` triggers a USD SWIFT wire to the IBAN destination. For a single payout instead of a reusable account, create a [one-off offramp](#one-off-offramp-single-usd-payout) with `destination_payment_rail: "swift"`.

### SWIFT for onramps

SWIFT also works as an inbound rail. Include `swift` in `capabilities` when creating an onramp account; this narrows the account to SWIFT deposits. The returned `bank_account` deposit instructions then carry the BIC and the beneficiary's postal address (`account_holder_address`) — give the sender both, along with the account details. The sender's bank asks for the beneficiary address on international wires, and the sender must copy it exactly as shown.

Dakota does not charge for receiving a SWIFT deposit. Banks on the route can still deduct their fees before the wire reaches Dakota. The deposit is booked for the amount that arrives, so the transaction can be smaller than the amount the sender wired.

### SWIFT caveats

* **Bank fees reduce the amount received.** See the note at the top of this section. The deductions are not reported to Dakota and are not in the receipt.
* **`payment_reference` delivery is not guaranteed.** The reference is carried as the wire's remittance information; whether the payee sees it depends on the receiving bank and any intermediaries. Constraints: 5–140 characters across at most 4 lines of 35 characters; letters, digits, spaces, commas, and periods only.
* **`rail`, `capabilities`, and destination routing are immutable after account creation.** `PATCH /accounts/{account_id}` only updates the developer fee (`developer_fee_bps` or `developer_fee_fixed`); a request that changes a routing field returns `501`. To add SWIFT for an existing customer, create a new account with `rail: "swift"`.
* **Returns carry no NACHA code.** An international wire return may come back as a reduced amount after intermediary fees, without an `R`-code.

***

## One-off Swap (Single Cross-Chain Swap)

Use a one-off swap when the target network varies per swap (a reusable swap account pins `destination_network_id`) or you want to apply a different developer fee (`developer_fee_bps` or `developer_fee_fixed`) on this specific swap. `payment_reference` and `destination_payment_rail` are offramp-only and do not apply to swaps.

```mermaid theme={null}
sequenceDiagram
    participant App as Your App
    participant Source as Source chain
    participant Dakota
    participant Target as Target chain

    App->>Dakota: POST /transactions (transaction_type: one_off)
    Dakota-->>App: crypto_address (single-use)
    App->>Source: Send the amount you want swapped to crypto_address
    Source->>Dakota: Source stablecoin received
    Dakota->>App: Webhook: transaction.one_off.created
    Dakota->>Target: Deliver target stablecoin to destination
    Dakota->>App: Webhook: transaction.one_off.updated (completed)
```

### Create the One-off Swap

Prerequisite: a crypto Destination on the target network/asset already attached to a Recipient — see [Add a Crypto Destination](/documentation/common-flows#add-a-crypto-destination-for-onramps-and-swaps).

```bash theme={null}
curl -X POST https://api.platform.dakota.xyz/transactions \
  -H "X-API-Key: $DAKOTA_API_KEY" \
  -H "X-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_type": "one_off",
    "customer_id": "2LfTd6QQrUyPKwRR9qMMyk7CMHS",
    "amount": "500.00",
    "source_network_id": "ethereum-mainnet",
    "source_asset": "USDC",
    "destination_id": "2LfYm5KMnRvLFtRP7nJJug4zJEP",
    "destination_asset": "USDT",
    "destination_network_id": "polygon-mainnet",
    "developer_fee_bps": 25
  }'
```

**Response:**

```json theme={null}
{
  "id": "2LfZn6LNoSvMGuSQ0pLLswOffOn",
  "resource_type": "one_off",
  "status": "pending",
  "crypto_address": "0xabc...",
  "source_network_id": "ethereum-mainnet",
  "source_asset": "USDC",
  "destination_asset": "USDT",
  "destination_network_id": "polygon-mainnet"
}
```

Send the USDC you want swapped to `crypto_address`. You choose the amount — Dakota does not return a deposit quote to send against — and Dakota converts what arrives and delivers the destination asset on the target network. Same `transaction.one_off.*` webhooks as one-off offramp.

<Warning>
  **Send it in a single transfer.** As with one-off offramps, the address accepts exactly one deposit. Anything sent after the first is refused and held rather than returned, recoverable only through [Dakota support](https://support.dakota.xyz). Create another one-off transaction instead of topping up.
</Warning>

`amount` on the request is the destination amount you expect, and is optional. When omitted, Dakota still converts and delivers whatever you deposit. As with offramps, reconcile against `receipt.output` rather than the `destination_amount` on the event, which only echoes what you requested.

The `developer_fee_bps` above is deducted from your deposit before conversion — at 25 bps a 500.00 USDC deposit gives up 1.25 USDC, leaving 498.75 USDC to swap — so size the deposit accordingly if the destination must receive an exact amount. With `developer_fee_fixed` instead, send `amount` plus the fee. Dakota's own fee is billed separately rather than taken from the deposit.

<Warning>
  Sandbox object-create endpoints reject mainnet network IDs and cap per-request `amount` at \$2 USD. USDT is not yet supported in sandbox (coming soon); USD, USDC, and RD work today. See [Testing — Sandbox restrictions](/documentation/testing#sandbox-restrictions).
</Warning>

***

## One-off transaction lifecycle

Both one-off offramps and one-off swaps share the same `OneOffTransactionStatus` values and the same lifecycle rules. Inspect `status` on the transaction object or on each `transaction.one_off.updated` event to drive your own state machine.

| Status | Terminal | Meaning |
| - | - | - |
| `pending` | No | Created; waiting for the source deposit at `crypto_address`. |
| `processing` | No | Deposit received; Dakota is converting and delivering. |
| `pending_return` | No | For offramps: the receiving bank has initiated a return; the transfer may still settle. |
| `pending_reversal` | No | For offramps: an ACH reversal is in flight; the transfer may still complete. |
| `completed` | Yes | Funds delivered. `completed_at` is set. |
| `failed` | Yes | Terminal failure. Inspect `failure_reason` when present. |
| `cancelled` | Yes | Cancelled before delivery (see below). |
| `returned` | Yes | For offramps: the receiving bank returned the funds. Inspect `failure_code`, `return_code`, `return_reason` and `return_deadline`. |
| `reversed` | Yes | For offramps: the transfer was reversed after completion (an ACH reversal), or a returned payout was refunded to the source wallet. Inspect `failure_code`, `reversal_reason` and `net_recovered_amount`. |

`pending_return`, `returned`, `pending_reversal`, and `reversed` only apply to one-off offramps (the bank leg). They do not appear on one-off swaps, which are crypto-to-crypto. This mirrors the general [Transaction lifecycle](/api-reference/state-lifecycles#transaction-lifecycle) — one-offs surface `pending` as their initial status rather than `not_started`.

### Cancel a one-off transaction

Call `POST /transactions/{transaction_id}/cancellations` to cancel a one-off transaction that has not yet delivered. A successful cancellation returns `204 No Content` and the transaction moves to `cancelled`. Cancellation is only meaningful before Dakota starts settling the outbound leg — in practice, while the transaction is still in `pending` and no deposit has arrived at `crypto_address`.

The endpoint returns `400 Invalid request or transaction cannot be cancelled` when the target transaction is not in a cancellable state — for example, when it has already reached a terminal status (`completed`, `failed`, `cancelled`, `returned`, `reversed`) or is far enough along that the outbound leg can no longer be halted. The `detail` field on the problem response carries the specific reason. See [Errors](/api-reference/errors) for the response shape.

One-off requests do not accept a `return_address` (unlike reusable offramp accounts, which do). If a deposit lands on a `crypto_address` for a one-off that has already been cancelled, contact Dakota support with the transaction `id` to reconcile — the cancellation endpoint does not itself handle recovered funds.

### Failed, returned, and reversed one-offs

For terminal non-success statuses, the fields on the `OneOffTransaction` object are your source of truth:

* `failed` — read `failure_reason` for the cause.
* `returned` — switch on `failure_code`: the code mapped from the bank's return code when there is one, otherwise `payment_returned`. `return_code` (e.g. `R01`) is the bank's own code when it sent one, `return_reason` is Dakota's message, and `return_deadline` is the ACH return window.
* `reversed` — either an ACH originator reversal (`reversal_reason`, e.g. `duplicate`, `receiver_incorrect`, and `reversal_initiated_at`) or a returned payout that was refunded to the source wallet. A refunded return has `failure_code` set and no `reversal_reason` (except payouts returned before this behaviour shipped in October 2026, which may carry no `failure_code`).

#### Returned SWIFT payouts

An international (SWIFT) payout that the receiving bank returns moves to `returned`, and then to `reversed` once the returned funds are refunded to the source wallet. SWIFT returns are not refunded automatically, so the payout can stay at `returned` until Dakota makes the refund. There is no separate `refunded` status.

On both statuses the payout carries `failure_code` (the code mapped from the bank's return code, or `payment_returned` when there is none or it does not map) and `return_reason`. `reversal_reason` stays empty. Payouts returned before this behaviour shipped (October 2026) may carry no `failure_code`.

The bank or an intermediary can deduct a fee from the returned funds, and the customer bears that deduction. `net_recovered_amount` is set when the refund is made, and only when the return came back short: it is the face amount less the deduction, in the same units as `send_amount`. On `returned` it is absent whatever came back, so its absence there says nothing about the amount. On a `reversed` payout that was a bank return, its absence means nothing was withheld.

**In sandbox**, a returned SWIFT payout can end in one of two ways, depending on which bank leg carried it. Some are refunded automatically, without operator action: the payout moves to `returned` and then to `reversed`, with `failure_code: payment_returned`. Others stay at `returned` and are not refunded automatically, the same as in production, where Dakota operations resolve them. A SWIFT payout in a currency other than USD always stays at `returned`. For a USD SWIFT payout, the outcome is not something you can choose or predict from the request, so do not assume either one: act on the `status` and the `transaction.one_off.updated` or `transaction.auto.updated` webhook you receive, and do not wait for `reversed` on a payout that has settled at `returned`.

`failure_code` is not a status. Use `status` for the outcome; a payout that completes after a return (for example a resent wire) has no `failure_code` and no return fields.

Unlike a reusable offramp account, a one-off transaction has no `return_address` on the create request. If a one-off ends in `returned` or `reversed` and you need to reconcile the recovered value, contact Dakota support with the transaction `id`.

***

## Developer Fees

A developer fee is your cut of each deposit to an account or one-off transaction. Dakota takes it from the deposit before conversion. Dakota's own fee is billed separately on your invoice and is not taken out of the deposit.

A fee is **either** a percentage **or** a fixed amount:

| Field | Type | Charged on each deposit |
| - | - | - |
| `developer_fee_bps` | integer, `0`–`10000` | `amount × developer_fee_bps / 10000` (1 bp = 0.01%) |
| `developer_fee_fixed` | decimal string, such as `"10.00"` | exactly `developer_fee_fixed`, whatever the deposit size |

* **Send one or the other.** A request that sends both is a `400`, even when one of them is `0`.
* **Setting one on update replaces the other.** `PATCH /accounts/{account_id}` with `developer_fee_fixed` switches a percentage account to a fixed fee, and `developer_fee_bps` switches it back. A `PATCH` that sends neither leaves the fee as it is.
* **Changes apply to future deposits only.** Transactions already created keep the fee they were created with.
* **Omit both to charge no fee.** To remove a fixed fee from an account, set `developer_fee_bps` to `0`.

Set the fee when you create an account (`POST /accounts`) or a one-off transaction (`POST /transactions`), and change it on an account with `PATCH /accounts/{account_id}`. A one-off's fee can't be changed after creation.

### Fixed fees are charged in the deposited asset

`developer_fee_fixed` has no currency of its own. It is charged **in units of the asset deposited to the account**, and it is never converted between currencies:

* It must be greater than `0` and have at most 2 decimal places. `"10"`, `"10.5"` and `"10.00"` are all valid.
* There is no upper limit.
* The same value means a different amount on accounts that receive different assets. `"10.00"` is 10 USDC on a USDC deposit, 10 USD on a USD bank deposit and 10 EUR on a EUR bank deposit.

| Account | `developer_fee_fixed` | Deposit | Fee charged | Converted |
| - | - | - | - | - |
| Offramp or swap receiving USDC | `"10.00"` | 250.00 USDC | 10.00 USDC | 240.00 USDC |
| Onramp receiving USD by ACH | `"10.00"` | 100.00 USD | 10.00 USD | 90.00 USD |
| Onramp receiving EUR by SWIFT | `"10.00"` | 500.00 EUR | **10.00 EUR** | 490.00 EUR |

For example, this offramp account charges 10.00 USDC on every USDC deposit:

```bash theme={null}
curl -X POST https://api.platform.dakota.xyz/accounts \
  -H "X-API-Key: $DAKOTA_API_KEY" \
  -H "X-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "account_type": "offramp",
    "fiat_destination_id": "2LfYm5KMnRvLFtRP7nJJug4zBAN",
    "source_asset": "USDC",
    "source_network_id": "ethereum-mainnet",
    "destination_asset": "USD",
    "rail": "ach",
    "developer_fee_fixed": "10.00"
  }'
```

The response returns the fee and the smallest deposit the account will convert:

```json theme={null}
{
  "id": "2LfZn6LNoSvMGuSQ0pLLxj6BLGR",
  "account_type": "offramp",
  "source_crypto_address": "0x1234567890abcdef1234567890abcdef12345678",
  "source_network_id": "ethereum-mainnet",
  "source_asset": "USDC",
  "destination_asset": "USD",
  "rail": "ach",
  "developer_fee_bps": 0,
  "developer_fee_fixed": "10.00",
  "minimum_deposit": "10.01"
}
```

`GET /accounts/{account_id}` returns the same fields. `developer_fee_bps` is `0` on a fixed-fee account. `developer_fee_fixed` and `minimum_deposit` are absent on an account that charges a percentage or no fee.

### Minimum deposit

A fixed-fee account only converts a deposit that leaves something after the fee. `minimum_deposit` is `developer_fee_fixed` + 0.01, in units of the deposited asset. On the account above it is `"10.01"`, so a 10.01 USDC deposit converts 0.01 USDC.

<Warning>
  **A deposit smaller than `minimum_deposit` is not converted, and it is not returned automatically.** No transaction is created for it. Dakota sends a [`deposit.held`](/documentation/webhooks#deposit-events) webhook instead. To recover it, contact [Dakota support](https://support.dakota.xyz) with the account `id` and the deposit details.
</Warning>

### Crypto deposits must be USD-pegged stablecoins

On a fixed-fee account, a crypto deposit must be a USD-pegged stablecoin, such as USDC or USDT. If a fixed-fee account receives any other crypto asset, Dakota doesn't charge the fee: it holds the deposit for review, and nothing is converted until the review is done. Percentage fees have no such restriction.

### Fixed fees on one-off transactions

On a one-off transaction, `amount` is the destination amount you expect, not the amount to deposit. The fixed fee is taken from whatever is deposited, so **the depositor sends the destination amount plus the fee**. Dakota doesn't check `amount` against the fee when you create the one-off, for any pair of assets. A small payout with a larger fee is accepted.

For example, a USDC → USD one-off offramp with `amount` 5.00 and `developer_fee_fixed` 10.00:

```bash theme={null}
curl -X POST https://api.platform.dakota.xyz/transactions \
  -H "X-API-Key: $DAKOTA_API_KEY" \
  -H "X-Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_type": "one_off",
    "customer_id": "2LfTd6QQrUyPKwRR9qMMyk7CMHS",
    "amount": "5.00",
    "source_network_id": "ethereum-mainnet",
    "source_asset": "USDC",
    "destination_id": "2LfYm5KMnRvLFtRP7nJJug4zBAN",
    "destination_asset": "USD",
    "developer_fee_fixed": "10.00"
  }'
```

Send 15.00 USDC to the returned `crypto_address`. Dakota takes 10.00 USDC as your fee and delivers 5.00 USD. The one-off returns `developer_fee_fixed` when you read it, but not `minimum_deposit`. A deposit that doesn't cover the fee plus 0.01 is not converted; contact [Dakota support](https://support.dakota.xyz) to recover it.

### Where fixed fees are available

A fixed fee isn't available on every account. When an account or one-off can't charge one, `developer_fee_fixed` is refused with a `400`:

```json theme={null}
{
  "type": "https://docs.dakota.xyz/api-reference/errors#invalid-request",
  "title": "Invalid Request",
  "status": 400,
  "detail": "developer_fee_fixed is not supported for this account; use developer_fee_bps."
}
```

Use `developer_fee_bps` on that account instead. The same error is returned when you `PATCH` an account that can't charge a fixed fee.

Agentic payments also take `developer_fee_bps` or `developer_fee_fixed`, in `developer_fee_defaults` or on a `create_auto_account` action, and the same restriction applies to them. By default a payment's `amount` is what the payee receives, so either kind of fee is added on top. See [the conversion fee](/documentation/agentic-payments/client-policy#the-conversion-fee-and-which-side-of-it-your-amount-is-on).

### The fee charged

The fee actually taken from each deposit appears as `developer_fee` in the transaction's `receipt`, in the deposited asset. `client_fee` is its deprecated alias, with the same value. On the EUR onramp above, `GET /transactions/{transaction_id}` returns:

```json theme={null}
{
  "receipt": {
    "input": { "amount": "500.00", "asset": "EUR" },
    "output": { "amount": "529.20", "asset": "USDC" },
    "exchange_rate": "1.08",
    "developer_fee": { "amount": "10.00", "asset": "EUR" },
    "client_fee": { "amount": "10.00", "asset": "EUR" }
  }
}
```

The fee is charged in EUR and the 490.00 EUR left is converted; the exchange rate here is illustrative. On `transaction.*` webhooks, each fee is a flat decimal string instead of an object; see [Fee fields in the receipt](/documentation/webhooks#fee-fields-in-the-receipt).

### Fee payouts

Developer fees charged in EUR are held and not paid out automatically. To arrange a payout of EUR fees, contact [Dakota support](https://support.dakota.xyz).

### Set the fee in the dashboard

You can also set the developer fee when you create an onramp, offramp, swap or one-off transaction in the Dakota dashboard. The create form has a **Developer fee** selector with three options:

| Option | What you enter | Sent as |
| - | - | - |
| **None** (default) | Nothing | No developer fee |
| **Percentage** | **Fee percentage**, such as `0.5` for 0.5%. At most 2 decimal places and at most 100%. | `developer_fee_bps` (`0.5` becomes `50`) |
| **Fixed amount** | **Fixed fee amount**, such as `10.00`. At most 2 decimal places, greater than 0. The deposited asset is shown next to the field once you've picked it. | `developer_fee_fixed` |

The form sends only the option you picked, never both fields. The fixed amount is charged in units of the deposited asset, as described above. If the account can't charge a fixed fee, creation fails with the `developer_fee_fixed is not supported for this account` error; choose **Percentage** instead.

The detail drawer of an onramp, offramp or swap account shows a **Developer Fee** row: the percentage with its basis points (for example `0.5% (50 bps)`), the fixed amount with its asset (for example `10.00 USDC`), or `None`. Fixed-fee accounts also show a **Minimum Deposit** row, such as `10.01 USDC`. A one-off offramp's drawer shows the **Developer Fee** row only when a fee was set.

To change the fee on an existing account, use `PATCH /accounts/{account_id}`.

### Developer fee errors

Each error is a `400` [`invalid-request`](/api-reference/errors#invalid-request) problem. The `detail` is one of these messages, where the quoted value is the one you sent:

| Case | `detail` |
| - | - |
| Both fields sent | `Set either developer_fee_bps or developer_fee_fixed, not both.` |
| `developer_fee_fixed` isn't a decimal string | `developer_fee_fixed must be a decimal string such as "10.00"; got "ten".` |
| `developer_fee_fixed` is 0 or negative | `developer_fee_fixed must be greater than 0; got "0". To charge no fee, set developer_fee_bps to 0.` |
| More than 2 decimal places | `developer_fee_fixed allows at most 2 decimal places; got "10.001".` |
| The account can't charge a fixed fee | `developer_fee_fixed is not supported for this account; use developer_fee_bps.` |

`developer_fee_fixed` is checked in the order listed. Exponent notation (`"1e1"`), a leading `+`, a trailing or leading `.`, and surrounding spaces all get the decimal-string error. `developer_fee_bps` keeps its existing validation (an integer from `0` to `10000`).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.