Send money abroad by international wire
Pay a recipient abroad from your US dollar account by SWIFT wire. For a payment in another currency you get a firm exchange rate first, and the recipient amount is fixed before you confirm.
International wires work with test money today. Live payments aren't switched on yet, and the bank sets how long a wire takes: there's no same-day guarantee.
The three calls
- Save the recipient once:
POST /api/treasury/counterpartieswithkind: "international". Needs the scopewrite:counterparties. - Get a firm rate (not needed for US dollar wires):
POST /api/treasury/fx-quotes. Needswrite:payouts. - Send:
POST /api/treasury/payoutswithrail: "intl_wire". Needswrite:payoutsand anIdempotency-Key.
const headers = {
Authorization: `Bearer ${process.env.SOREN_API_KEY}`,
"Content-Type": "application/json",
};
// 1. Save the recipient (IBAN or the country's local account number)
const counterparty = await fetch("https://sorenpay.com/api/treasury/counterparties", {
method: "POST",
headers: { ...headers, "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({
kind: "international",
name: "Acme GmbH",
bic: "COBADEFFXXX",
accountNumber: "DE89370400440532013000",
holderType: "business",
address: { line1: "Hauptstrasse 1", city: "Berlin", countryCode: "DE" },
currency: "EUR",
}),
}).then((r) => r.json());
// 2. Firm rate for exactly EUR 1,000.00 arriving (before bank deductions)
const quote = await fetch("https://sorenpay.com/api/treasury/fx-quotes", {
method: "POST",
headers: { ...headers, "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({
counterpartyId: counterparty.id,
buyCurrency: "EUR",
buyAmountMinor: 100000,
}),
}).then((r) => r.json());
// 3. Send before the quote's lock expires
const payout = await fetch("https://sorenpay.com/api/treasury/payouts", {
method: "POST",
headers: { ...headers, "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({
rail: "intl_wire",
counterpartyId: counterparty.id,
instructedCurrency: "EUR",
instructedAmountMinor: 100000,
quoteId: quote.id,
description: "Invoice 2026-114",
}),
}).then((r) => r.json());Each call returns the saved object (recipient, quote or payout) with its id.
The full field list is in the OpenAPI spec at
/api/v1/openapi.json.
After you send
- Status:
GET /api/treasury/payouts/{id}. - Tracking:
GET /api/treasury/payouts/{id}/trackingreturns the SWIFT tracking the bank reports. - Held US dollar wires can be released or cancelled with
POST /api/treasury/payouts/{id}/releaseand/cancel. - Recall (
/recall) isn't available yet.
A payout's amount is reserved from your balance when you send it. If the bank never confirms it, the reservation is released after 24 hours. Nothing is sent twice: a payout is submitted to the bank once and never retried.
Coming soon
- Local payouts in many currencies through our FX partners: pay a bank abroad
in the recipient's currency (
/api/payments/internationalanswers422 capability_unavailableuntil then). - Paying from a currency balance. See Multi-currency.
Every recipient you save is screened against sanctions lists first. See Compliance.