Skip to main content
Pay out to a bank account in Europe or in the United States with four API calls. You fund a balance in USDC, your verified customer saves the bank account of a beneficiary, and each payout is sent by SEPA Instant in EUR or by ACH in USD. You get a firm quote before anything is debited, and a webhook at every step.

EUR, SEPA Instant

Transfers in EUR to bank accounts in 45 countries, including countries outside the EU. Funds usually arrive within minutes.

USD, ACH (United States)

Transfers in USD to checking and savings accounts in the United States, with no currency conversion. Paid from your Ops Others balance.

Quote before you pay

Each quote gives the amount received, the fee and the total debited. Nothing is debited until you confirm. A failed transfer is refunded automatically.
The endpoints, the fees, the statuses and the webhooks are the same for both. This page first describes the SEPA flow, then what changes for ACH payouts to the United States.

How it works

1

List the countries

GET /payouts/countries returns the countries you can pay to (SEPA countries and the United States) and the regions or states of each country.
2

Save a beneficiary

POST /payouts/beneficiaries saves the bank account of a beneficiary for a verified customer.
3

Request a quote

POST /payouts/quotes prices the payout. Nothing is debited.
4

Confirm with your reference

POST /payouts debits your balance (Payout SEPA for SEPA, Ops Others for ACH) and sends the payout. It returns 202 with status pending.
5

Follow the webhooks

payout.processing when the payout is sent to the bank, then payout.completed, or payout.failed followed by payout.refunded.

Prerequisites

A verified customer

Only a customer with verification_level verified or full (identity verification approved) and status active can have beneficiaries and send payouts. Otherwise the call returns 422 VALIDATION_ERROR:
See KYC levels and the KYC flow to verify a customer.

A funded Payout SEPA balance

Payouts are paid in USD from a dedicated ops balance: Ops Payout SEPA (balance_type payout_sepa). It is funded with USDC like your other ops balances:
  1. In your partner dashboard, open the Ops balance section and request the deposit address of the Payout SEPA balance.
  2. Send USDC to this address. The balance is credited once the deposit is confirmed, minus the deposit fee of your plan.
Each SEPA payout debits the amount plus the fee from this balance. ACH payouts to the United States are paid from your Ops Others balance instead: see Funding from Ops Others.

Your plan

Payouts (SEPA and ACH) are available on every plan, including Découverte. On Découverte, payouts are limited to 5,000 USD per calendar month, all customers combined, SEPA and ACH together. See Fees and limits.

Step 1: List the countries

Every entry has a rail: sepa for a SEPA country, us for the United States. The country of a SEPA beneficiary must be one of the sepa countries, and its state_province one of the value fields listed for that country. For the United States, regions lists the 57 accepted states and territories (for example new_york or district_of_columbia). Any other value is refused.

Step 2: Save a beneficiary

Response 201:
  • The full IBAN is never returned: responses only show iban_masked.
  • A customer can have up to 50 active beneficiaries. The same IBAN cannot be saved twice for a customer.
  • Invalid fields are returned in details.fields, one message per field:
Manage beneficiaries with GET /payouts/beneficiaries?customer_code=…, GET /payouts/beneficiaries/{code} and DELETE /payouts/beneficiaries/{code}. To change the bank details of a beneficiary, delete it and save it again.

Step 3: Request a quote

amount_usd is the amount of the payout in USD, from 25 to 2,499, with at most 2 decimals. The fee is added on top. Response 201 (example on the Starter plan, fee $5 + 2%):
Nothing is debited when a quote is created. A quote that is not confirmed simply expires.
The quote already runs the checks of the payout: verified and active customer, Découverte monthly limit, and a balance (Payout SEPA, or Ops Others for ACH) that covers total_debited_usd. They are run again at confirmation.

Step 4: Confirm with your reference

total_debited_usd is debited from your Payout SEPA balance (Ops Others for ACH) and the payout is created with status pending. Response 202:
The code of the payout is the quote_code. The payout is then sent to the bank asynchronously: follow it with the webhooks below, or with GET /payouts/{code} and GET /payouts?status=…&customer_code=…. If the quote has expired by the time the payout is sent to the bank, KemyCard requests a new quote automatically. If the amount received would be more than 1% lower than the quote you accepted, the payout is cancelled and refunded instead.

Idempotency with reference

reference is required and unique per partner account: 1 to 100 characters among letters, digits and - _ . : /. Use your own ID, for example your order or withdrawal ID. If a call times out or your server restarts, send the same request again: you never pay twice.

Step 5: Follow the webhooks

