Skip to main content
This page covers flows that branch off the core walkthrough in 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 (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, and / - ? : ( ) . , ' + only (the SWIFT character set, so hyphens are allowed). 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.

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.
Response:
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.
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. 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.
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. 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. 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.
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.

SWIFT Payouts (International Wire)

See Foreign exchange (FX) for currencies, availability checks and quote examples. 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 to see which currencies are available and POST /fx/quotes to price one. Fixed (rate-locked) quotes are available on request and are not generally available yet. In sandbox, FX access is enabled for every client (see FX Access). 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.
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.

Currency availability

Check the Customer’s available currencies before requesting a quote. See Check available currencies for the request, response and quote-mode fields.

Availability by jurisdiction

SWIFT, and FX on SWIFT, is not available everywhere. Whether a customer can use it depends on where the customer is based and where your organization (the client the customer belongs to) is based. Dakota does not publish the list of affected jurisdictions, and a refusal does not say which jurisdiction caused it. Check before you build the flow: call GET /customers/{customer_id}/fx-currencies?direction=outgoing for the customer (direction=incoming for SWIFT deposits).
  • 200: the customer passed the jurisdiction check for this request. The list reports current foreign-currency availability for the requested direction and omits currencies not offered where they are based. An empty currencies array means no foreign currency is currently reported; it does not guarantee that USD SWIFT is configured or available. A 200 does not mean the customer’s SWIFT setup is complete: check their international_wire capability with GET /customers/{customer_id}/capabilities. Quote and payment checks still apply.
  • 403 with type capability-unavailable: SWIFT is not available to the customer. Creating a SWIFT account or one-off payout, or requesting an FX quote, returns the same error.
A 503 with type eligibility-unavailable usually means Dakota could not check availability at that moment; retry with exponential backoff. On the FX quote endpoints the same type is also used when quotes cannot be served for the account, for example "detail": "The account is not provisioned for FX quotes.". Retrying does not fix that; contact Dakota support if it persists. This check covers where the customer and your organization are based, not where the money is going. Each payout is still screened when it is sent, and screening can refuse a payout to a particular beneficiary.

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.
  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.
  3. Create the offramp Account pointing at that destination:
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 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, and / - ? : ( ) . , ' + only (the SWIFT character set, so hyphens are allowed).
  • 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.

Create the One-off Swap

Prerequisite: a crypto Destination on the target network/asset already attached to a Recipient — see Add a Crypto Destination.
Response:
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.
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. Create another one-off transaction instead of topping up.
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.
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.

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. 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 — 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 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:
  • 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.
For example, this offramp account charges 10.00 USDC on every USDC deposit:
The response returns the fee and the smallest deposit the account will convert:
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.
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 webhook instead. To recover it, contact Dakota support with the account id and the deposit details.

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:
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 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:
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.

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:
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.

Fee payouts

Developer fees charged in EUR are held and not paid out automatically. To arrange a payout of EUR fees, contact Dakota support.

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: 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 problem. The detail is one of these messages, where the quoted value is the one you sent: 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).