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, 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 — per-transaction developer fee override. The API does not return developer_fee_bps on account or transaction reads, so record the value you set. The fee actually charged appears as client_fee in each transaction’s receipt.

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. In each transaction’s receipt, client_fee is the developer fee that was deducted 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)

SWIFT is Dakota’s international USD wire rail. Use it to pay recipients whose bank accounts are outside the US domestic rails (ACH, Fedwire, FedNow). SWIFT is USD only, settles 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.

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, commas, and periods only.
  • rail and capabilities are immutable after account creation. PUT /accounts/{account_id} only updates destination routing and developer_fee_bps. 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_bps 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. 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 — read return_code (e.g. R01) and return_reason for the bank’s reason, return_deadline for the return window, and net_recovered_amount when the return settled short.
  • reversed — read reversal_reason (Lead Bank ACH reversal code, e.g. duplicate, receiver_incorrect) and reversal_initiated_at.
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.