The data of each event is the payout object, the same as GET /payouts/{code}, with its rail, received_amount and received_currency. When you confirm a payout, you also receive balance.debited with reason payout_sepa, payout_code and reference, for SEPA and ACH payouts alike: balance_type tells you which balance was debited (payout_sepa or others). With SEPA Instant, funds usually arrive within minutes. An ACH transfer can take a few business days to arrive. Subscribe to these events when you register your webhook endpoint, or use "*".

Payout statuses

A failed payout is always refunded automatically: you do not need to do anything. To send it again, request a new quote.

ACH payouts to the United States

Send USD by ACH to a checking or savings account in the United States. The beneficiary receives USD: there is no currency conversion. You use the same endpoints and the same flow as for SEPA (beneficiary, quote, confirmation with your reference, webhooks). This section describes what changes.
RTP (Real-Time Payments) is not available. Payouts to the United States are sent by ACH only.

Prerequisites

  • A verified customer, exactly as for SEPA: verification_level verified or full and status active. See A verified customer.
  • A funded Ops Others balance: ACH payouts are paid from your Ops Others balance (others), not from your Payout SEPA balance. See Funding from Ops Others.
  • Your plan: ACH payouts are available on every plan, including Découverte, with the same fees as SEPA payouts.

Funding from Ops Others

Each ACH payout debits the amount plus the fee from your Ops Others balance (balance_type others), the balance that also pays wallets, virtual accounts, KYC and plan payments. Your Payout SEPA balance is never used for ACH payouts, and the Ops Others balance is never used for SEPA payouts. The Ops Others balance is funded with USDC like your other ops balances. On this balance:
  • the debit of an ACH payout is recorded with the nature PAYOUT;
  • the refund of a failed ACH payout (amount + fee) is credited back with the nature REFUND.
When you confirm an ACH payout, you receive balance.debited with reason payout_sepa (the same reason as for SEPA payouts), balance_type others, payout_code and reference. If the Ops Others balance does not cover total_debited_usd, the quote or the confirmation returns 400 INSUFFICIENT_BALANCE:

Save a US beneficiary

Send "rail": "us" to POST /payouts/beneficiaries:
The address of the account holder (street, city, state_province, postal_code) must be in the United States. country is not sent: it is always US. Response 201:
  • The full account number is never returned: responses only show account_number_masked (last 4 digits).
  • The same bank account (same routing_number and account_number) cannot be saved twice for a customer: the call returns 422 VALIDATION_ERROR with details.field = account_number.
  • US beneficiaries count in the limit of 50 active beneficiaries per customer.
  • Invalid fields are returned in details.fields, one message per field:

Quote and send an ACH payout

Request a quote with the beneficiary_code of the US beneficiary. amount_usd is from 100 to 2,499 USD, with at most 2 decimals:
Response 201 (example on the Starter plan, fee $5 + 2%):
  • rail is ach. received_amount is the amount in USD the beneficiary will receive. amount_eur and exchange_rate are always null for ACH.
  • balance_type is others: total_debited_usd will be debited from your Ops Others balance when you confirm.
  • Confirm before expires_at, otherwise request a new quote.
Confirm with POST /payouts and your reference, exactly as for SEPA (see Step 4). Response 202:
The idempotency rules of reference, the statuses and the payout.* webhooks are the same as for SEPA. If an ACH payout fails, total_debited_usd is credited back to your Ops Others balance and failure_reason says so.

Timing

An ACH transfer can take a few business days to arrive on the beneficiary’s account. The payout moves to processing when it is sent to the bank, then to completed once the funds have arrived: rely on the payout.completed webhook (or GET /payouts/{code}) rather than on a fixed delay.

Fees and limits

Fee per payout

The fee is the same for SEPA and ACH payouts. It is charged on top of the amount and debited with it, from your Payout SEPA balance (SEPA) or your Ops Others balance (ACH).

Deposit on the Payout SEPA balance

Deposits on the Ops Others balance, which pays ACH payouts, carry the deposit fee of that balance: see Ops balance deposits.

Limits

When the Découverte limit would be exceeded, the quote or the confirmation returns 403 PLAN_LIMIT_REACHED:

Test mode

With a sk_test_ key, every payout endpoint validates your request (required fields, beneficiary fields including the US fields, format of amount_usd and reference) and returns simulated data. A US beneficiary created in test mode is returned with its US fields, but quotes and payouts in test mode are always simulated SEPA payouts (rail sepa, EUR). Nothing is stored, nothing is debited, nothing is sent to a bank and no webhook is sent. GET /payouts/countries returns the real list of countries. See Test mode.

Error handling

For an ACH payout, the message is Insufficient Ops Others balance. and details.balance_type is others. See Error Handling for the general error format.

Questions

For any question about payouts, contact us at [email protected].