International transfers
Pay banks abroad by SWIFT, SEPA or Faster Payments, and local bank accounts and mobile wallets in their own currency.
An international transfer pays someone outside the US bank rails. There are two kinds:
- Bank rails abroad. You choose the rail: SWIFT (the recipient receives USD), SEPA (EUR) or UK Faster Payments (GBP).
- Local payouts. You leave
railout, and Gravv pays the recipient's bank account or mobile wallet in its local currency, such as naira in Nigeria or shillings on a Kenyan mobile wallet.
Example. A software company's wallet-backed USD account sends 1,000.00 USD to a designer's IBAN in Germany by SEPA. At an illustrative rate of 0.885 EUR per USD, the response shows local_amount 885 and local_currency EUR, which is what the designer is due. Gravv debits the account 1,000.00 USD plus the fee.
Payments and supported countries lists the countries and rails that are open today. The supported-countries endpoints list the countries the API knows, but they do not tell you whether a route is open. If a route is not open, the API refuses the transfer when you send it, for example with transfers to MX/MXN are not available at this time, and debits nothing.
SWIFT (USD)
| Destination | From a bank-held USD account | From a wallet-backed account |
|---|---|---|
| Nigeria (NG) | Available | Not yet available |
| Any other country | Not yet available. Ask support to open the corridor before you build on it | Not yet available |
| Any currency other than USD | Not supported | Not supported |
- Save a
swiftpayee with the recipient's legal name,account_number(needed even when you also sendiban),bic,account_owner_type, the recipient'saddressand the bank's address. If you send an intermediary bank block, fill in all of its fields or leave the block out. See Add an external account. - Find the bank and its address with
GET /v1/external-accounts/institutions?swift_code=<BIC>. The response'sprefillholds the bank fields to copy into the payee. - Send
"rail": "swift"insidedestination.wireis a US domestic wire, and the API refuses it for a SWIFT payee. - Write the purpose of payment in
description. Gravv sends it to the bank. - The bank may ask for a supporting document such as an invoice. Attach it when you send, with
supporting_document_ids. Otherwise the transfer can pause. See Paused transfers. - The minimum is 1 USD. Banks along the route may take their own charges from the amount you send.
SEPA (EUR) and Faster Payments (GBP)
| Rail | Destination | From a wallet-backed account | From a bank-held USD account |
|---|---|---|---|
sepa |
AD AT BE CY CZ DE DK EE ES FI FR GR HR HU IE IS IT LI LT LU LV MC MT NL NO PL PT RO SE SI SK SM VA | Available where your business is enabled | Not supported |
fps |
GB | Available where your business is enabled | Not supported |
- A
sepapayee is EUR only and needsiban. - A
fpspayee is GBP only and needs the 6-digit sort code inrouting_number, plusaccount_number. - Gravv debits the account in its own currency. The recipient receives EUR or GBP at the rate Gravv takes when you send. Read
local_amountin the response. If a rate looks wrong (for example exactly 1), stop and contact support before you send more. - If the first transfer returns
transfers to DE/EUR are not supported at this time, your business is not enabled for this rail yet. Contact support.
Local bank accounts and mobile wallets
Save a bank_account or mobile_money payee with an institution_id from GET /v1/external-accounts/institutions, then send without rail (or with "rail": "globalbank"):
curl --request POST \
--url https://api.gravv.xyz/v1/transfer \
--header 'Api-Key: <API_KEY>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: 5d2e8b1a-3c4f-4a6e-9b7d-0c1e2f3a4b62' \
--data '
{
"customer_id": "e0c40bf4-c1a6-4714-bde1-316a1c15e956",
"source": {
"source_type": "internal_account",
"id": "5151220a-b97c-442a-8cf5-b48ec96c8779"
},
"destination": {
"destination_type": "external_account",
"id": "ad2fee6e-161f-4b04-ac5f-39ed4e9182bc"
},
"amount": "150.00",
"description": "School fees",
"client_reference": "jp-rw-2026-10-003",
"additional_information": {
"remitter_full_name": "Jean-Paul Habimana",
"remitter_country": "CA"
}
}
'
{
"data": {
"amount": "150",
"amount_currency": "USD",
"reference": "c62d1693-2a10-4897-8b1d-279d3d64a646",
"date_created": "2026-10-13T11:02:40.300Z",
"transfer_status": "pending",
"transaction_id": "22a31043-d85f-44b8-abfd-94bd2924a529",
"local_amount": "213000",
"local_currency": "RWF",
"fee": "1",
"fee_currency": "USD",
"requires_approval": false
},
"error": null
}
- Some routes need the sender's name, country, date of birth or address. Send them in
additional_information. Gravv uses these values ahead of the ones on the customer profile. Without them, a transfer can pause withsender_details_required. local_amountis the amount priced for the recipient when Gravv accepted the transfer. Gravv does not lock the rate. It takes the rate when you send.- The transaction shows
transaction_typeglobal_remittance.
What can go wrong
| Response | Why | Fix |
|---|---|---|
400 transfers to NG/NGN are not available at this time |
The country is not open in this environment | Contact support to enable it |
400 transfers to RW/RWF are not supported at this time |
No route can pay this right now | Contact support |
400 this payee is not yet set up for transfers — please contact support to complete its setup |
The payee has no institution_id from the institutions list |
Save the payee with an institution_id |
400 the payee is missing required information for this transfer type — please update the payee details |
Gravv's record of the bank or operator lacks a code this route needs | Contact support with the payee id. Saving the payee again does not help |
400 payee type "swift" does not accept ACH/Wire transfers |
rail: "wire" for a SWIFT payee |
Send "rail": "swift" |
400 payee type "bank_account" does not accept ACH/Wire transfers |
rail: "wire" for a local payee |
Leave rail out |
400 this account can only send USD: the recipient must receive USD |
SEPA, FPS or a local payout from a bank-held USD account | Pay from a wallet-backed account |
400 the selected source account cannot be used for an international transfer |
This account cannot send abroad | Use the customer's USD account, or contact support |
400 destination country is required for international transfers |
A payee in a shared currency (XOF, XAF, EUR) without its country | Save the payee with an institution_id and institution_country_iso_code |
400 FX rate unavailable for currency conversion |
No rate right now | Retry later with a new Idempotency-Key |
200 with transfer_status paused |
The transfer needs a document or sender details, or it reached a limit | See Paused transfers |
Webhook transfer.status.failed, transaction still pending |
Manual review. The outcome was unclear, so a person checks it | Do not send it again. Contact support with the reference |
Recipes
- Bank rails abroad: SWIFT with an invoice, SWIFT with a document pause, SEPA, Faster Payments.
- Local payouts: Remittance and crypto.