Transfers

Transfer to another of your accounts, or to another business

POST/transfers

destination is one of:

  • own_account + accountId — another of your own accounts (acc_… from GET /accounts), in the same currency. Free of charge. A sub-merchant's account is not your own. The source itself is 400 destination_is_source; an account that is not yours is 404 not_found; another currency is 400 currency_mismatch.
  • business + exactly one of email (the business owner's) or merchantNumber (its ten-digit number, as GET /me reports it). The money lands in that business's primary account in the currency. The transfer fee is charged on top and reported in fee. Whatever the reason a business does not resolve — no such business, it cannot receive, no account in the currency, an owner e-mail shared by several businesses — the answer is one: 400 destination_not_found, so the endpoint cannot be used to learn who banks here. Its detail is one text for every reason, and points at POST /payouts — an individual is paid with a payout. Your own business is 400 destination_is_self. An API key whose destinations keep failing to resolve is refused with 429 destination_lookup_limited for the rest of the window. A merchantNumber carries a check digit; a mistyped one is 400 validation_failed without a lookup.

sourceAccountId may be left out: your default account in the currency (isDefault: true on GET /accounts) is debited — or the only one, when you hold just one. None is 400 no_account_for_currency.

Always 202. Most transfers settle inside the request and read completed; one that has not settled yet reads pending — poll Location. The transfer is the ledger's own entry: its id is the txn_… id GET /accounts/{accountId}/transactions shows for the debit. There is no step-up and no approval step for API transfers; the signed key is the authentication.

A refusal (insufficient_funds, limit_exceeded, …) is a 400 with its own code. It does not use up the merchantReference: once refused, the reference may be sent again with a new Idempotency-Key. A refusal made after the transfer was recorded leaves a failed entry in the ledger under the reference; at most one transfer under a reference is ever not failed. A 500 is never a refusal: retry with the same Idempotency-Key and you get the transfer as it stands, never a second one — or look the reference up with GET /transfers?merchantReference=, which finds the transfer if it was made. A request left unanswered and not retried for 15 minutes is settled by the platform: answered with the transfer if one was made, otherwise refused with 400 request_not_executed — nothing moved, its merchantReference is free again, and a retry under the same key gets that answer, so send it again under a new one. The same Idempotency-Key with a different request is 400 idempotency_key_reused, however long after. Requires transfers:write.

Authentication
ApiKeyAuth
Execution
asynchronous

Parameters

  • Idempotency-Keystringheaderrequired
    Client-generated unique key for this logical request (UUID recommended). See Idempotency.

    min length 1 · max length 255

  • X-Request-Idstringheader
    Optional client correlation id; echoed back unchanged.

    max length 128

Request body application/jsonrequired

  • merchantReferencestringrequired
    Your own unique reference for this transfer; reusing it under a new Idempotency-Key is 400 duplicate_merchant_reference.

    min length 1 · max length 100

  • amountobjectrequired
    What the destination is credited. A fiat currency; no more decimals than it has.
    • valuestringrequired

      Example: 149.90

      pattern ^-?\d{1,18}(\.\d{1,18})?$

    • currencystringrequired
      ISO 4217 code for fiat (EUR), asset ticker for crypto (USDT).

      Example: EUR

      pattern ^[A-Z0-9]{3,10}$

  • destinationTransferDestinationrequired
    own_account with accountId, or business with exactly one of email and merchantNumber. On the resource: the type, and for own_account the accountId. A business's e-mail or number is not kept, and its account is never shown; counterpartyName on the ledger entry says who received it.
    • typestringrequired

      Allowed values: own_accountbusiness

    • accountIdstring
      Opaque account identifier. Treat as a string; never parse or construct it.

      Example: acc_AAAAAAAAAAc

      pattern ^acc_[A-Za-z0-9_-]{11}$

    • emailstring (email)
      The receiving business's owner e-mail.

      max length 254

    • merchantNumberstring
      The receiving business's merchant number (GET /me → merchantNumber).

      pattern ^[0-9]{10}$

  • sourceAccountIdstring
    Optional. Left out, your default account in the currency (isDefault) — or the only one.

    Example: acc_AAAAAAAAAAc

    pattern ^acc_[A-Za-z0-9_-]{11}$

  • descriptionstring

    max length 140

Responses

Transfer accepted. The code is always 202 — read status: completed or failed is final; pending means it has not settled yet, so poll Location — Retry-After is sent only then. An idempotent replay returns this original body.

Headers

  • Locationstring (uri-reference)
    The resource URL to poll for the current state (RFC 9110 §15.3.3 status monitor).
  • Retry-Afterinteger
    Seconds to wait before polling Location. On a 202 it is present only while the body's status is not yet terminal — its absence is a second signal that the work is already done.
  • X-Request-Idstring
    The client's X-Request-Id if supplied, otherwise a server-generated id. Equals traceId in problems.
  • Idempotent-Replayedboolean
    true when this response was replayed from an earlier request with the same Idempotency-Key.
  • RateLimit-Limitinteger
  • RateLimit-Remaininginteger
  • RateLimit-Resetinteger
    Seconds until the window resets.

Schema application/json

  • objectstringrequired

    Allowed values: transfer

  • idstringrequired
    The ledger id of the transfer's debit — the same entry GET /accounts/{accountId}/transactions shows.

    Example: txn_AAAAAAAAB3Y

    pattern ^txn_[A-Za-z0-9_-]{11}$

  • merchantReferencestring
    Absent on a transfer made in the portal.
  • statusstringrequired
    pending accepted, not settled yet · completed settled · failed refused, rejected or expired — no money moved.

    Allowed values: pendingcompletedfailed

  • amountMoneyrequired
    Decimal amount as a string — never a float, never minor units. An amount you send may carry no more decimal places than its currency has (and never more than 8); trailing zeros do not count, so 10.100 EUR is fine and 10.123 EUR is 400 validation_failed on amount.value.
    • valuestringrequired

      Example: 149.90

      pattern ^-?\d{1,18}(\.\d{1,18})?$

    • currencystringrequired
      ISO 4217 code for fiat (EUR), asset ticker for crypto (USDT).

      Example: EUR

      pattern ^[A-Z0-9]{3,10}$

  • feeobjectrequired
    Charged on top of amount; zero between your own accounts.
    • valuestringrequired

      Example: 149.90

      pattern ^-?\d{1,18}(\.\d{1,18})?$

    • currencystringrequired
      ISO 4217 code for fiat (EUR), asset ticker for crypto (USDT).

      Example: EUR

      pattern ^[A-Z0-9]{3,10}$

  • totalDebitedobjectrequired
    What leaves the source account: amount + fee.
    • valuestringrequired

      Example: 149.90

      pattern ^-?\d{1,18}(\.\d{1,18})?$

    • currencystringrequired
      ISO 4217 code for fiat (EUR), asset ticker for crypto (USDT).

      Example: EUR

      pattern ^[A-Z0-9]{3,10}$

  • sourceAccountIdstringrequired
    Opaque account identifier. Treat as a string; never parse or construct it.

    Example: acc_AAAAAAAAAAc

    pattern ^acc_[A-Za-z0-9_-]{11}$

  • destinationTransferDestinationrequired
    own_account with accountId, or business with exactly one of email and merchantNumber. On the resource: the type, and for own_account the accountId. A business's e-mail or number is not kept, and its account is never shown; counterpartyName on the ledger entry says who received it.
    • typestringrequired

      Allowed values: own_accountbusiness

    • accountIdstring
      Opaque account identifier. Treat as a string; never parse or construct it.

      Example: acc_AAAAAAAAAAc

      pattern ^acc_[A-Za-z0-9_-]{11}$

    • emailstring (email)
      The receiving business's owner e-mail.

      max length 254

    • merchantNumberstring
      The receiving business's merchant number (GET /me → merchantNumber).

      pattern ^[0-9]{10}$

  • descriptionstring
  • failureobject
    Present when status is failed.
    • codestringrequired
      The code the refusal was answered with.
    • messagestringrequired
  • createdAtstring (date-time)required
    RFC 3339, UTC, with millisecond precision.

    Example: 2026-09-18T10:15:30.123Z

  • updatedAtstring (date-time)required
    RFC 3339, UTC, with millisecond precision.

    Example: 2026-09-18T10:15:30.123Z

  • completedAtstring (date-time)
    RFC 3339, UTC, with millisecond precision.

    Example: 2026-09-18T10:15:30.123Z