TransferWise API
Base URL Sandbox
https://api.sandbox.transferwise.tech
Base URL LIVE
https://api.transferwise.com
Welcome to the TransferWise API documentation. You can explore the different ways to use our API and choose the right one for you below.
- Payouts and Account Automation
- Third-Party Payouts
- Banks
- Affiliates
- Connected Applications
- Receive Money
- Open Banking API
Payouts and Account Automation
This lets you to automate how you use your TransferWise account. You can automate payments, connect your business tools, and create ways to manage your finances.
You can:
- Power your cross-border and domestic payouts with a single API integration.
- Pay out directly to bank accounts or email recipients.
- Monitor payments received to your TransferWise local bank details (AUD, EUR, GBP, NZD, USD).
- Get statements for balance reconciliation and accounting purposes.
- Fully automate transfer creation and track statuses.
- Always get the mid-market exchange and our low cost transparent fees.
- Use our platform to create and build your own tool to manage your finances.
Our Payouts Guide will help you get started with the technical integration.
Third-Party Payouts
Third-Party Payouts allows marketplaces and financial institutions (banks and payment service providers) to use TransferWise as a payout option for their customers. It’s different from Payouts since it doesn’t require your company to be the originator of payments. Instead, TransferWise will act as a third-party to your customers when they initiate a payment through your site.
All the above listed payouts and account automation benefits are also true for third-party payouts service. You can build payment services to your customers on top of TransferWise payment platform that enables your customers to send cross-border payouts to 40+ currencies in 70+ countries.
In addition there will also be a dedicated account manager who will be your primary contact to solve all questions and support issues should these arise.
Please note that subscribing to third party payouts service requires your company to complete enhanced due diligence process performed by TransferWise compliance team. Please contact our sales team for more info how to get started.
Our Third-Party Payouts Guide will help you get started with the technical integration.
Banks
Our bank integration lets banks build TransferWise payments seamlessly into their own desktop and mobile apps. Banks can also build their own native user experience directly onto our API, co-branded with TransferWise.
What are the benefits for my bank?
- Provide your customers faster and cheaper cross-border payments, compared to traditional SWIFT alternatives.
- Offer competitive, fair, and transparent pricing to customers at the mid-market exchange rate.
- Reduce your operational costs of cross-border payments.
- Stop losing out on cross-border revenues because your customers are finding better alternatives.
How does it work?
- Transparent and fair pricing - Your customers will get the same price no matter if they make transfers via your bank integration or directly via TransferWise.
- Same great TransferWise service - Your customers get access to our 24/7 customer support without leaving your own site or app.
- Custom solution - We’ll work together to find and build a solution that works for your bank. There’s no one-size-fits-all approach. Together we’ll decide:
- How do we set up flow of funds?
- How do we handle customer support?
- How do we harmonize customer onboarding and AML processes?
See what some of our bank partners have to say
- Monzo and TransferWise in the United Kingdom
- N26 and TransferWise in Germany
- LHV and TransferWise in Estonia
- BPCE and TransferWise in France
Example: the N26 native user experience using TransferWise API
Please contact banks@transferwise.com to get started.
Take a look at our technical integration here – Bank Integration Guide.
Affiliates
When you apply to the TransferWise affiliates program you can get access to our API to help you build your own valuable content for your customers or readers.
The TransferWise API lets you to:
- Get the real-time mid-market exchange rates for any currency route.
- Get up to 30 days of historical mid-market exchange rates for any currency route.
- Get a TransferWise quote for any supported currency route, which includes our fees and estimated delivery time.
The Affiliates Integration Guide helps you get started with the technical integration.
Connected Applications
With Connected Applications, you can let your customers connect their TransferWise accounts to your product. Say you’re an accounting software – doing this could let your customers automate reconciliation. If you’re a payroll company, you could push customer payments right into TransferWise. You could even push TransferWise notifications through your app. Whatever you want to build, you likely could!
We need to take a deeper look into your application use case and the added value it will bring to our joint customers in order to authorise such an integration. So before starting the technical work please contact our sales team for more info on how to get started.
Our Connected Apps Guide gives you an overview of required technical integration work.
Receive Money
You can receive money to the local bank details that come with your TransferWise account (AUD, EUR, GBP, NZD and USD) and reconcile these incoming payments via the API.
Checkout flows
We currently don’t offer the option to build TransferWise into your checkout flow as a payment option to receive money. Note though that TransferWise can be added as a payout option on your site for beneficiaries to choose to receive their payout through to an email address, directly to a bank account or any other mechanism we support in our standard product.
Open Banking API
Under the Second Payment Services Directive (PDS2) we are opening up the standardized version of our API to the rest of the world. Find out more about our Open Banking API
Payouts Guide
Welcome to the TransferWise payouts API documentation. Before you start coding, please take few moments to review some important information about TransferWise and our API.
Getting started
1. Learn about TransferWise.
TransferWise and its borderless account features and pricing are best explained below.
https://transferwise.com/gb/borderless/pricing
2. Sign up for your TransferWise account, activate your borderless account, and complete verification.
Using the product before integrating with our API will help you understand how our payment flow works. Just follow these four steps.
Sign up for your TransferWise account https://transferwise.com/gb/borderless.
Complete verification – you need to do this before you start your technical integration. Also ensure you’re compliant with our Terms and Conditions and Acceptable Use Policy. Also make sure two-step log in is set up.
Activate at least one currency in your borderless account, deposit small amount (via card or bank transfer) and setup your first payment. This penny-testing is not mandatory of course, but we do recommended it so you will understand how TransferWise payment flow works.
Verify that our coverage includes your currency route(s). Check Supported Currencies. Please note that there are few restrictions for businesses, please review Restricted Business Routes
Please note that our Fixed Rate functionality is intended to provide time for customers to send funds to TransferWise, while holding the rate for them. TransferWise is not a trading platform and the Fixed Rate functionality is automatically disabled if abusive behaviour (such as multiple transfer creation and selective completion) is detected.
3. Choose the best tool for you
You don’t necessarily need to integrate with the API to make a large number of payouts. We have two ways you can do it:
Batch payments. Create and send up to 1,000 transfers with just one payment using our Batch Payments tool. All you need to do is fill a CSV file with all the transfer details, upload it to TransferWise, and pay for the batch. No development effort needed.
API integration. Completely automate your payment process by sending payment orders via the TransferWise API.
API access
curl -X GET https://api.sandbox.transferwise.tech/v1/profiles \
-H "Authorization: Bearer xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx"
Authentication
Sign up for a developer account and get your personal API token for our sandbox. https://sandbox.transferwise.tech/register
NB! Two factor authentication (2FA) code for sandbox login is 111111
.
Your developer account will have some test money that you can use to start making payments in same way as you would in a live environment. You can get your API tokens in the Settings tab of your account page.
Add your API token as header parameter to every request like this:
Authorization: Bearer xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
Acquiring your API token
Your API tokens section can be found at the bottom of the Settings page inside your TransferWise account. By default, you have no active tokens. You can issue new tokens after enabling 2-step login.
We support tokens of two permission levels:
- Read only - List and show transfers, recipients and balances
- Full access - Create, manage and fund transfers
Issue a Read only token unless you specifically need the capabilities of Full access. Token permission level can be changed after issuance. The lifetime of the token is 10 years.
Keeping your API token safe
Your API tokens should be guarded closely. They represent your identity and authorization and can be used to interact with your TransferWise account on your behalf. Whoever has access to your token can access your account details and history. In the case of a Full access token, they can also send transfers. Once you obtain an API token from us, it is on you to keep it safe.
Below is technical advise and guidance on how to protect your tokens. Not everything may apply to the application you are building and the goal is not to provide a long checklist of things to do. Rather, we attempt to provide generic guidance and best-practices, to send you in the right direction. You will have to do additional research and consider the specific technology and purpose of your application.
Source code
Don't store API tokens as plaintext files in Git
$ git clone https://github.com/mycompany/myapp.git
$ cat myapp.git/apiconfig.json
{
"token": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
"url": "api.transferwise.com"
}
A common mistake made by engineers is storing access tokens in source code, in plaintext - which is then shared in a version control system, sometimes publicly.
When an API token is stored like this, it can be accessed and used by anyone who has access to the source code. Avoid storing secrets in code.
Instead:
- Use environment variables to pass secrets into your application. You can configure them in your web server settings, startup script or platform-specific tools such as Docker or Kubernetes.
- If your deployment platform has a dedicated mechanism for storing secrets, use it
- Use a configuration file that is excluded from your version control. It can be created manually, or put into the deployment server by automated tools. Make sure the file can only be read by your web application
Limit permissions of a sensitive configuration file
$ cp .env.sample .env
$ echo .env >> .gitignore
$ chown myapp:root .env && chmod 600 .env
Token lifecycle
If you suspect that your token has leaked, revoke and rotate it. If you accidentally push a token to a remote public repository, rotate it. Quickly deleting an access token from VCS might not be enough - remember that VCS stores historical changes, is distributed and might have automation assigned to new pushes.
Revoke old tokens that you no longer need or use.
During the lifetime of an active token, limit the amount of people and systems who can access it. E-mail inboxes and chat logs are archived and not a secure place to hold tokens. Ideally, your access token would live only in TransferWise systems and your production system(s) that actually need it. You do not need to hold a backup copy of the token, as you can reveal an existing token from your profile settings page.
Encryption
TransferWise API is using HTTPS with >=TLS 1.2
. Non-encrypted HTTP connections are not accepted.
Do not connect to our API with unencrypted HTTP, as this will transmit your access token in plaintext over the network.
Verifying certificates in client code
<?php
// Secure - this will fail when an invalid HTTPS certificate is returned.
// Such failure is not normal and most likely means there is something
// in-between you and TransferWise, intercepting communications.
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_URL, 'https://api.transferwise.com');
// Insecure - do not do this. This will not validate certificates and
// might leak your access token to an attacker.
// See https://curl.haxx.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, 'https://api.transferwise.com');
Validate certificates. You should not proceed with a connection when you receive a certificate validation error from TransferWise. Make sure all parts of your application are using encryption and HTTPS and failing when certificate validation fails.
Application design
Secure your application against common security flaws (OWASP Top 10). Think how an attacker could leverage Unrestricted File Upload or Insecure Direct Object Reference to read the contents of your server's environment or config files.
If your application is larger, consider extracting TransferWise-specific functionality into a separate middleware or service layer. This would enable you to move API tokens there, separate from the main application.
Do not store the token in user-accessible code such as browser-side JavaScript or Android apps that can be decompiled. The token should always live server-side, exposing domain-logic via API-s.
If you need to pass the token around via HTTP requests, use HTTP headers or POST body - do not store the token in URI or query parameters. Web servers usually log the URL and browsers pass it between websites via the Referrer header.
Limiting token access by IP
You can enhance your integration security by only allowing certain IP addresses to use your API token.
Typically, you would integrate with our API from a set number of fixed IP addresses. Restricting access from all other IPs will make it harder to misuse your API token, should it ever leak. IP whitelisting does not protect against cases where several clients egress from the same whitelisted IP (shared external IP for the office network, an egress proxy in front of all of your servers).
Each token can be limited to single IP addresses, a set of IP addresses or entire IP ranges. You can do this in the API token edit view.
Please note:
- IP addresses should use only IPv4 format e.g.
192.168.100.14
- IP ranges should use CIDR notation e.g.
192.168.100.0/24
which would include192.168.100.0
up to192.168.100.255
- You can authorize multiple discrete IP-s or IP ranges for one token
If a request is being made using an IP address that is not in the whitelisted IP addresses, the server will respond with a 401 Unauthorized HTTP status code.
TEST and LIVE environments
- You can access the Sandbox API at https://api.sandbox.transferwise.tech
- The LIVE API is located at https://api.transferwise.com
Please note Sandbox environment is limited. We do not send any emails from it as well as transfer processing is not simulated. Please consider Simulation endpoints to change transfer state after funding.
Get your profile id
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/profiles \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": 217896,
"type": "personal",
"details": {
"firstName": "Oliver",
"lastName": "Wilson",
"dateOfBirth": "1977-07-01",
"phoneNumber": "+3725064992",
"avatar": "https://lh6.googleusercontent.com/-XzeFZ2PJE1A/AAAAAAAI/AAAAAAAAAAA/RvuvhXFsqs0/photo.jpg",
"occupation": null,
"primaryAddress": 236532
}
},
{
"id": 220192,
"type": "business",
"details": {
"name": "ABC Logistics Ltd",
"registrationNumber": "12144939",
"acn": null,
"abn": null,
"arbn": null,
"companyType": "LIMITED",
"companyRole": "OWNER",
"descriptionOfBusiness": "Information and communication",
"primaryAddress": 240402,
"webpage": "https://abc-logistics.com"
}
}
]
You only need to call this endpoint once to obtain your user profile id. Your personal and business profiles have different IDs. Profile id values are required when making payouts.
It’s recommended to always provide profileId when you’re creating new resources later (Create Quote, Create Recipient Account, Create Transfer). If you omit profileId then resource will by default belong to your personal profile. This might not be your intention, as you most probably want to execute transfers under your business profile.
Request
GET https://api.sandbox.transferwise.tech/v1/profiles
Response
Personal Profile Fields
Field | Description | Format |
---|---|---|
id | Personal profile id | Integer |
type | Profile type | Text |
details.firstName | Person first name | Text |
details.lastName | Person last name | Text |
details.dateOfBirth | Date of birth | "yyyy-mm-dd" |
details.phoneNumber | Phone number | Text |
details.avatar | Link to avatar image | Text |
details.occupation | Occupation | Text |
details.primaryAddress | Address object id | Integer |
Business Profile Fields
Field | Description | Format |
---|---|---|
id | Business profile id | Integer |
type | Profile type | Text |
details.name | Business name | Text |
details.registrationNumber | Business registration number | Text |
details.acn | ACN (only applicable for Australian business) | Text |
details.abn | ABN (only applicable for Australian business) | Text |
details.arbn | ARBN (only applicable for Australian business) | Text |
details.companyType | Company legal type | Text |
details.companyRole | Person's role in the company | Text |
details.descriptionOfBusiness | Business description | Text |
details.primaryAddress | Address object id | Integer |
details.webpage | Webpage URL | Text |
Create quote
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/quotes \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"source": "EUR",
"target": "GBP",
"rateType": "FIXED",
"targetAmount": 600,
"type": "BALANCE_PAYOUT"
}'
Example Response:
{
"id": 10451930,
"source": "EUR",
"target": "GBP",
"sourceAmount": 663.84,
"targetAmount": 600.00,
"type": "BALANCE_PAYOUT",
"rate": 0.9073,
"createdTime": "2018-08-27T14:35:44.553Z",
"createdByUserId": <your user id>,
"profile": <your profile id>,
"rateType": "FIXED",
"deliveryEstimate": "2018-08-27T14:35:44.496Z",
"fee": 2.34,
"allowedProfileTypes": [
"PERSONAL",
"BUSINESS"
],
"guaranteedTargetAmount": false,
"ofSourceAmount": true
}
There are four steps to execute payouts:
Step 1: Create a quote
Step 2: Create a recipient account
Step 3: Create a transfer
Step 4: Fund a transfer
Quote fetches current mid-market exchange rate that will be used for your transfer. Quote also calculates our fee and estimated delivery time.
Request
POST https://api.sandbox.transferwise.tech/v1/quotes
Field | Description | Format |
---|---|---|
profile | Personal or business profile id | Text |
source | Source(send) currency code | Text |
target | Target(receive) currency code | Text |
rateType | Always use constant 'FIXED' | Text |
targetAmount | Amount in target currency | Decimal |
sourceAmount | Amount in source currency. Either sourceAmount or targetAmount is required, never both. |
Decimal |
type | 'BALANCE_PAYOUT' for payments 'BALANCE_CONVERSION' for conversion between balances |
Text |
Response
Quote id is needed for creating transfers in step 3.
Field | Description | Format |
---|---|---|
id | Quote id | Integer |
source | Source(send) currency code | Text |
target | Target(receive) currency code | Text |
sourceAmount | Amount in source currency | Decimal |
targetAmount | Amount in target currency | Decimal |
type | Quote type | Text |
rate | Exchange rate value | Decimal |
createdTime | Quote created timestamp | Timestamp |
createdByUserId | Your used id | Integer |
profile | Personal or business profile id | Integer |
rateType | Always 'FIXED' | Text |
deliveryEstimate | Estimated timestamp when recipient would receive funds, assuming transfer will be created now. | Timestamp |
fee | TransferWise fee in source currency for this payment (deducted from source amount). | Decimal |
allowedProfileTypes | PERSONAL, BUSINESS or both. Specifies which legal entities can use this quote. There are a few currency routes that we don’t support for business customers yet. | Text |
guaranteedTargetAmount | Not relevant for fixed rate quotes. Please ignore. | Boolean |
ofSourceAmount | Not relevant for fixed rate quotes. Please ignore. | Boolean |
Create recipient account
Example Request (Create GBP recipient):
curl -X POST https://api.sandbox.transferwise.tech/v1/accounts \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"currency": "GBP",
"type": "sort_code",
"profile": <your profile id>,
"accountHolderName": "Ann Johnson",
"legalType": "PRIVATE",
"details": {
"sortCode": "231470",
"accountNumber": "28821822"
}
}'
Example Response (Create GBP recipient):
json { "id": 31273058, "profile": <your profile id>, "accountHolderName": "Ann Johnson", "type": "sort_code", "country": "GB", "currency": "GBP", "details": { "accountNumber": "28821822", "sortCode": "231470" } }
There are four steps to execute payouts:
Step 1: Create a quote
Step 2: Create a recipient account
Step 3: Create a transfer
Step 4: Fund a transfer
Recipient is a person or institution who is the ultimate beneficiary of your payment.
Recipient bank account details are different for different currencies. For example, you only need to know the IBAN number to send payments to most European and Nordic countries. But in order to send money to Canada, you’d need to fill out four fields: You recipient’s institution number, transit number, account number, and account type.
A UK GBP example is provided here. You can find other currency examples in Recipient Accounts section below.
Request
POST https://api.sandbox.transferwise.tech/v1/accounts
Field | Description | Format |
---|---|---|
currency | 3 character currency code | Text |
type | Recipient type | Text |
profile | Personal or business profile id | Integer |
accountHolderName | Recipient full name | Text |
legalType | Recipient legal type: PRIVATE or BUSINESS | Text |
details | Currency specific fields | Group |
details.sortCode | Recipient bank sort code (GBP example) | Text |
details.accountNumber | Recipient bank account no (GBP example) | Text |
Response
Recipient id is needed for creating transfers in step 3.
Field | Description | Format |
---|---|---|
id | recipientAccountId | Integer |
profile | Personal or business profile id | Integer |
acccountHolderName | Recipient full name | Text |
currency | 3 character country code | Text |
country | 2 character currency code | Text |
type | Recipient type | Text |
details | Currency specific fields | Group |
details.sortCode | Recipient bank sort code (GBP example) | Text |
details.accountNumber | Recipient bank account no (GBP example) | Text |
Send money to email recipient
If you don't know your recipient’s bank account details, you can still send money using their email address. You need to set up email recipient and then TransferWise will collect bank details directly from your recipient.
When you set up the transfer, we’ll email your recipient a secure link to collect their bank account details. Once your recipient provides their bank account details to us, we’re able to complete your transfer.
See below under Recipient Accounts.Create Email Recipients for more details.
Create transfer
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/transfers \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"targetAccount": <recipient account id>,
"quote": <quote id>,
"customerTransactionId": "<the UUID you generated for the transfer attempt>",
"details" : {
"reference" : "to my friend",
"transferPurpose": "verification.transfers.purpose.pay.bills",
"sourceOfFunds": "verification.source.of.funds.other"
}
}'
Example Response:
{
"id": 468956,
"user": <your user id>,
"targetAccount": <recipient account id>,
"sourceAccount": null,
"quote": <quote id>,
"status": "incoming_payment_waiting",
"reference": "to my friend",
"rate": 0.9065,
"created": "2018-08-28 07:43:55",
"business": <your business profile id>,
"transferRequest": null,
"details": {
"reference": "to my friend"
},
"hasActiveIssues": false,
"sourceCurrency": "EUR",
"sourceValue": 661.89,
"targetCurrency": "GBP",
"targetValue": 600,
"customerTransactionId": "bd244a95-dcf8-4c31-aac8-bf5e2f3e54c0"
}
There are four steps to execute payouts:
Step 1: Create a quote
Step 2: Create a recipient account
Step 3: Create a transfer
Step 4: Fund a transfer
A transfer is a payout order you make to a recipient account based on a quote. Once created, a transfer will need to be funded within the next 5 working days, or it’ll automatically get cancelled.
Request
POST https://api.sandbox.transferwise.tech/v1/transfers
Field | Description | Format |
---|---|---|
targetAccount | Recipient account id. You can create multiple transfers to same recipient account. | Integer |
quote | Quote id. You can only create one transfer per one quote. You cannot use same quote ID to create multiple transfers. |
Integer |
customerTransactionId | This is required to perform idempotency check to avoid duplicate transfers in case of network failures or timeouts. | UUID |
details.reference (optional) | Recipient will see this reference text in their bank statement. Maximum allowed characters depends on the currency route. Read the Business Payments Tips article for more information. | Text |
details.transferPurpose (conditionally required) | For example when target currency is THB. See more about conditions at Transfers.Requirements | Text |
details.sourceOfFunds (conditionally required) | For example when target currency is USD and transfer amount exceeds 10k. See more about conditions at Transfers.Requirements | Text |
There are two options to deal with conditionally required fields:
- Always provide values for these fields
- Always call transfers-requirements endpoint and submit values only if indicated so
Response
You need to save the transfer id for tracking its status later.
Field | Description | Format |
---|---|---|
id | Transfer id | Integer |
user | Your user id | Integer |
targetAccount | Recipient account id | Integer |
sourceAccount | Not used | Integer |
quote | Quote id | Integer |
status | Transfer current status | Text |
reference | Deprecated, use details.reference instead | Text |
rate | Exchange rate value | Decimal |
created | Timestamp when transfer was created | Timestamp |
business | Your business profile id | Integer |
transferRequest | Not used | Integer |
details.reference | Payment reference text | Text |
hasActiveIssues | Are there any pending issues which stop executing the transfer? | Boolean |
sourceCurrency | Source currency code | Text |
sourceValue | Transfer amount in source currency | Decimal |
targetCurrency | Target currency code | Text |
targetValue | Transfer amount in target currency | Decimal |
customerTransactionId | UUID format unique identifier assigned by customer. Used for idempotency check purposes. | UUID |
Avoiding duplicate transfers
We use customerTransactionId field to avoid duplicate transfer requests. When your first call fails (error or timeout) then you should use the same value in customerTransactionId field that you used in the original call when you are submitting a retry message. This way we can treat subsequent retry messages as repeat messages and will not create duplicate transfers to your account.
Fund transfer
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v3/profiles/{profileId}/transfers/{transferId}/payments \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"type": "BALANCE"
}'
Example Response:
{
"type": "BALANCE",
"status": "COMPLETED",
"errorCode": null
}
There are four steps to execute payouts:
Step 1: Create a quote
Step 2: Create a recipient account
Step 3: Create a transfer
Step 4: Fund a transfer
This API call is the final step for executing payouts. TransferWise will now debit funds from your borderless account balance and start processing your transfer.
If your borderless balance is short of funds then this call will fail with "insufficient funds" error.
Initial developer account has by default plentiful funds available for EUR, USD, GBP, and AUD.
You can add new currencies to your account via the user interface: https://sandbox.transferwise.tech
You can then top up your new currencies by converting funds from other currencies.
Request
POST https://api.sandbox.transferwise.tech/v3/profiles/{profileId}/transfers/{transferId}/payments
Use transfer id that you obtained in previous step.
Field | Description | Format |
---|---|---|
type | "BALANCE". This indicates that your transfer will be funded from your borderless account balance. |
Text |
Response
You need to save transfer id for tracking its status later.
Field | Description | Format |
---|---|---|
type | "BALANCE" | Text |
status | "COMPLETED" or "REJECTED" | Text |
errorCode | Failure reason. For example "balance.payment-option-unavailable" | Text |
Get transfer delivery time
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/delivery-estimates/{transferId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"estimatedDeliveryDate" : "2018-01-10T12:15:00.000+0000"
}
Get the live delivery estimate for a transfer by the transfer ID. The delivery estimate is the time at which we currently expect the transfer to arrive in the beneficiary's bank account. This is not a guaranteed time, but we’re working hard to make these estimates as accurate as possible.
Request
GET https://api.sandbox.transferwise.tech/v1/delivery-estimates/{transferId}
Response
You need to save the transfer id to track its status later.
Field | Description | Format |
---|---|---|
estimatedDeliveryDate | Estimated time when funds will arrive to recipient's bank account | Timestamp |
Track transfer status
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/transfers/{transferId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": 468956,
"user": <your user id>,
"targetAccount": <recipient account id>,
"sourceAccount": null,
"quote": <quote id>,
"status": "outgoing_payment_sent",
"reference": "to my friend",
"rate": 0.9065,
"created": "2018-08-28 07:43:55",
"business": <your business profile id>,
"transferRequest": null,
"details": {
"reference": "to my friend"
},
"hasActiveIssues": false,
"sourceCurrency": "EUR",
"sourceValue": 661.89,
"targetCurrency": "GBP",
"targetValue": 600,
"customerTransactionId": "bd244a95-dcf8-4c31-aac8-bf5e2f3e54c0"
}
You can check your latest transfer status by polling this endpoint. You can use webhooks to get notified about transfer status updates. Normal state flow of transfers:
Incoming Payment Waiting ⇒ Processing ⇒ Funds Converted ⇒ Outgoing Payment Sent
Outgoing Payment Sent is the final state of the normal flow. If the payment fails, the problematic flow will continue. An example would be if the recipient bank account doesn’t exist or is entered wrong and the payment is returned. Problematic state flow of transfers:
Outgoing Payment Sent ⇒ Bounced Back ⇒ Funds Refunded
Most bounce backs occur within 2-3 business days. However, to be on the safe side, we advise you to check the transfer status for potential bounce backs for 2 weeks.
Transfer state flow
See below for the full list of transfer statuses and what they mean in the order of occurrence:
incoming_payment_waiting –You have submitted a transfer and it’s waiting for funding.
waiting_recipient_input_to_proceed – This status is only used for “send money to email” transfers. It means we’re waiting for your recipient to fill in their bank details so we can continue processing your transfer.
processing – We have receive your funds and are processing the transfer. Processing is a generic term and means we’re doing behind-the-scene activities before the money gets to your recipient, like AML, compliance, and fraud checks.
funds_converted – All compliance checks have been completed with your transfer and funds have been converted from source (your) currency to target (your recipient’s) currency.
outgoing_payment_sent – This means TransferWise has paid out funds to your recipient. This is the final state of the transfer, assuming funds will not be returned. When a transfer has this state it doesn’t mean the money has arrived in your recipient’s bank account. Note: Payment systems in different countries operate in different speeds and frequency. For example, in the UK, the payment will reach your recipient bank account within few minutes after we have sent the outgoing payment. However, in Eurozone and US, it usually takes a day until funds are available.
cancelled – This status is used when the transfer you created was not funded and therefore never processed. This is a final state of the transfer.
funds_refunded – Transfer has been refunded. This is a final final state of the transfer.
bounced_back –Transfer has bounced back but has not been cancelled nor refunded yet. This is not a final transfer state, it means the transfer will either be delivered with delay or it will turn to funds_refunded state
Keep in mind the transfer statuses in our API have different names than what you’ll see on our website or app. That’s because we use more consumer friendly language in the front end of our products. For example "Completed" on our website means "outgoing_payment_sent" in the API.
Sandbox limitations
We don't send out email notifications about payment status changes in sandbox.
We don't process payments in sandbox, which means that created payments remain in their first state. You can use Simulation endpoints to change transfer statuses in sandbox.
Check account balance
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/borderless-accounts?profileId={profileId} \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": 64,
"profileId": <your profile id>,
"recipientId": 13828530,
"creationTime": "2018-03-14T12:31:15.678Z",
"modificationTime": "2018-03-19T15:19:42.111Z",
"active": true,
"eligible": true,
"balances": [
{
"balanceType": "AVAILABLE",
"currency": "GBP",
"amount": {
"value": 10999859,
"currency": "GBP"
},
"reservedAmount": {
"value": 0,
"currency": "GBP"
},
"bankDetails": null
},
{
"balanceType": "AVAILABLE",
"currency": "EUR",
"amount": {
"value": 9945236.2,
"currency": "EUR"
},
"reservedAmount": {
"value": 0,
"currency": "EUR"
},
"bankDetails": null
}
]
}
]
Get available balances for all activated currencies in your account.
Request
GET https://api.sandbox.transferwise.tech/v1/borderless-accounts?profileId={profileId}
Use profile id obtained earlier to make this call.
Response
Field | Description | Format |
---|---|---|
id | borderlessAccountId | Integer |
profileId | Personal or business profile id | Integer |
recipientId | Recipient id you can use for borderless top up payment order | Integer |
creationTime | Date when balance account was opened | Timestamp |
modificationTime | Date when balance account setup was modified | Timestamp |
active | Is borderless account active or inactive | Boolean |
eligible | Ignore | Boolean |
balances[n].balanceType | AVAILABLE | Text |
balances[n].currency | Currency code | Text |
balances[n].amount.value | Available balance in specified currency | Decimal |
balances[n].amount.currency | Currency code | Text |
balances[n].reservedAmount.value | Reserved amount from your balance | Decimal |
balances[n].reservedAmount.currency | Reserved amount currency code | Text |
balances[n].bankDetails | Your borderless account bank details | Group |
Get account statement
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v3/profiles/{profileId}/borderless-accounts/{borderlessAccountId}/statement.json?
currency=EUR&intervalStart=2018-03-01T00:00:00.000Z&intervalEnd=2018-03-15T23:59:59.999Z \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"accountHolder": {
"type": "PERSONAL",
"address": {
"addressFirstLine": "Veerenni 24",
"city": "Tallinn",
"postCode": "12112",
"stateCode": "",
"countryName": "Estonia"
},
"firstName": "Oliver",
"lastName": "Wilson"
},
"issuer": {
"name": "TransferWise Ltd.",
"firstLine": "56 Shoreditch High Street",
"city": "London",
"postCode": "E1 6JJ",
"stateCode": "",
"country": "United Kingdom"
},
"bankDetails": null,
"transactions": [
{
"type": "DEBIT",
"date": "2018-04-30T08:47:05.832Z",
"amount": {
"value": -7.76,
"currency": "EUR"
},
"totalFees": {
"value": 0.04,
"currency": "EUR"
},
"details": {
"type": "CARD",
"description": "Card transaction of 6.80 GBP issued by Tfl.gov.uk/cp TFL TRAVEL CH",
"amount": {
"value": 6.8,
"currency": "GBP"
},
"category": "Transportation Suburban and Loca",
"merchant": {
"name": "Tfl.gov.uk/cp",
"firstLine": null,
"postCode": "SW1H 0TL ",
"city": "TFL TRAVEL CH",
"state": " ",
"country": "GB",
"category": "Transportation Suburban and Loca"
}
},
"exchangeDetails": {
"forAmount": {
"value": 6.8,
"currency": "GBP"
},
"rate": null
},
"runningBalance": {
"value": 16.01,
"currency": "EUR"
},
"referenceNumber": "CARD-249281"
},
{
"type": "CREDIT",
"date": "2018-04-17T07:47:00.227Z",
"amount": {
"value": 200,
"currency": "EUR"
},
"totalFees": {
"value": 0,
"currency": "EUR"
},
"details": {
"type": "DEPOSIT",
"description": "Received money from HEIN LAURI with reference SVWZ+topup card",
"senderName": "HEIN LAURI",
"senderAccount": "EE76 1700 0170 0049 6704 ",
"paymentReference": "SVWZ+topup card"
},
"exchangeDetails": null,
"runningBalance": {
"value": 207.69,
"currency": "EUR"
},
"referenceNumber": "TRANSFER-34188888"
},
{
"type": "CREDIT",
"date": "2018-04-10T05:58:34.681Z",
"amount": {
"value": 9.94,
"currency": "EUR"
},
"totalFees": {
"value": 0,
"currency": "EUR"
},
"details": {
"type": "CONVERSION",
"description": "Converted 8.69 GBP to 9.94 EUR",
"sourceAmount": {
"value": 8.69,
"currency": "GBP"
},
"targetAmount": {
"value": 9.94,
"currency": "EUR"
},
"fee": {
"value": 0.03,
"currency": "GBP"
},
"rate": 1.147806
},
"exchangeDetails": null,
"runningBalance": {
"value": 9.94,
"currency": "EUR"
},
"referenceNumber": "CONVERSION-1511237"
}
],
"endOfStatementBalance": {
"value": 9.94,
"currency": "EUR"
},
"query": {
"intervalStart": "2018-03-01T00:00:00Z",
"intervalEnd": "2018-04-30T23:59:59.999Z",
"currency": "EUR",
"accountId": 64
}
}
Get borderless account statement for one currency and for specified time range. The period between intervalStart and intervalEnd cannot exceed 469 days (around 1 year 3 month).
Request
GET https://api.sandbox.transferwise.tech/v3/profiles/{profileId}/borderless-accounts/{borderlessAccountId}/statement.json?
currency=EUR&intervalStart=2018-03-01T00:00:00.000Z&intervalEnd=2018-03-15T23:59:59.999Z
All query parameters are mandatory.
Field | Description | Format |
---|---|---|
borderlessAccountId | Your borderlessAccountId is included in "Check account balance" response as field "id". | Integer |
currency | Currency code | Text |
intervalStart | Statement start time in UTC time | Zulu time. Don't forget the 'Z' at the end. |
intervalEnd | Statement start time in UTC time | Zulu time. Don't forget the 'Z' at the end. |
Note that you can also download statements in PDF and CSV formats if you replace statement.json with statement.csv or statement.pdf respectively in the above URL.
Response
Field | Description | Format |
---|---|---|
accountHolder.type | Account holder type: PERSONAL or BUSINESS | Text |
accountHolder.address.addressFirstLine | Account holder address street | Text |
accountHolder.address.city | Account holder address city | Text |
accountHolder.address.postCode | Account holder address zip code | Text |
accountHolder.address.stateCode | Account holder address state | Text |
accountHolder.address.countryName | Account holder address country | Text |
accountHolder.firstName | Account holder first name | Text |
accountHolder.lastName | Account holder last name | Text |
issuer.name | Account issuer name | Text |
issuer.firstLine | Account issuer address street | Text |
issuer.city | Account issuer address city | Text |
issuer.postCode | Account issuer address zip code | Text |
issuer.stateCode | Account issuer address state | Text |
issuer.country | Account issuer address country | Text |
bankDetails | Your borderless account bank details | Group |
transactions[n].type | DEBIT or CREDIT | Text |
transactions[n].date | Time of transaction | Zulu time |
transactions[n].amount.value | Transaction amount | Decimal |
transactions[n].amount.currency | Transaction currency code | Text |
transactions[n].totalFees.value | Transaction fee amount | Decimal |
transactions[n].totalFees.currency | Transaction fee currency code | Text |
transactions[n].details.type | CARD, CONVERSION, DEPOSIT, TRANSFER, MONEY_ADDED | Text |
transactions[n].details.description | Human readable explanation about the transaction | Text |
transactions[n].details.amount.value | Amount in original currency (card transactions abroad) | Decimal |
transactions[n].details.amount.currency | Original currency code | Text |
transactions[n].details.sourceAmount.value | Amount in source currency (conversions) | Decimal |
transactions[n].details.sourceAmount.currency | Source currency code | Text |
transactions[n].details.targetAmount.value | Amount in target currency (conversions) | Decimal |
transactions[n].details.targetAmount.currency | Target currency code | Text |
transactions[n].details.fee.value | Conversion fee amount | Decimal |
transactions[n].details.fee.currency | Conversion fee currency code | Text |
transactions[n].details.rate | Conversion exchange rate | Decimal |
transactions[n].details.senderName | Deposit sender name | Text |
transactions[n].details.senderAccount | Deposit sender bank account details | Text |
transactions[n].details.paymentReference | Deposit payment reference text | Text |
transactions[n].details.category | Card transaction category | Text |
transactions[n].details.merchant.name | Card transaction merchant name | Text |
transactions[n].details.merchant.firstLine | Merchant address street | Text |
transactions[n].details.merchant.postCode | Merchant address zip code | Text |
transactions[n].details.merchant.city | Merchant address city | Text |
transactions[n].details.merchant.state | Merchant address state | Text |
transactions[n].details.merchant.country | Merchant address country | Text |
transactions[n].details.merchant.category | Merchant category | Text |
transactions[n].exchangeDetails.forAmount.value | Currency exchange amount | Decimal |
transactions[n].exchangeDetails.forAmount.currency | Currency code | Text |
transactions[n].exchangeDetails.rate | Exchange rate | Decimal |
transactions[n].runningBalance.value | Running balance after the transaction | Decimal |
transactions[n].runningBalance.currency | Running balance currency code | Text |
transactions[n].referenceNumber | TransferWise assigned unique transaction reference number | Text |
endOfStatementBalance.value | Closing balance for specified time period | Decimal |
endOfStatementBalance.currency | Closing balance currency code | Text |
query.intervalStart | Query parameter repeated | Zulu time |
query.intervalEnd | Query parameter repeated | Zulu time |
query.currency | Query parameter repeated | Text |
query.accountId | Query parameter repeated | Integer |
Create topup order
Step 1 - Create quote for topup:
curl -X POST https://api.sandbox.transferwise.tech/v1/quotes \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"source": "EUR",
"target": "EUR",
"rateType": "FIXED",
"targetAmount": 6000,
"type": "REGULAR"
}'
Step 2 - Find out your balance recipient account id:
curl -X GET https://api.sandbox.transferwise.tech/v1/borderless-accounts?profileId={profileId} \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": 64,
"profileId": <your profile id>,
"recipientId": <your balance recipient account id>,
...
}
]
Step 3 - Create transfer for topup:
curl -X POST https://api.sandbox.transferwise.tech/v1/transfers \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"targetAccount": <recipient account id fetched in step 2>,
"quote": <quote id from step 1>,
"customerTransactionId": "<the UUID you generated for the transfer attempt>",
"details" : {
"reference" : "optional text to identify your topup order"
}
}'
There are 2 different ways you can send funds to your borderless account:
1) Simply send domestic bank transfer from your bank account to your borderless account details (IBAN / SortCode-AccountNo). There is no need to setup a topup order in this case.
2) Create a topup order and then send corresponding amount via domestic or international bank transfer to TransferWise escrow bank account details.
You can obtain escrow account details from your account manager.
This option is usually used when you are sending funds via international (swift) transfers.
Setting up a topup order is similar to setting up a regular transfer. Some minor changes are documented below.
1. Create topup quote
POST https://api.sandbox.transferwise.tech/v1/quotes
Same way as described in Create quote but use quote type REGULAR:
2. Find out your balance recipient account id
GET https://api.sandbox.transferwise.tech/v1/borderless-accounts?profileId={profileId}
Call Check account balance endpoint and fetch recipientId field value from the response.
This recipientId will not change, so you just need to fetch it once and then you can re-use the same value for all topup orders.
3. Create topup transfer (order)
POST https://api.sandbox.transferwise.tech/v1/transfers
As last step you now need to create a transfer (topup order). This is same call as described in Create transfer.
Use the value fetched in previous step in targetAccount field.
All done.
Going live checklist
1. Make your integration bulletproof
- Implement basic retry mechanism to handle potential failures or network interruptions
- Implement duplicate prevention mechanism to avoid duplicate payments. Verify that UUID is uniquely generated for each individual payment and that its value is kept the same in case of retrying.
- Implement basic logging to help out in debugging and problem solving, if needed.
- Check that you can handle all possible transfer states during polling of transfer info.
- Automatically check available balance before submitting requests to fund your transfers. This avoids rejections due to insufficient balance.
- Verify that your borderless account statement includes all the information you need for financial accounting.
2. Open LIVE account
- Sign up for your TransferWise account and go through the onboarding flow, including the 2FA setup. Make sure your borderless account and balances are activated.
3. Set up security for LIVE environment
- Get your live API token from Settings page.
- Store your live API token securely in your production servers so that only authorized members of your team have access to it.
4. Do penny testing in LIVE
- Make a small deposit into your borderless account.
- Make few small value test payments via LIVE API before you start executing larger transfers.
- All set. Switch it on.
5. Sign up for API status notifications.
Third-Party Payouts Guide
This guide is an extension to Payouts Guide and it only outlines small differences between creating regular transfers and creating third party transfers. Please read through regular Payouts Guide first.
Differences
There are four steps to complete payouts:
- Step 1: Create a quote
- Step 2: Create a recipient account
- Step 3: Create a transfer
- Step 4: Fund a transfer
The difference compared to regular payouts is limited to using a different endpoint in Step 3: Create a transfer.
Instead of using POST https://api.sandbox.transferwise.tech/v1/transfers
endpoint to create transfers you need to use
POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/third-party-payments
endpoint.
This endpoint is very similar to regular Create transfers endpoint, but please note these differences:
- Payment originator datablock is additionally required.
- originalTransferId field is being used instead of customerTransactionId
Full details how to use this endpoint can be found under API Reference section Create Third-Party Transfers.
All other functionality is available exactly same way as described under Payouts Guide above.
Limitations
- API only. You can only create third party transfers via API. Creating third party transfers via batch file upload or via transferwise.com user interface is not possible yet.
- Email recipients are not supported. We don't support setting up third party transfers to email recipients. You can send payments to bank accounts only.
- Some currency routes are not supported. Please contact our sales team for details.
Bank Integrations Guide (LEGACY)
New documentation available
For any banks who are beginning their integration now please use the new version of the TransferWise for Banks API documentation which has been updated and improved with he latest API endpoints and use cases for banks. This documentation remains only as a reference for older integrations.
API access
TransferWise uses standard OAuth 2.0 protocol for authentication and authorization.
Once our partnership begins, we’ll send you API access credentials for the sandbox environment consisting of a Client ID and a Client Secret. The credentials are needed to complete the authorisation_code grant type of OAuth 2.0 through which the customer will allow your application to be able to act on their behalf. We also need redirect_url from your technical team so that we can limit our callbacks to only that URL, this is URL that we will forward users to after successfully granting your application access to their TransferWise account. Specifying this explicitly makes the integration more secure. This article about OAuth 2.0 framework is a great way to refresh your knowledge about the protocol itself.
SANDBOX and LIVE environments
- Sandbox API is located at https://api.sandbox.transferwise.tech
- LIVE API is located at https://api.transferwise.com
Customized user interface
You will build your TransferWise user experience directly into your mobile and desktop applications.
There are different ways to build the frontend experience, especially when it comes to the sequence of steps in the payment flow. This guide is more like a list of building blocks and ideas for what you can do, rather than a strict step-by-step guide.
For example, you can put sign up/log in step as a first step, then show the currency calculator, and then collect recipient details. Alternatively, you can build it so a user starts from the calculator, then you collect recipient details, and as a last step ask user to sign up/log in.
We have plenty of examples to show you how this has been done by our current partners and can help you to build a great experience for your customers.
Building your backend
You should expose an API internally for your web and mobile clients to call to provide the required TransferWise features. Your backend system will manage both communication to the TransferWise API and internal operations such as checking a user has sufficient balance to make the requested transfer and triggering the funds to be sent to TransferWise when they confirm a transfer.
You should also store a copy of certain data relating to TransferWise to decrease latency and increase resiliency when users review previous transfers they made or recipients they sent funds to. The extent of what you store will depend on your integration.
You should also build a polling mechanism to periodically update the status of a transfer and its delivery estimate, keeping your user up to date of where their transfer is in the process.
We have a dedicated team focusing on bank partnerships who will help you along the way, sharing knowledge and experience from previous integrations to help you build a robust and highly available system.
Your TransferWise user experience
User onboarding flow
The user onboarding flow consists of these building blocks.
You need to go through this flow only once for each customer before they can set up their first transfer.
- Get user authorization for existing accounts or sign up a new user via API
- Get user tokens
- Create personal user profile
- Create business user profile - this is an optional step only to be used if your bank is providing business customers access to TransferWise.
Transfer flow
To create transfers on behalf of users you need these building blocks:
Transfer update polling
To keep your users informed of the status and estimated time of arrival of their transfer:
Get user authorization for existing accounts
At a high level there are three steps to gaining access to an existing TransferWise account.
- Your app redirects the user to TransferWise authorization webpage, which prompts them to login if necessary.
- The user logs in to TransferWise.
- The user agrees to provide access, the TransferWise authorization page then redirects user back to your pre-configured url, including a code you can use to generate user tokens. e.g.
https://www.yourbank.com/?code=[CODE]
These steps are explained in more detail below.
1. Your banking app redirects user to TransferWise authorization webpage
Your website or app opens the following url in the user's browser.
Sandbox:
https://sandbox.transferwise.tech/oauth/authorize/?client_id={clientId}&redirect_uri={redirectUri}
Live:
https://transferwise.com/oauth/authorize/?client_id={clientId}&redirect_uri={redirectUri}
List of available parameters:
Parameter | Description |
---|---|
client_id (required) | The client ID you received from us. |
redirect_uri (required) | The preconfigured URL in your application where users will be sent after authorization. |
state | An opaque value, used for security purposes. If this parameter is set in the request, then it is returned to the application as part of the redirect_uri. More about state parameter. |
On mobiles apps you should not use WebView
components to show the authorization page to the users because they are not secure and will not allow users to log in to TransferWise with Google, which is an option used by some of our users. Your app should instead open the device's full browser app.
Please also note that provided [CODE]
expires within 30 minutes and is one time use only.
2. The user logs in to TransferWise
Our usual log in screens are presented to the user if they are not already logged in on the browser being used. If enabled for a user they will also be prompted to go through our two-factor authentication procedure.
3. The user agrees to grant access and we forward them to your redirect_url
Once a user gives your banking app authorization to connect to TransferWise and access their data, the user is redirected back to your redirect_url with a generated code query string value. For example
https://www.yourbank.com/?code=[CODE]
Your website or service can then use this code to obtain the access token to act on behalf of the user account described in the get user tokens section.
If you are building your TransferWise integration as a native mobile phone app then the redirect URL should be able to handle returning the user to the correct place in the app.
At the point you gain access to a user account you should double check it is the one you were expecting to be given access to - sometimes users can get confused and log in to a different account. Together we want to avoid TransferWise accounts being linked to bank accounts of a different person or business, therefore you should check the user's details once the link is created. Currently you should do this sanity check based on the date of birth of the user but are working on a more robust solution. If the DoB exists but doesn't match then you should not allow the link to be made and inform the user we do not think the accounts match and to get in touch with customer service.
Error handling
When authorization request returns an error response, we display the message on our webpage. The user may also see a link back to your application, with error
and error_description
parameters in the url instead of code
.
Sign up new users via API
If the user doesn't already have a TransferWise account then you can create one for them. The sign up with registration code feature lets you create new users directly via an API call, without the need to redirect new users to the TransferWise authorization page. This way new users can complete everything without ever leaving your banking app, making a very streamlined flow.
We can provide this option to banks where we can create a trusted reliance model on your KYC processes. Please discuss this option with the team supporting your integration.
Existing TransferWise users will always need to be redirected to authorization page flow, you can detect this at the point you attempt to create the user based ont he API response.
Note that these new users have to accept TransferWise Terms and Conditions as part of their sign up process nevertheless. See endpoint Terms and conditions.
Get user tokens
When using the first option to (get user authorization for existing accounts ) then this step is to generate user-level tokens so you can call API endpoints on behalf of the user who authorized your banking app. You do this using the access code that was returned to you as a query string parameter in the redirect_uri you provided us.
Example Request:
curl \
-u '[your-api-client-id]:[your-api-client-secret]' \
-d 'grant_type=authorization_code' \
-d 'client_id=[your-api-client-id]' \
-d 'code=[code-from-redirect-uri]' \
-d 'redirect_uri=https://www.yourbank.com' \
'https://api.sandbox.transferwise.tech/oauth/token'
You will be returned an access token and a refresh token.
Example Response:
{
"access_token":"ba8k9935-62f2-475a-60d8-6g45377b4062",
"token_type":"bearer",
"refresh_token":"a235uu9c-9azu-4o28-a1kn-e15500o151cx",
"expires_in": 43199,
"scope":"transfers"
}
For calling API endpoints you need to provide the user's access_token
in the request's HTTP header in the format Authorization: Bearer <access_token>
.
Access tokens are short lived for security reasons, they are only valid for 12 hours by default. When they expire you need to use the refresh_token
to generate a new access_token.
This means you have to securely store the user's refresh_token
in order to generate a new access_token
each time they use your TransferWise integration, or you poll for updated data,
Request
POST https://api.sandbox.transferwise.tech/oauth/token
Use Basic Authentication with your api-client-id/api-client-secret as username/pwd.
Field | Description | Format |
---|---|---|
grant_type | "authorization_code" | Text |
client_id | your api_client_id | Text |
code | Code provided to you upon redirect back from authorization flow. See step Get user authorization. | Text |
redirect_uri | Redirect page associated with your api client credentials | Text |
Response
Field | Description | Format |
---|---|---|
access_token | Access token to be used when calling API endpoints on behalf of user. Valid for 12 hours. | uuid |
token_type | "bearer" | Text |
refresh_token | Refresh token which you need to use in order to request new access_token. The lifetime of refresh tokens is 10 years. | uuid |
expires_in | Expiry time in seconds | Integer |
scope | "transfers" | Text |
Refresh user access token
Example Request:
curl \
'https://api.sandbox.transferwise.tech/oauth/token' \
-u '[your-api-client-id]:[your-api-client-secret]' \
-d 'grant_type=refresh_token' \
-d 'refresh_token=[user's refresh token]'
Example Response:
{
"access_token":"be69d566-971e-4e15-9648-85a486195863",
"token_type":"bearer",
"refresh_token":"1d0ec7b9-b569-426d-a18d-8dead5b6a3cc",
"expires_in":43199,
"scope":"transfers"
}
Access tokens are valid for 12 hours, so upon expiry you need to use refresh_token to generate new access_token.
In order to maintain an uninterrupted connection, you can request a new access token whenever it’s close to expiring. There is no need to wait for the actual expiration to happen first.
Request
POST https://api.sandbox.transferwise.tech/oauth/token
Use Basic Authentication with your api-client-id/api-client-secret as username/pwd.
Field | Description | Format |
---|---|---|
grant_type | "refresh_token" | Text |
refresh_token | User's refresh_token obtained in Get user tokens step. | uuid |
Response
Field | Description | Format |
---|---|---|
access_token | Access token to be used when calling API endpoints on behalf of user. Valid for 12 hours. | uuid |
token_type | "bearer" | Text |
refresh_token | Refresh token which you need to use in order to request new access_token once the existing one expires | uuid |
expires_in | Expiry time in seconds | Integer |
scope | "transfers" | Text |
Token Expiry
It is possible that a user's refresh token will become invalid. This could happen for a number of reasons, for example:
- The user revokes access for your application to their account.
- The user enables enhanced security on their TransferWise account.
- TransferWise revoke tokens due to a security breach of your client secret.
Due to this possibility your application should handle a failing refresh token scenario - to do this depends on how you originally gained access to the user.
1. An existing user granted your application access to the account
If you were granted access by an existing user then you should send the user through the same flow as you initially did to generate tokens described in get user authorization for existing accounts.
2. Your application created the user
In the case you created the user using the sign up new users via API flow then the mechanism for regenerating tokens is dependent on whether the user you created has "reclaimed" their TransferWise account and used our website or apps directly.
If the user has not reclaimed their account then the original registrationCode
you generated should still be able to generate new tokens for the user. Because of this you should store this code alongside the created user ID in your database at the point of user generation.
If the previously stored token fails with an error code 400 and error:
{
"error": "invalid_grant",
"error_description": "Invalid user credentials."
}
In this case you can assume the user has reclaimed the account and push them through the get user authorization for existing accounts flow.
Create personal user profile
When you first get access to a user's TransferWise user account you cannot predict if they already have submitted their profile data or not.
The User Profiles.List endpoint will give you data for both personal and business profiles, if they exist. This makes it easy to figure out if a user has already set up this data with TransferWise or not. If the user already has a personal profile set up, then you can skip this creation step.
If you are using the sign up new users via API feature then you absolutely need to create personal profile for the user, however it is possible you will also need to do it when getting access to an existing user account.
There are three steps to creating a new personal user profile:
1) Create personal user profile – general data. This includes customer name, date of birth, and phone number.
2) Open update window. Open the update window for the profile updates.
3) Create personal user profile – address data. Add address information to the personal user profile.
4) Close update window. Close the update window for the profile updates.
Create business user profile
A personal profile has to be created first. You can’t create a business user profile without a personal profile.
Creating a business profile is similar to how you created a personal profile. There are four steps:
1) Create business user profile – general data. This includes business name, type and other information.
2) Open update window. Open the update window for the profile updates.
3) Create business user profile – address data. Add address information to the business user profile.
4) Create business user profile - director data. Add business director information to the business user profile.
5) Create business user profile - UBO data. Add ultimate business owner information to the business user profile.
6) Close update window. Close the update window for the profile updates.
Create quote
Please look at Create quote under Full API Reference.
You need to set quote type as "REGULAR".
Create or select recipient account
Please look at Create recipient account under Full API Reference for information on the calls to create recipients.
It is also recommended that you use the GET accounts
endpoint to load the user's previously used recipients and allow them to select from them in your user interface. This allows them to only have to create a recipient once and then re-use it in future, plus it allows existing TransferWise users to use their familiar users from our platform.
When returning this list please filter out any recipient of type SwiftCode
, unfortunately API limitations mean these cannot be used in bank integrations.
You should store a cached copy of the recipients that are used or created by users of your app such that you can load that data again quickly to show in your app, for example a transfer tracking screen might show recipient data.
Please note, when creating a new transfer always reload the full list of recipients over our API as cannot be certain the recipients you store a copy of have not been deleted in the meantime.
Create transfer
Please look at Create transfer under Full API Reference.
Fund transfer
Once you have successfully created a transfer via the TransferWise API you should debit the exact source amount from your customer's bank account and send the funds to TransferWise’s local bank account via domestic payment. You should send the amount provided in the quote object you created in the first step of the process. The details of this bank account will be shared with you by the TransferWise team helping your integration.
In order for us to link this incoming domestic payment with a corresponding transfer order, we need you to use specific text in the "payment reference" field.
Calling endpoint Get pay-in methods with quoteId returns you the correct reference text. e.g. quote-1456477 P5472304
. We currently drive this behaviour using the second part of this string, starting with P, you should use a regular expression to extract this string to send as the reference, e.g. .*(P\d+)
, taking the second group.
Track transfer status
Please look at Track transfer status under TransferWise Payouts Guide.
Get updated transfer delivery time estimate
Please look at Get transfer delivery time under TransferWise Payouts Guide.
Updating personal profile
When user data changes the personal profile information must be updated.
1) Open update window. Open the update window for profile updates.
2) Update personal profile - general data. Update the personal profile data.
3) Close update window. Close the update window for profile updates.
Updating business profile
When business data changes the business profile information must be updated.
1) Open update window. Open the update window for profile updates.
2) Update business profile - general data. Update the business profile data.
3) Update business profile - directors data. Update directors information in the business user profile.
3) Update business profile - UBO data. Update ultimate business owners information in the business user profile.
4) Close update window. Close the update window for profile updates.
Edge case handling
This section discusses some edge cases that you should test and handle before going live with your integration.
Email address considerations
Due to how getting access to user accounts works the TransferWise platform relies on user email addresses matching between the bank and ourselves. At the point the bank attempts to create a user we check and see if an account already exists for that email address, if so we return a 409 response and the client application forwards the user to login to TransferWise to do the OAuth grant flow.
This works well when the email addresses match in the first place and aren't updated on either side after the link is established. Of course, this is not always going to be the case so we must consider what happens in either eventuality.
Non-matching email addresses
If a user already has a TransferWise account and you create a user for the same person under a different email address they could end up with a duplicate user account under the second email address. Currently we monitor this behaviour for abuse but we are working on a more robust user creation solution to prevent this occurring.
Email Change
It is possible to change a user’s email address both at TransferWise and potentially also on the bank platform. These flows can cause complications with the integration.
Email changed at TransferWise
If a user changes their email address all tokens to the user account are revoked. In this case the bank will receive a 400 when attempting to generate an access_token and as such should follow the same process as described in the token expiry section above and start the sign up flow from the beginning.
In this case, if the user has changed their email address at TransferWise, it is possible the user will end up with a new TransferWise account using their old email address still held by the bank, or they might link their bank account to a different already existing TransferWise account under the old email address.
Email changed at the bank
In this case the tokens will remain valid for the TransferWise account, however, depending on how the user originally linked the account, different things can happen when/if that token expires.
If the bank created the account originally they will be unable to generate tokens using the registration_code they have as the endpoint requires the email address which will now no longer match. To mitigate this it is recommended that the bank store the email that was originally used for sign up alongside the registration code and use this rather than the most up to date email address they store for the user.
If the token expires for a user not created by the bank and the user has a new email address at the bank then they can be pushed through the sign up flow with this new email address and either have a new account created or link an existing against the new email, as described in token expiry.
The result of many of these flows is that the user may end up with more than one TransferWise account, which is undesirable. Currently we monitor this behaviour for abuse but we are working on a more robust user creation scenario to prevent this occurring.
Email change mitigation
The result of these eventualities are that over time a user of the bank could be linked to more than one TransferWise account and so therefore you will need to be defensive when requesting older user data as the request may fail because we forbid one user to access other user's data. We recommend to keep a local copy of your user's transfer data and update it asynchronously such that older transfers remain accessible to the user in the case where it can no longer be accessed. You should also make sure to handle these failing calls gracefully and continue to process transfers that can be accessed over the API.
In the event a user is not happy at losing access to their older data or having two accounts is confusing then we can manually update the email addresses to match for the two accounts they want.
Going live checklist
1. Make your integration bulletproof
- Implement basic retry mechanism to handle potential failures or network interruptions
- Implement duplicate prevention mechanism to avoid duplicate payments. Verify that UUID is uniquely generated for each individual payment and its value is kept same in case of retrying.
- Implement basic logging to help out in debugging and problem solving, if needed.
- Check that you can handle all possible transfer states during polling of transfer info.
- Handle the potential issues described in edge case handling.
- Required data fields for user profile addresses, recipients, and transfers vary for different currencies. Please explore Recipient Accounts.Requirements, Transfers.Requirements and Addresses.Requirements.
2. Set up security for LIVE environment
- Make sure you have received and successfully decrypted Live API credentials, storing them securely.
- Ensure access tokens and refresh tokens are also stored securely and only exposed to authorized persons.
- Make sure your server has TLS version 1.2 or higher.
- Implement a mechanism to obtain new access token upon expiration.
3. Do some testing in LIVE
- Launch LIVE integration to a limited set of your customers and test all currency routes you will offer end-to-end.
- We recommend launching a limited set of currencies initially to limit the scope of potential issues, please seek guidance from the TransferWise team.
- Test successful flow and bounce back flow (where funds cannot be delivered).
- All set. Switch it on.
4. Sign up for API status notifications.
Affiliates Integration Guide
API access
Once you become our affiliate we will send you TransferWise API access credentials: api_client_id & api_client_secret. You can then use these as username and password with Basic Authentication method.
There are two endpoints Exchange Rates.List and Get Temporary Quote which you can call with this authentication method.
TEST and LIVE environments
- Sandbox API is located at https://api.sandbox.transferwise.tech
- LIVE API is located at https://api.transferwise.com
Get current exchange rates
Example Request (Basic authentication):
curl -X GET "https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD" \
--user <your api client_id>:<your api client_secret>
Example Response:
[
{
"rate": 1.166,
"source": "EUR",
"target": "USD",
"time": "2018-08-31T10:43:31+0000"
}
]
GET https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD
TransferWise updates exchange rates in nearly real-time – at least once per minute. This allows you to track and see the current mid-market exchange rate for any currency route.
See more at Exchange Rates.List
Get exchange rate history
Example Request (Basic authentication):
curl -X GET "https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD&from=2018-08-15T00:00:00&to=2018-08-30T23:59:59&group=day" \
--user <your api client_id>:<your api client_secret>
Example Response:
[
{
"rate": 1.166,
"source": "EUR",
"target": "USD",
"time": "2018-08-15T00:00:00+0000"
},
{
"rate": 1.168,
"source": "EUR",
"target": "USD",
"time": "2018-06-30T00:00:00+0000"
}
...
]
GET https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD&from=2018-08-15T00:00:00&to=2018-08-30T23:59:59&group=day
We expose up to 30 days exchange rate history via our API. This helps you to build an analysis page to show trends and implement an alerting system for your users.
See more at Exchange Rates.List
Get pricing and speed
Example Request (Basic authentication):
curl -X GET https://api.sandbox.transferwise.tech/v1/quotes?source=EUR&target=GBP&rateType=FIXED&targetAmount=600 \
--user <your api client_id>:<your api client_secret>
Example Response:
{
"source": "EUR",
"target": "GBP",
"sourceAmount": 663.84,
"targetAmount": 600.00,
"type": "REGULAR",
"rate": 0.9073,
"createdTime": "2018-08-27T14:35:44.553Z",
"createdByUserId": 0,
"rateType": "FIXED",
"deliveryEstimate": "2018-08-27T14:35:44.496Z",
"fee": 2.34,
"allowedProfileTypes": [
"PERSONAL",
"BUSINESS"
],
"guaranteedTargetAmount": false,
"ofSourceAmount": true
}
GET https://api.sandbox.transferwise.tech/v1/quotes?source=EUR&target=GBP&rateType=FIXED&targetAmount=600
Is currency route supported?
If we don't support a route then this endpoint will respond with an error code "error.route.not.supported".
How much does a transfer cost?
The TransferWise fee is included in the response.
How long does my transfer take?
Estimated delivery time is included in the response. This can vary quite a lot for different currency routes. For example transfers often only take a few hours from EUR to GBP, while sending money from USD can take 1-2 business days. This endpoint allows you to find out the estimated delivery time for each currency route.
See more at Get Temporary Quote
Connected Apps Guide
This guide described how your application can request TransferWise customers to grant access to their account.
Note that asking TransferWise users to copy-paste their Transferwise API tokens directly into your application is a violation of our security policy. So please only use proper OAuth authorization flow as described below.
API access
TransferWise uses standard OAuth 2.0 protocol for authentication and authorization.
Once our partnership begins, we’ll send you API access credentials for the sandbox environment consisting of a Client ID and a Client Secret. The credentials are needed to complete the authorisation_code grant type of OAuth 2.0 through which the customer will allow your application to be able to act on their behalf. We also need redirect_url from your technical team so that we can limit our callbacks to only that URL, this is URL that we will forward users to after successfully granting your application access to their TransferWise account. Specifying this explicitly makes the integration more secure. This article about OAuth 2.0 framework is a great way to refresh your knowledge about the protocol itself.
SANDBOX and LIVE environments
- Sandbox API is located at https://api.sandbox.transferwise.tech
- LIVE API is located at https://api.transferwise.com
Get user authorization
At a high level there are three steps to gaining access to an existing TransferWise account.
- Your app redirects the user to TransferWise authorization webpage, which prompts customers to login.
- The user logs in to TransferWise.
- The user agrees to provide access, the TransferWise authorization page then redirects user back to your preconfigured url, including a code you can use to geneate user tokens. e.g.
https://www.yourapp.com/?code=[CODE]
These steps are explained in more detail below.
1. Your application redirects user to TransferWise authorization webpage
Your website or app opens the following url in the user's browser.
Sandbox:
https://sandbox.transferwise.tech/oauth/authorize/?client_id={clientId}&redirect_uri={redirectUri}
Live:
https://transferwise.com/oauth/authorize/?client_id={clientId}&redirect_uri={redirectUri}
List of available parameters:
Parameter | Description |
---|---|
client_id (required) | The client ID you received from us. |
redirect_uri (required) | The preconfigured URL in your application where users will be sent after authorization. |
state | An opaque value, used for security purposes. If this parameter is set in the request, then it is returned to the application as part of the redirect_uri. More about state parameter. |
On mobiles apps you should not use WebView
components to show the authorization page to the users because they are not secure and will not allow users to log in to TransferWise with Google, which is an option used by some of our users. Your app should instead open the device's full browser app.
2. The user logs in to TransferWise
Our usual log in screens are presented to the user if they are not already logged in on the browser being used. If enabled for a user they will also be prompted to go through our two-factor authentication procedure.
3. The user agrees to grant access and we forward them to your redirect_url
Once a user gives your application authorization to connect to TransferWise and access their data, the user is redirected back to your redirect_url with a generated code query string value. For example
https://www.yourapp.com/?code=[CODE]
Your website or service can then use this code to obtain the access token to act on behalf of the user account described in the get user tokens section.
If you are building your TransferWise integration as a native mobile phone app then the redirect URL should be able to handle returning the user to the correct place in the app.
Please note that provided [CODE]
expires within 30 minutes and is one time use only.
Error handling
When authorization request returns an error response, we display the message on our webpage. The user may also see a link back to your application, with error
and error_description
parameters in the url instead of code
.
Get user tokens
You can now use authorization code returned to you as a query string parameter to obtain user access and refresh tokens. So that you can make calls on behalf of TransferWise user.
Example Request:
curl \
-u '[your-api-client-id]:[your-api-client-secret]' \
-d 'grant_type=authorization_code' \
-d 'client_id=[your-api-client-id]' \
-d 'code=[code-from-redirect-uri]' \
-d 'redirect_uri=https://www.yourapp.com' \
'https://api.sandbox.transferwise.tech/oauth/token'
You will be returned an access token and a refresh token.
Example Response:
{
"access_token":"ba8k9935-62f2-475a-60d8-6g45377b4062",
"token_type":"bearer",
"refresh_token":"a235uu9c-9azu-4o28-a1kn-e15500o151cx",
"expires_in": 43199,
"scope":"transfers"
}
For calling API endpoints you need to provide the user's access_token
in the request's HTTP header in the format Authorization: Bearer <access_token>
.
Access tokens are short lived for security reasons, they are only valid for 12 hours by default. When they expire you need to use the refresh_token
to generate a new access_token.
This means you have to securely store the user's refresh_token
in order to generate a new access_token
each time they use your TransferWise integration, or you poll for updated data,
Request
POST https://api.sandbox.transferwise.tech/oauth/token
Use Basic Authentication with your api-client-id/api-client-secret as username/pwd.
Field | Description | Format |
---|---|---|
grant_type | "authorization_code" | Text |
client_id | your api_client_id | Text |
code | Code provided to you upon redirect back from authorization flow. See step Get user authorization. | Text |
redirect_uri | Redirect page associated with your api client credentials | Text |
Response
Field | Description | Format |
---|---|---|
access_token | Access token to be used when calling API endpoints on behalf of user. Valid for 12 hours. | uuid |
token_type | "bearer" | Text |
refresh_token | Refresh token which you need to use in order to request new access_token. The lifetime of refresh tokens is 10 years. | uuid |
expires_in | Expiry time in seconds | Integer |
scope | "transfers" | Text |
Refresh user access token
Example Request:
curl \
'https://api.sandbox.transferwise.tech/oauth/token' \
-u '[your-api-client-id]:[your-api-client-secret]' \
-d 'grant_type=refresh_token' \
-d 'refresh_token=[user's refresh token]'
Example Response:
{
"access_token":"be69d566-971e-4e15-9648-85a486195863",
"token_type":"bearer",
"refresh_token":"1d0ec7b9-b569-426d-a18d-8dead5b6a3cc",
"expires_in":43199,
"scope":"transfers"
}
Access tokens are valid for 12 hours, so upon expiry you need to use refresh_token to generate new access_token.
In order to maintain an uninterrupted connection, you can request a new access token whenever it’s close to expiring. There is no need to wait for the actual expiration to happen first.
Request
POST https://api.sandbox.transferwise.tech/oauth/token
Use Basic Authentication with your api-client-id/api-client-secret as username/pwd.
Field | Description | Format |
---|---|---|
grant_type | "refresh_token" | Text |
refresh_token | User's refresh_token obtained in Get user tokens step. | uuid |
Response
Field | Description | Format |
---|---|---|
access_token | Access token to be used when calling API endpoints on behalf of user. Valid for 12 hours. | uuid |
token_type | "bearer" | Text |
refresh_token | Refresh token which you need to use in order to request new access_token once the existing one expires | uuid |
expires_in | Expiry time in seconds | Integer |
scope | "transfers" | Text |
Token Expiry
It is possible that a user's refresh token will become invalid. This could happen for a number of reasons, for example:
- The user revokes access for your application to their account.
- The user enables enhanced security on their TransferWise account.
- TransferWise revoke tokens due to a security breach of your client secret.
Due to this possibility your application should handle a failing refresh token scenario by sending the user through the authorization code flow as you initially did.
Open Banking API
Base Open Banking URL in Sandbox
https://openbanking.sandbox.transferwise.tech
Base Open Banking URL in Production
https://openbanking.transferwise.com
The TransferWise Open Banking API is a collection of RESTful APIs that enable Third Party Providers (TPPs) to access account information, initiate payments and confirm availability of funds on behalf of TransferWise customers. The API implementation follows the Open Banking UK standard, and TransferWise is a registered member of the Open Banking Directory.
Through this API you can either query account information, if you're an Account Information Service Provider (AISP), initiate payments, if you're a Payment Initiation Service Provider (PISP), or confirm the availability of funds, if you're a Card Based Payment Instrument Issuer (CBPII). We are currently supporting version 3.1.1 of the Open Banking API.
Prerequisites
Well-Known Open Banking URL
https://sandbox.transferwise.tech/openbanking/.well-known/openid-configuration
There's a couple of things you should be aware of in order to connect to the TransferWise Open Banking API:
- Being a registered TPP under the Open Banking Directory will ease the integration process.
- We are using mutualTLS as the means for authentication. Moreover, the
CN
of your client certificate is expected to match theclientId
under which you are registered. - You need to register your client, before you'll be able to call any of the APIs. Check out the Sandbox Access first.
For a detailed description of requirements and supported algorithms please check out the Well-Known Open Banking URL.
Sandbox Access
We highly recommend that you get started with connecting to our sandbox first, before moving on to production. To get started with the registration process drop us an email to openbanking@transferwise.com.
Open Banking Directory
If you're a registered TPP in the Open Banking Directory and you are using Signing and Transport certificates issued by Open Banking. At the moment we accept both the old style OB Transport and OB Signing, as well as the eIDAS-like OBWAC and OBSeal certificates. You can easily onboard by providing either of the following things:
- You can generate and send us a Software Statement Assertion (SSA) from the Open Banking Directory.
- Alternatively, you can also just send us your Open Banking Organization ID together with the Software Statement ID that you wish to use.
In either case, please make sure to have your list of Redirect Uri-s correctly configured in your Software Statement, otherwise you'll not be able to go through the whole flow.
eIDAS Certificates
In case you're using an eIDAS certificates instead of the ones issued by the Open Banking Directory just contact us at openbanking@transferwise.com to see how we can move forward.
Sandbox Test User
You can sign up for a test user account here https://sandbox.transferwise.tech/register. The 2FA code used for any subsequent logins to the sandbox will alway be 111111
.
You'll be asked to set up a developer account by filling in your profile information. Once this is done, you'll see that your newly created profile comes with a couple of test accounts opened and some test funds in them.
You do NOT need to create an API Token via the web interface in case you're intention is to use this test user for the Open Banking flow.
Sandbox Test Flow
After you've successfully applied for the Sandbox Access and you've set up a Sandbox Test User you are ready to test the Open Banking flow. For the purpose of this test flow let's assume that your TPP is an AISP and it's registered with the following details
Client ID | Redirect URI | Authorized Scopes |
---|---|---|
ob-dummy-tpp | https://ob-dummy-tpp/redirect | accounts |
1. Create an Access Token
Example Token Request
curl -X POST \
https://openbanking.sandbox.transferwise.tech/open-banking/auth/token \
--cacert CA.pem --cert client.pem --key client.key \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&scope=accounts'
Example Response
{
"access_token": "abcd1234-abcd-1234-abcd-abcdef123456",
"token_type": "bearer",
"expires_in": 6000,
"scope": "accounts openbanking"
}
As a first step you'll need to request an access token from the Token Endpoint.
Request
POST https://openbanking.sandbox.transferwise.tech/open-banking/auth/token
Field | Description | Format |
---|---|---|
grant_type | OAuth Grant Type | client_credentials |
scope | The requested scopes | Space separated list |
You must include the requested scope in your token request. As an AISP your requested scope will be accounts
.
Response
Field | Description | Format |
---|---|---|
access_token | The access token | Text |
expires_in | Expiration time in seconds | Long |
scope | The scopes you have been given access to | Text |
2. Create a Consent
Example Create Consent Request
curl -X POST \
https://openbanking.sandbox.transferwise.tech/open-banking/v3.1/aisp/account-access-consents \
--cacert CA.pem --cert client.pem --key client.key \
-H 'Authorization: Bearer abcd1234-abcd-1234-abcd-abcdef123456' \
-H 'Content-Type: application/json' \
-d '{
"Data": {
"Permissions": [
"ReadAccountsBasic", "ReadTransactionsBasic", "ReadTransactionsDebits"
]}}'
Example Response
{
"Data": {
"Status": "AwaitingAuthorisation",
"ConsentId": "123"
}
}
Request
POST https://openbanking.sandbox.transferwise.tech/open-banking/v3.1/aisp/account-access-consents
Using the access-token
returned from Creating an Access Token you can create a new consent object. Use the authorization header:
Authorization: Bearer xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
The payload of this request will look different depending on whether you're an AISP, PISP or CBPII. For an AISP you'll need to specify a set of permissions describing the access that you wish to gain on behalf of the end user.
Permissions
For AISPs the list of supported permissions is:
- ReadAccountsBasic
- ReadAccountsDetail
- ReadBalances
- ReadTransactionsBasic
- ReadTransactionsCredits
- ReadTransactionsDebits
- ReadTransactionsDetail
Response
The response will be JSON data reflecting the newly created consent object. There are two important return values to highlight here.
Data.Status
will containAwaitingAuthorisation
because this consent has not been authorized by the user yet.Data.ConsentId
will contain the unique identifier assigned to your consent object. Save this, as you'll need it later.
3. User Flow
Example Authorization Request
https://sandbox.transferwise.tech/openbanking/authorize?
response_type=code%20id_token&
redirect_uri=https://ob-dummy-tpp/redirect&
scope=openid%20accounts&
client_id=ob-dummy-tpp&
state=state123&
nonce=nonce123&
request=eyJ0...sYjmjJg
Example Authorization JWT Request
HEADER
{
"kid" : "er84c2cYa6dAe57BV3278Pf",
"alg" : "PS256",
"typ" : "JWT"
}
PAYLOAD
{
"scope" : "openid accounts",
"response_type" : "code id_token",
"sub" : "user_id",
"claims" : {
"id_token" : {
"openbanking_intent_id" : {
"essential" : true,
"value" : "123"
},
"acr" : {
"values" : [
"urn:openbanking:psd2:sca",
"urn:openbanking:psd2:ca"
],
"essential" : true
}
},
"userinfo" : {
"openbanking_intent_id" : {
"value" : "123",
"essential" : true
}
}
},
"iss" : "ob-dummy-tpp",
"client_id" : "ob-dummy-tpp",
"aud" : "https://openbanking.sandbox.transferwise.tech",
"exp" : 2499287201,
"iat" : 2499283601,
"max_age" : 86400,
"redirect_uri" : "https://ob-dummy-tpp/redirect"
}
At the moment we are only supporting the browser redirect flow (Hybrid Flow) for authorizing the created consent.
The customer journey will start from the TPPs website from where a user action will trigger a redirect to the TransferWise Open Banking Authorization Endpoint
GET https://sandbox.transferwise.tech/openbanking/authorize
Parameter | Required | Description |
---|---|---|
response_type | Mandatory | code id_token |
redirect_uri | Mandatory | One of the pre-registered redirect URIs |
scope | Mandatory | Must include openid plus any requested scope |
client_id | Mandatory | Pre-registered clientId of the TPP |
request | Mandatory | JWT Request Object |
state | Optional | If present, it must also be present in the JWT |
nonce | Optional | If present, it must also be present in the JWT |
You can take a look at the example JWT request object on the right. Please note that:
- Every request parameter sent in the URL must also be present in the signed JWT.
- The
aud
claim should be correctly filled ashttps://openbanking.sandbox.transferwise.tech
- The
openbanking_intent_id
must be filled with a validConsentId
issued to the TPP. - The JWT must be signed with a valid signing certificate.
Once the TPP redirects the user browser to the Authorization Endpoint the following things will happen in order:
- User Login (use the username and password from the Test User Registration)
- Pass 2FA challenge (User the code
111111
in sandbox) - Select profile you wish to give access to (Business or Personal)
- Review and Authorize Consent
- Redirect back to TPP
As part of the last step, the user browser is redirected to the TPP with the following parameters
Parameter | Required | Description |
---|---|---|
code | Mandatory | The authorization_code issued as the request of the request |
id_token | Mandatory | Signed JWT containing details about the authorization |
state | Optional | In case it was provided with the request |
Note that in case the authorization request fails either because of a validation error on the request, or because the enduser drops off, we still redirect the user browser to the TPP with an error response of the following format:
Field | Description | Format |
---|---|---|
error | Error code according to RFC6749 | Text |
error_description | Detailed explanation of error | Text |
4. Exchange Authorization Code for Access Token
Example Token Request
curl -X POST \
https://openbanking.sandbox.transferwise.tech/open-banking/auth/token \
--cacert CA.pem --cert client.pem --key client.key \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&redirect_uri=https%3A%2F%2Fob-dummy-tpp%2Fredirect&code=abcdauthcode'
Example Response
{
"access_token": "zzzzzzzz-1111-2222-3333-zzzzzzzzzzzz",
"token_type": "bearer",
"refresh_token": "refreshr-efre-shre-fres-hrefreshrefr",
"expires_in": 6000,
"scope": "accounts consent-id:123 openbanking openid"
}
Once you get the authorization code
after the browser redirect, you'll have to call the Token Endpoint to exchange this for a valid access token.
Request
POST https://openbanking.sandbox.transferwise.tech/open-banking/auth/token
Field | Description | Format |
---|---|---|
grant_type | OAuth Grant Type | authorization_code |
redirect_uri | Pre-registered redirect Uri | URI |
code | Authorization Code | Text |
Response
Field | Description | Format |
---|---|---|
access_token | The access token | Text |
expires_in | Expiration time in seconds | Long |
scope | The scopes you have been given access to | Text |
refresh_token | Refresh Token for refreshing access token | Text |
5. Query the API
Example Request
curl -X GET \
https://openbanking.sandbox.transferwise.tech/open-banking/v3.1/aisp/accounts \
--cacert CA.pem --cert client.pem --key client.key \
-H 'Authorization: Bearer zzzzzzzz-1111-2222-3333-zzzzzzzzzzzz' \
Example Response
{
"Data": {
"Account": [
{
"AccountId": "504",
"Currency": "GBP",
"AccountType": "Personal",
"AccountSubType": "EMoney",
"Account": [
{
"SchemeName": "UK.OBIE.SortCodeAccountNumber",
"Identification": "230xxx1000xxxx",
"Name": "John Smith (GBP)"
}
],
"Servicer": {
"SchemeName": "UK.OBIE.BICFI",
"Identification": "TRWIGB22"
}
}
]
}
}
With the access-token
from Authorization Code Flow used in the Authorization header, you'll be able to query the data endpoints.
Authorization: Bearer xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx
As an AISP you'll be able to call the following endpoints
Accounts
GET https://openbanking.sandbox.transferwise.tech/open-banking/v3.1/aisp/accounts
GET https://openbanking.sandbox.transferwise.tech/open-banking/v3.1/aisp/accounts/{id}
Balances
GET https://openbanking.sandbox.transferwise.tech/open-banking/v3.1/aisp/accounts/{id}/balances
Transactions
GET https://openbanking.sandbox.transferwise.tech/open-banking/v3.1/aisp/accounts/{id}/transactions
Contact Us
Having issues while calling our API endpoints? Check our API status at https://status.transferwise.com/ If you would like to receive status change notifications, feel free to sign up here.
Have a technical question about API? Send email to api@transferwise.com
Making lots of payments? We have a dedicated team to talk to you. https://transferwise.com/gb/business/contact
Have a question about how TransferWise works?
Search TransferWise Help Centre. https://transferwise.com/help
Want more information about your payments?
Lookup TransferWise Support Centre details. https://transferwise.com/contact
Full API Reference
Addresses
Create
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/addresses \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"details": {
"country": "EE",
"firstLine": "Narva mnt 5-1",
"postCode": "10113",
"city": "Tallinn"
}
}'
Example Response:
{
"id": 236532,
"profile": <your profile id>,
"details": {
"country": "EE",
"firstLine": "Narva mnt 5-1",
"postCode": "10113",
"city": "Tallinn",
"state": "",
"occupation": null
}
}
Adds address info to user profile.
List of required fields are slightly different for different countries.
For example state field is required for US, CA, BR and AU addresses but not for other countries.
Please look at Addresses.Requirements to figure out which fields are required to create addresses in specific country.
Request
POST https://api.sandbox.transferwise.tech/v1/addresses
Field | Description | Format |
---|---|---|
profile | User profile id. | Integer |
details.country | 2 digit ISO country code. | Text |
details.firstLine | Address line: street, house, apartment. | Text |
details.postCode | Zip code | Text |
details.city | City name | Text |
details.state | State code. Required if country is US, CA, AU, BR | Text |
details.occupation | User occupation. Required for US, CA, JP | Text |
Response
Field | Description | Format |
---|---|---|
id | Address id | Integer |
profile | User profile id. | Integer |
details.country | 2 digit ISO country code. | Text |
details.firstLine | Address line: street, house, apartment. | Text |
details.postCode | Zip code | Text |
details.city | City name | Text |
details.state | State code. Required if country is US, CA, AU, BR | Text |
details.occupation | User occupation. Required for US, CA, JP | Text |
Get By Id
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/addresses/{addressId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": 236532,
"profile": <your profile id>,
"details": {
"country": "EE",
"firstLine": "Narva mnt 5-1",
"postCode": "10113",
"city": "Tallinn",
"state": "",
"occupation": null
}
}
Get address info by id.
Request
GET https://api.sandbox.transferwise.tech/v1/addresses/{addressId}
List
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/addresses?profile={profileId} \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": 7099091,
"profile": <your profile id>,
"details": {
"country": "EE",
"firstLine": "Veerenni 29",
"postCode": "12991",
"city": "Tallinn",
"state": null,
"occupation": null
}
}
]
List of addresses belonging to user profile.
Request
GET https://api.sandbox.transferwise.tech/v1/addresses?profile={profileId}
Requirements
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/address-requirements \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"type": "address",
"fields": [
{
"name": "Country",
"group": [
{
"key": "country",
"type": "select",
"refreshRequirementsOnChange": true,
"required": true,
"displayFormat": null,
"example": "Germany",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": [
{
"key": "AX",
"name": "Åland Islands"
},
...
{
"key": "ZM",
"name": "Zambia"
}
]
}
]
},
{
"name": "City",
"group": [
{
"key": "city",
"type": "text",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "London",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": null
}
]
},
{
"name": "Postal code",
"group": [
{
"key": "postCode",
"type": "text",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "10025",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": null
}
]
}
...
]
}
]
Request
GET https://api.sandbox.transferwise.tech/v1/address-requirements
POST https://api.sandbox.transferwise.tech/v1/address-requirements
GET and POST address-requirements endpoints help you to figure out which fields are required to create a valid address for different countries. You could even build a dynamic user interface on top of these endpoints. This is a step-by-step guide on how these endpoints work.
Call GET /v1/address-requirements to get list of fields you need to fill with values in "details" section for creating a valid address. Response contains 4 required top level fields:
- country (select field with list of values)
- city (text field)
- postCode (text field)
- firstLine (text field)
Analyze the list of fields. Because refreshRequirementsOnChange=true for field 'country' then this indicates that there are additional fields required depending on the selected value.
Call POST /v1/address-requirements with selected country value to expose sub fields.
For example posting {"details": {"country" : "US"}} will also add "state" to list of fields.
But posting {"details": {"country" : "GB"}} will not.If you choose "US" as country you will notice that "state" field also has refreshRequirementsOnChange=true. This means you would need to make another POST call to /v1/address-requirements with a specific state value.
For example posting {"details": { "country" : "US", "state": "AZ" }} will also add "occupation" to list of fields.
But posting {"details": { "country" : "US", "state": "AL" }} will not.So once you get to the point where you have provided values for all fields which have refreshRequirementsOnChange=true then you have complete set of fields to compose a valid request to create an address object. For example this is a valid request to create address in US Arizona:
POST /v1/addresses:
{ "profile" : your-profile-id,
"details": {
"country" : "US",
"state": "AZ",
"city": "Phoenix",
"postCode": "10025",
"firstLine": "50 Sunflower Ave.",
"occupation": "software engineer"
} }
Response
Field | Description | Format |
---|---|---|
type | "address" | Text |
fields[n].name | Field description | Text |
fields[n].group[n].key | Key is name of the field you should include in the JSON | Text |
fields[n].group[n].type | Display type of field (e.g. text, select, etc) | Text |
fields[n].group[n].refreshRequirementsOnChange | Tells you whether you should call POST address-requirements once the field value is set to discover required lower level fields. | Boolean |
fields[n].group[n].required | Indicates if the field is mandatory or not | Boolean |
fields[n].group[n].displayFormat | Display format pattern. | Text |
fields[n].group[n].example | Example value. | Text |
fields[n].group[n].minLength | Min valid length of field value. | Integer |
fields[n].group[n].maxLength | Max valid length of field value. | Integer |
fields[n].group[n].validationRegexp | Regexp validation pattern. | Text |
fields[n].group[n].validationAsync | Validator URL and parameter name you should use when submitting the value for validation | Text |
fields[n].group[n].valuesAllowed[n].key | List of allowed values. Value key | Text |
fields[n].group[n].valuesAllowed[n].name | List of allowed values. Value name. | Text |
Borderless Accounts
Get Account Balance
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/borderless-accounts?profileId={profileId} \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": 64,
"profileId": <your profile id>,
"recipientId": 13828530,
"creationTime": "2018-03-14T12:31:15.678Z",
"modificationTime": "2018-03-19T15:19:42.111Z",
"active": true,
"eligible": true,
"balances": [
{
"balanceType": "AVAILABLE",
"currency": "GBP",
"amount": {
"value": 10999859,
"currency": "GBP"
},
"reservedAmount": {
"value": 0,
"currency": "GBP"
},
"bankDetails": null
},
{
"balanceType": "AVAILABLE",
"currency": "EUR",
"amount": {
"value": 9945236.2,
"currency": "EUR"
},
"reservedAmount": {
"value": 0,
"currency": "EUR"
},
"bankDetails": {
"id": 90,
"currency": "EUR",
"bankCode": "DEKTDE7GXXX",
"accountNumber": "DE51 7001 1110 6050 1008 91",
"swift": "DEKTDE7GXXX",
"iban": "DE51 7001 1110 6050 0008 91",
"bankName": "Handelsbank",
"accountHolderName": "Oliver Wilson",
"bankAddress": {
"addressFirstLine": "Elsenheimer Str. 41",
"postCode": "80687",
"city": "München",
"country": "Germany",
"stateCode": null
}
}
}
]
}
]
Get available balances for all activated currencies in your borderless account.
Request
GET https://api.sandbox.transferwise.tech/v1/borderless-accounts?profileId={profileId}
Use profile id obtained earlier to make this call.
Response
Field | Description | Format |
---|---|---|
id | Borderless account id | Integer |
profileId | Personal or business profile id | Integer |
recipientId | Recipient id you can use for borderless topup transfer | Integer |
creationTime | Date when balance account was opened | Timestamp |
modificationTime | Date when balance account setup was modified. | Timestamp |
active | Is borderless account active or inactive | Boolean |
eligible | Ignore | Boolean |
balances[n].balanceType | AVAILABLE | Text |
balances[n].currency | Currency code | Text |
balances[n].amount.value | Available balance in specified currency | Decimal |
balances[n].amount.currency | Currency code | Text |
balances[n].reservedAmount.value | Reserved amount from your balance | Decimal |
balances[n].reservedAmount.currency | Reserved amount currency code | Text |
balances[n].bankDetails | Bank account details assigned to your borderless account. Available for EUR, GBP, USD, AUD, NZD | Group |
balances[n].bankDetails.id | Bank account details id | Integer |
balances[n].bankDetails.currency | Bank account currency | Text |
balances[n].bankDetails.bankCode | Bank account code | Text |
balances[n].bankDetails.accountNumber | Bank account number | Text |
balances[n].bankDetails.swift | Bank account swift code | Text |
balances[n].bankDetails.iban | Bank account iban | Text |
balances[n].bankDetails.bankName | Bank name | |
balances[n].bankDetails.accountHolderName | Bank account holder name | Text |
balances[n].bankDetails.bankAddress.addressFirstLine | Bank address street and house | Text |
balances[n].bankDetails.bankAddress.postCode | Bank address zip code | Text |
balances[n].bankDetails.bankAddress.city | Bank address city | Text |
balances[n].bankDetails.bankAddress.country | Bank address country | Text |
balances[n].bankDetails.bankAddress.stateCode | Bank address state code | Text |
Get Account Statement
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v3/profiles/{profileId}/borderless-accounts/{borderlessAccountId}/statement.json?
currency=EUR&intervalStart=2018-03-01T00:00:00.000Z&intervalEnd=2018-03-15T23:59:59.999Z \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"accountHolder": {
"type": "PERSONAL",
"address": {
"addressFirstLine": "Veerenni 24",
"city": "Tallinn",
"postCode": "12112",
"stateCode": "",
"countryName": "Estonia"
},
"firstName": "Oliver",
"lastName": "Wilson"
},
"issuer": {
"name": "TransferWise Ltd.",
"firstLine": "56 Shoreditch High Street",
"city": "London",
"postCode": "E1 6JJ",
"stateCode": "",
"country": "United Kingdom"
},
"bankDetails": null,
"transactions": [
{
"type": "DEBIT",
"date": "2018-04-30T08:47:05.832Z",
"amount": {
"value": -7.76,
"currency": "EUR"
},
"totalFees": {
"value": 0.04,
"currency": "EUR"
},
"details": {
"type": "CARD",
"description": "Card transaction of 6.80 GBP issued by Tfl.gov.uk/cp TFL TRAVEL CH",
"amount": {
"value": 6.8,
"currency": "GBP"
},
"category": "Transportation Suburban and Loca",
"merchant": {
"name": "Tfl.gov.uk/cp",
"firstLine": null,
"postCode": "SW1H 0TL ",
"city": "TFL TRAVEL CH",
"state": " ",
"country": "GB",
"category": "Transportation Suburban and Loca"
}
},
"exchangeDetails": {
"forAmount": {
"value": 6.8,
"currency": "GBP"
},
"rate": null
},
"runningBalance": {
"value": 16.01,
"currency": "EUR"
},
"referenceNumber": "CARD-249281"
},
{
"type": "CREDIT",
"date": "2018-04-17T07:47:00.227Z",
"amount": {
"value": 200,
"currency": "EUR"
},
"totalFees": {
"value": 0,
"currency": "EUR"
},
"details": {
"type": "DEPOSIT",
"description": "Received money from HEIN LAURI with reference SVWZ+topup card",
"senderName": "HEIN LAURI",
"senderAccount": "EE76 1700 0170 0049 6704 ",
"paymentReference": "SVWZ+topup card"
},
"exchangeDetails": null,
"runningBalance": {
"value": 207.69,
"currency": "EUR"
},
"referenceNumber": "TRANSFER-34188888"
},
{
"type": "CREDIT",
"date": "2018-04-10T05:58:34.681Z",
"amount": {
"value": 9.94,
"currency": "EUR"
},
"totalFees": {
"value": 0,
"currency": "EUR"
},
"details": {
"type": "CONVERSION",
"description": "Converted 8.69 GBP to 9.94 EUR",
"sourceAmount": {
"value": 8.69,
"currency": "GBP"
},
"targetAmount": {
"value": 9.94,
"currency": "EUR"
},
"fee": {
"value": 0.03,
"currency": "GBP"
},
"rate": 1.147806
},
"exchangeDetails": null,
"runningBalance": {
"value": 9.94,
"currency": "EUR"
},
"referenceNumber": "CONVERSION-1511237"
}
],
"endOfStatementBalance": {
"value": 9.94,
"currency": "EUR"
},
"query": {
"intervalStart": "2018-03-01T00:00:00Z",
"intervalEnd": "2018-04-30T23:59:59.999Z",
"currency": "EUR",
"accountId": 64
}
}
Get borderless account statement for one currency and for specified time range. The period between intervalStart and intervalEnd cannot exceed 469 days (around 1 year 3 month).
Request
GET https://api.sandbox.transferwise.tech/v3/profiles/{profileId}/borderless-accounts/{borderlessAccountId}/statement.json?
currency=EUR&intervalStart=2018-03-01T00:00:00.000Z&intervalEnd=2018-03-15T23:59:59.999Z
All query parameters are mandatory.
Field | Description | Format |
---|---|---|
borderlessAccountId | Your borderlessAccountId is included in Get Account Balance response as field "id". | Integer |
currency | Currency code | Text |
intervalStart | Statement start time in UTC time | Zulu time. Don't forget the 'Z' at the end. |
intervalEnd | Statement start time in UTC time | Zulu time. Don't forget the 'Z' at the end. |
Note that you can also download statements in PDF and CSV formats if you replace statement.json with statement.csv or statement.pdf respectively in the above URL.
Response
Field | Description | Format |
---|---|---|
accountHolder.type | Account holder type: PERSONAL or BUSINESS | Text |
accountHolder.address.addressFirstLine | Account holder address street | Text |
accountHolder.address.city | Account holder address city | Text |
accountHolder.address.postCode | Account holder address zipc ode | Text |
accountHolder.address.stateCode | Account holder address state | Text |
accountHolder.address.countryName | Account holder address country | Text |
accountHolder.firstName | Account holder first name | Text |
accountHolder.lastName | Account holder last name | Text |
issuer.name | Account issuer name | Text |
issuer.firstLine | Account issuer address street | Text |
issuer.city | Account issuer address city | Text |
issuer.postCode | Account issuer address zip code | Text |
issuer.stateCode | Account issuer address state | Text |
issuer.country | Account issuer address country | Text |
bankDetails | Your borderless account bank details | Group |
transactions[n].type | DEBIT or CREDIT | Text |
transactions[n].date | Time of transaction | Zulu time |
transactions[n].amount.value | Transaction amount | Decimal |
transactions[n].amount.currency | Transaction currency code | Text |
transactions[n].totalFees.value | Transaction fee amount | Decimal |
transactions[n].totalFees.currency | Transaction fee currency code | Text |
transactions[n].details.type | CARD, CONVERSION, DEPOSIT, TRANSFER, MONEY_ADDED | Text |
transactions[n].details.description | Human readable explanation about the transaction | Text |
transactions[n].details.amount.value | Amount in original currency (card transactions abroad) | Decimal |
transactions[n].details.amount.currency | Original currency code | Text |
transactions[n].details.sourceAmount.value | Amount in source currency (conversions) | Decimal |
transactions[n].details.sourceAmount.currency | Source currency code | Text |
transactions[n].details.targetAmount.value | Amount in target currency (conversions) | Decimal |
transactions[n].details.targetAmount.currency | Target currency code | Text |
transactions[n].details.fee.value | Conversion fee amount | Decimal |
transactions[n].details.fee.currency | Conversion fee currency code | Text |
transactions[n].details.rate | Conversion exchange rate | Decimal |
transactions[n].details.senderName | Deposit sender name | Text |
transactions[n].details.senderAccount | Deposit sender bank account details | Text |
transactions[n].details.paymentReference | Deposit payment reference text | Text |
transactions[n].details.category | Card transaction category | Text |
transactions[n].details.merchant.name | Card transaction merchant name | Text |
transactions[n].details.merchant.firstLine | Merchant address street | Text |
transactions[n].details.merchant.postCode | Merchant address zipcode | Text |
transactions[n].details.merchant.city | Merchant address city | Text |
transactions[n].details.merchant.state | Merchant address state | Text |
transactions[n].details.merchant.country | Merchant address country | Text |
transactions[n].details.merchant.category | Merchant category | Text |
transactions[n].exchangeDetails.forAmount.value | Currency exchange amount | Decimal |
transactions[n].exchangeDetails.forAmount.currency | Currency code | Text |
transactions[n].exchangeDetails.rate | Exchange rate | Decimal |
transactions[n].runningBalance.value | Running balance after the transaction | Decimal |
transactions[n].runningBalance.currency | Running balance currency code | Text |
transactions[n].referenceNumber | TransferWise assigned unique transaction reference number | Text |
endOfStatementBalance.value | Closing balance for specified time period | Decimal |
endOfStatementBalance.currency | Closing balance currency code | Text |
query.intervalStart | Query parameter repeated | Zulu time |
query.intervalEnd | Query parameter repeated | Zulu time |
query.currency | Query parameter repeated | Text |
query.accountId | Query parameter repeated | Integer |
Convert Currencies
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/borderless-accounts/{borderlessAccountId}/conversions \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-H "X-idempotence-uuid: <your generated uuid> \
-d '{
"quoteId": <conversion quote id>
}'
Example Response:
{
"id": <conversion transaction id>,
"type": "CONVERSION",
"state": "COMPLETED",
"balancesAfter": [
{
"value": 10000594.71,
"currency": "GBP"
},
{
"value": 9998887.01,
"currency": "EUR"
}
],
"creationTime": "2017-11-21T09:55:49.275Z",
"steps": [
{
"id": 369588,
"type": "CONVERSION",
"creationTime": "2017-11-21T09:55:49.276Z",
"balancesAfter": [
{
"value": 9998887.01,
"currency": "EUR"
},
{
"value": 10000594.71,
"currency": "GBP"
}
],
"channelName": null,
"channelReferenceId": null,
"tracingReferenceCode": null,
"sourceAmount": {
"value": 113.48,
"currency": "EUR"
},
"targetAmount": {
"value": 100,
"currency": "GBP"
},
"fee": {
"value": 0.56,
"currency": "EUR"
},
"rate": 0.88558
}
],
"sourceAmount": {
"value": 113.48,
"currency": "EUR"
},
"targetAmount": {
"value": 100,
"currency": "GBP"
},
"rate": 0.88558,
"feeAmounts": [
{
"value": 0.56,
"currency": "EUR"
}
]
}
Convert funds between your borderless account currencies. Quote which is used in this call must have type "BALANCE_CONVERSION".
Note that this call needs an extra field in header called "X-idempotence-uuid".
Request
POST https://api.sandbox.transferwise.tech/v1/borderless-accounts/{borderlessAccountId}/conversions
Field | Description | Format |
---|---|---|
borderlessAccountId | Your borderlessAccountId is included in Get Account Balance response as field "id". | Integer |
X-idempotence-uuid | Unique identifier assinged by you. Used for idempotency check purposes. Should your call fail for technical reasons then you can use the same value again for making retry call. | UUID |
Get Available Currencies
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/borderless-accounts/balance-currencies \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"code": "EUR",
"hasBankDetails": true,
"payInAllowed": true,
"sampleBankDetails": null
},
{
"code": "GBP",
"hasBankDetails": true,
"payInAllowed": true,
"sampleBankDetails": null
},
{
"code": "USD",
"hasBankDetails": false,
"payInAllowed": true,
"sampleBankDetails": null
},
...
{
"code": "UAH",
"hasBankDetails": false,
"payInAllowed": false,
"sampleBankDetails": null
},
{
"code": "ARS",
"hasBankDetails": false,
"payInAllowed": false,
"sampleBankDetails": null
},
{
"code": "NPR",
"hasBankDetails": false,
"payInAllowed": false,
"sampleBankDetails": null
}
]
Get list of currencies that your can hold in your borderless account. Also shows which currencies have the option to get bank account details.
Request
GET https://api.sandbox.transferwise.tech/v1/borderless-accounts/balance-currencies
Response
Field | Description | Format |
---|---|---|
code | Currency code | Text |
hasBankDetails | Does currency have bank details opening option | Boolean |
payInAllowed | Can you send this currency to your borderless account | Boolean |
sampleBankDetails |
Get Currency Pairs
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/currency-pairs \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"sourceCurrencies": [
{
"currencyCode": "GBP",
"maxInvoiceAmount": 1000000,
"targetCurrencies": [
{
"currencyCode": "EUR",
"minInvoiceAmount": 1,
"fixedTargetPaymentAllowed": true
},
{
"currencyCode": "INR",
"minInvoiceAmount": 1,
"fixedTargetPaymentAllowed": true
},
{
"currencyCode": "USD",
"minInvoiceAmount": 1,
"fixedTargetPaymentAllowed": true
},
...
{
"currencyCode": "VND",
"minInvoiceAmount": 1,
"fixedTargetPaymentAllowed": true
},
{
"currencyCode": "ZAR",
"minInvoiceAmount": 1,
"fixedTargetPaymentAllowed": true
}
],
"totalTargetCurrencies": 47
}
],
"total": 19
}
Get list of allowed currency pairs that your can setup your transfers.
Request
GET https://api.sandbox.transferwise.tech/v1/currency-pairs
Response
Field | Description | Format |
---|---|---|
sourceCurrencies.currencyCode | Source currency code | Text |
sourceCurrencies.maxInvoiceAmount | Maximum allowed transfer amount in source currency | Decimal |
targetCurrencies.currencyCode | Target currency code | Text |
targetCurrencies.minInvoiceAmount | Minimum allowed transfer amount in source currency for this pair. | Decimal |
targetCurrencies.fixedTargetPaymentAllowed | Can you setup fixed rate payments or not. | Boolean |
Comparison
Request comparison quotes
Example Request:
curl -X GET https://api.transferwise.com/v3/comparisons/?sourceCurrency=GBP&targetCurrency=EUR&sendAmount=10000
Example Response:
{
"sourceCurrency": "GBP",
"targetCurrency": "EUR",
"sourceCountry": null,
"targetCountry": null,
"providerCountry": null,
"providerType": null,
"sendAmount": 10000.0,
"providers": [
{
"id": 39,
"alias": "transferwise",
"name": "TransferWise",
"logo": "https://dq8dwmysp7hk1.cloudfront.net/logos/transferwise.svg",
"type": "moneyTransferProvider",
"partner": false,
"quotes": [
{
"rate": 1.15989,
"fee": 37.12,
"receivedAmount": 11555.84,
"dateCollected": "2019-10-22T14:36:43Z",
"sourceCountry": null,
"targetCountry": null,
"markup": 0.0,
"deliveryEstimation": {
"duration": {
"min": "PT20H8M16.305111S",
"max": "PT20H8M16.305111S"
},
"providerGivesEstimate": true
}
}
]
},
{
"id": 1,
"alias": "barclays",
"name": "Barclays",
"logo": "https://dq8dwmysp7hk1.cloudfront.net/logos/barclays.svg",
"type": "bank",
"partner": false,
"quotes": [
{
"rate": 1.12792426,
"fee": 0.0,
"receivedAmount": 11279.24,
"dateCollected": "2019-10-22T14:00:04Z",
"sourceCountry": "GB",
"targetCountry": "ES",
"markup": 2.75592858,
"deliveryEstimation": {
"duration": {
"min": "PT24H",
"max": "PT24H"
},
"providerGivesEstimate": true
}
},
...
{
"rate": 1.12792426,
"fee": 0.0,
"receivedAmount": 11279.24,
"dateCollected": "2019-10-22T14:00:04Z",
"sourceCountry": "GB",
"targetCountry": "FI",
"markup": 2.75592858,
"deliveryEstimation": {
"duration": {
"min": "PT24H",
"max": "PT24H"
},
"providerGivesEstimate": true
},
...
}
...
]
}
]
}
The comparison API can be used to request price and speed information about various money transfer providers. This includes not only TransferWise but other providers in the market.
Price Estimation
The quotes (price / speed) provided by this API are based off of real quotes collected from 3rd party websites. We collect both the advertised exchange rate and fee for each provider for various amounts. When a comparison is requested we calculate the markup % on the collected exchange rate on the mid-market rate at the time of collection, we then apply this markup % on the current mid-market rate to provide a realistic estimate of what each provider offers. We collect data for all providers ~ once per hour to ensure we provide as accurate and up to date information as possible.
Note: Today, we only provide estimations for FX transactions with a Bank Transfer pay-in / pay-out option. This is important to stress as many providers offer significantly different fees / exchange rates when used debit / credit card, cash etc.
For more details on the data collection process please see the following page:
https://transferwise.com/gb/compare/disclaimer
If you have questions or suspect any data to be inaccurate or incomplete please contact us at:
Delivery Estimation
Similar to price, we collect speed data for most (if not all) providers which we have price information for. Many providers display speed estimates to their customers in a number of different ways.
Some examples:
- "The transfer should be complete within 2-5 days"
- "The money should arrive in your account within 48 hours"
- "Should arrive by 26th Aug"
- "Could take up to 4 working days"
The below API intends to model these in a consistent format by providing a min / max range for all delivery estimations. An estimate that states "up to X" will have "max" set to a duration but "min" as null, a "from X" will have "min" set to a duration and "max" as null. Finally for those providers who offer a specific, point in time estimation (like TransferWise), the API will surface a duration where min/max are equal.
Quotes structure
In order to provide the most flexible and accurate data for clients, we surface a denormalised list of quotes per provider where each quote represents a unique collection of comparison "dimensions".
A single given provider may expose multiple quotes for the same currency route. The most common example is where a provider offers different pricing for one country vs another country which uses the same currency. e.g:
Provider X:
- GBP EUR 1000 [GB -> ES] fee: 10, rate: 1.5
- GBP EUR 1000 [GB -> DE] fee: 8, rate: 1.5
- GBP EUR 1000 [GB -> FR] fee: 10, rate: 1.35
The same principle applies for speed. I.e a provider may have different speed estimates for different target countries and hence we expose these as discrete quotes - where a quote is a unique combination of route / country / speed / price factors.
A client may choose to reduce this set of quotes down to a single or several quotes in order to display a relevant quote to a given user. An example where we take the cheapest quote for a given currency route (and also surface the target country) can be seen at the below link:
https://transferwise.com/gb/compare/?sourceCurrency=GBP&targetCurrency=EUR&sendAmount=1000
Request
GET https://api.transferwise.com/v3/comparisons/?sourceCurrency=GBP&targetCurrency=EUR&sendAmount=10000
Field (Query Param) | Description | Format |
---|---|---|
sourceCurrency | ISO 4217 source currency code | Text |
targetCurrency | ISO 4217 target currency code | Text |
sendAmount | Amount in source currency | Decimal |
sourceCountry | (Optional) Filter by source country (ISO 3166-1 Alpha-2 code) | Text |
targetCountry | (Optional) Filter by target country (ISO 3166-1 Alpha-2 code) | Text |
providerType | (Optional) Filter by provider type | One of "bank","moneyTransferProvider" |
Response
Field | Description | Format |
---|---|---|
id | Provider id | Integer |
alias | Provider alias (lowercase slug name) | Text |
name | Provider name (presentational / formal name) | Text |
logo | URL pointing to provider logo (default svg format) | Text |
type | Provider type | Text |
partner | Whether a partner of TransferWise or not | Boolean |
quotes | An array of estimated quotes per provider | Array |
quotes.rate | The live estimated exchange for the provider for this quote | Timestamp |
quotes.fee | The estimated fee for the provider for this quote | Integer |
quotes.receivedAmount | The total estimated receive amount for the provider for this quote | Integer |
quotes.dateCollected | The date of collection for the original quote | Text |
quotes.sourceCountry | Source country (ISO 3166-1 Alpha-2 code) | Timestamp |
quotes.targetCountry | Target country (ISO 3166-1 Alpha-2 code) | Decimal |
quotes.deliveryEstimation | Delivery estimation details - i.e a speed estimate | Object |
quotes.deliveryEstimation.duration | Duration range | Object |
quotes.deliveryEstimation.duration.min | Minimum quoted time for transaction delivery | ISO 8601 duration format |
quotes.deliveryEstimation.duration.max | Maximum quoted time for transaction delivery | ISO 8601 duration format |
quotes.deliveryEstimation.providerGivesEstimate | Whether a provider publicly surfaces / exposes a speed estimate | Boolean |
Exchange Rates
List
Example Request (Bearer token):
curl -X GET "https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD" \
-H "Authorization: Bearer <your api token>"
Example Request (Basic authentication):
curl -X GET "https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD" \
--user <your api client_id>:<your api client_secret>
Example Response:
[
{
"rate": 1.166,
"source": "EUR",
"target": "USD",
"time": "2018-08-31T10:43:31+0000"
}
]
GET https://api.sandbox.transferwise.tech/v1/rates
Fetch latest exchange rates of all currencies.
GET https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD
Fetch latest exchange rate of one currency pair.
GET https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD&time=2019-02-13T14:53:01
Fetch exchange rate of specific historical timestamp.
GET https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD&from=2019-02-13T14:53:01&to=2019-03-13T14:53:01&group=day
Fetch exchange rate history over period of time with daily interval.
GET https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD&from=2019-02-13T14:53:01&to=2019-03-13T14:53:01&group=hour
Fetch exchange rate history over period of time with hourly interval.
GET https://api.sandbox.transferwise.tech/v1/rates?source=EUR&target=USD&from=2019-02-13T14:53:01&to=2019-03-13T14:53:01&group=minute
Fetch exchange rate history over period of time with 10 minute interval.
Request
Note that this endpoint supports two types of authentication: Bearer token and Basic authentication (client_id/client_secret).
Field | Description | Format |
---|---|---|
source | Source(send) currency code. | Text |
target | Target(receive) currency code. | Text |
time | Timestamp to get historic exchange rate. | Timestamp |
from | Period start date/time to get exchange rate history. | Timestamp or Date |
to | Period end date/time to get exchange rate history. | Timestamp or Date |
group | Interval: day hour minute | Text |
Response
List of exchange rate values which meet your query criteria.
Field | Description | Format |
---|---|---|
rate | Exchange rate value. | Decimal |
source | Source(send) currency code | Text |
target | Target(receive) currency code | Text |
time | Timestamp for exchange rate. | Timestamp |
Additional notes about date/time formatting used above
The request/response field(s) below support both Timestamp (combined date and time) and Date (date only) formats:
Field | Sample |
---|---|
from | 2019-03-13T14:53:01 or 2019-03-13 |
to | 2019-03-13T14:53:01+0100 or 2019-03-13+0100 |
The request/response field(s) below support only Timestamp (combined date and time):
Field | Sample |
---|---|
time | 2019-03-13T14:53:01 or 2019-03-13T14:53:01+0100 |
Timezone offset is supported but optional.
Quotes
Create
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/quotes \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"source": "EUR",
"target": "GBP",
"rateType": "FIXED",
"targetAmount": 600,
"type": "BALANCE_PAYOUT"
}'
Example Response:
{
"id": <quoteId>,
"source": "EUR",
"target": "GBP",
"sourceAmount": 663.84,
"targetAmount": 600.00,
"type": "BALANCE_PAYOUT",
"rate": 0.9073,
"createdTime": "2018-08-27T14:35:44.553Z",
"createdByUserId": <your user id>,
"profile": <your profile id>,
"rateType": "FIXED",
"deliveryEstimate": "2018-08-27T14:35:44.496Z",
"fee": 2.34,
"allowedProfileTypes": [
"PERSONAL",
"BUSINESS"
],
"guaranteedTargetAmount": false,
"ofSourceAmount": true
}
Quote can be used to create a transfer within 30 minutes. You need quoteId as an input to create a transfer.
Quote locks current mid-market exchange rate that will be used for your transfer.
Quote also calculates transfer fee and estimates delivery time.
Request
POST https://api.sandbox.transferwise.tech/v1/quotes
Field | Description | Format |
---|---|---|
profile | Personal or business profile id | Text |
source | Source(send) currency code | Text |
target | Target(receive) currency code | Text |
rateType | Always use constant 'FIXED' | Text |
targetAmount | Amount in target currency | Decimal |
sourceAmount | Amount in source currency. Either sourceAmount or targetAmount is required, never both. |
Decimal |
type | 'BALANCE_PAYOUT' for payments funded from borderless account 'BALANCE_CONVERSION' for conversion between balances 'REGULAR' for payments funded via bank transfers |
Text |
Response
Field | Description | Format |
---|---|---|
id | quoteId | Integer |
source | Source(send) currency code | Text |
target | Target(receive) currency code | Text |
sourceAmount | Amount in source currency | Decimal |
targetAmount | Amount in target currency | Decimal |
type | Quote type | Text |
rate | Exchange rate value | Decimal |
createdTime | Quote created timestamp | Timestamp |
createdByUserId | Your used id | Integer |
profile | Personal or business profile id | Integer |
rateType | Always 'FIXED' | Text |
deliveryEstimate | Estimated timestamp when recipient would receive funds, assuming transfer will be created now. | Timestamp |
fee | TransferWise fee in source currency for this payment (deducted from source amount). | Decimal |
allowedProfileTypes | PERSONAL, BUSINESS or both. Specifies which legal entities can use this quote. There are few currency routes are where we dont support business customers yet. | Text |
guaranteedTargetAmount | Not relevant for fixed rate quotes. Please ignore. | Boolean |
ofSourceAmount | Not relevant for fixed rate quotes. Please ignore. | Boolean |
Get By Id
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/quotes/{quoteId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": <quoteId>,
"source": "EUR",
"target": "GBP",
"sourceAmount": 663.84,
"targetAmount": 600.00,
"type": "BALANCE_PAYOUT",
"rate": 0.9073,
"createdTime": "2018-08-27T14:35:44.553Z",
"createdByUserId": <your user id>,
"profile": <your profile id>,
"rateType": "FIXED",
"deliveryEstimate": "2018-08-27T14:35:44.496Z",
"fee": 2.34,
"allowedProfileTypes": [
"PERSONAL",
"BUSINESS"
],
"guaranteedTargetAmount": false,
"ofSourceAmount": true
}
Get quote info by id.
Request
GET https://api.sandbox.transferwise.tech/v1/quotes/{quoteId}
Get Pay-in Methods
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/quotes/{quoteId}/pay-in-methods \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"type": "transfer",
"details": {
"payInReference": "quote-113300 P304205"
}
}
]
Get text that you should use in the "payment reference" field when sending funds via local bank transfer to TransferWise to fund your payment request. Reference text includes "P-REF" number of user which we need in order to automatically link funds.
Request
GET https://api.sandbox.transferwise.tech/v1/quotes/{quoteId}/pay-in-methods
Response
Field | Description | Format |
---|---|---|
type | Currently always 'transfer' meaning only pay-in option is via bank transfer. | Text |
details.payInReference | Reference text to be used when sending your bank transfer to TransferWise. | Text |
Get Temporary Quote
Example Request (Bearer token):
curl -X GET https://api.sandbox.transferwise.tech/v1/quotes?source=EUR&target=GBP&rateType=FIXED&targetAmount=600 \
-H "Authorization: Bearer <your api token>"
Example Request (Basic authentication):
curl -X GET https://api.sandbox.transferwise.tech/v1/quotes?source=EUR&target=GBP&rateType=FIXED&targetAmount=600 \
--user <your api client_id>:<your api client_secret>
Example Response:
{
"source": "EUR",
"target": "GBP",
"sourceAmount": 663.84,
"targetAmount": 600.00,
"type": "REGULAR",
"rate": 0.9073,
"createdTime": "2018-08-27T14:35:44.553Z",
"createdByUserId": 0,
"rateType": "FIXED",
"deliveryEstimate": "2018-08-27T14:35:44.496Z",
"fee": 2.34,
"allowedProfileTypes": [
"PERSONAL",
"BUSINESS"
],
"guaranteedTargetAmount": false,
"ofSourceAmount": true
}
GET https://api.sandbox.transferwise.tech/v1/quotes?source=SEK&target=USD&sourceAmount=1000&rateType=FIXED
Get temporary quote for sending 1000 SEK to USD
GET https://api.sandbox.transferwise.tech/v1/quotes?source=SEK&target=USD&targetAmount=1000&rateType=FIXED
Get temporary quote for sending SEK to 1000 USD
Request
Note that this endpoint supports two types of authentication: Bearer token and Basic authentication (client_id/client_secret).
GET https://api.sandbox.transferwise.tech/v1/quotes
Field | Description | Format |
---|---|---|
source | Source(send) currency code | Text |
target | Target(receive) currency code | Text |
rateType | Always use constant 'FIXED' | Text |
targetAmount | Amount in target currency | Decimal |
sourceAmount | Amount in source currency. Either sourceAmount or targetAmount is required, never both. |
Decimal |
Response
Same as Create, but without "id" field since temporary quote is not stored and cannot be used for creating transfer. Temporary quote is not associated with any user, it is anonymous.
Recipient Accounts
Create
Example Request (Create GBP recipient):
curl -X POST https://api.sandbox.transferwise.tech/v1/accounts \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"currency": "GBP",
"type": "sort_code",
"profile": <your profile id>,
"ownedByCustomer": true,
"accountHolderName": "Ann Johnson",
"details": {
"legalType": "PRIVATE",
"sortCode": "231470",
"accountNumber": "28821822"
}
}'
Example Response (Create GBP recipient):
{
"id": 13967081,
"business": null,
"profile": <your profile id>,
"accountHolderName": "Ann Johnson",
"currency": "GBP",
"country": "GB",
"type": "sort_code",
"details": {
"address": {
"country": null,
"countryCode": null,
"firstLine": null,
"postCode": null,
"city": null,
"state": null
},
"email": null,
"legalType": "PRIVATE",
"accountNumber": "28821822",
"sortCode": "231470",
"abartn": null,
"accountType": null,
"bankgiroNumber": null,
"ifscCode": null,
"bsbCode": null,
"institutionNumber": null,
"transitNumber": null,
"phoneNumber": null,
"bankCode": null,
"russiaRegion": null,
"routingNumber": null,
"branchCode": null,
"cpf": null,
"cardNumber": null,
"idType": null,
"idNumber": null,
"idCountryIso3": null,
"idValidFrom": null,
"idValidTo": null,
"clabe": null,
"swiftCode": null,
"dateOfBirth": null,
"clearingNumber": null,
"bankName": null,
"branchName": null,
"businessNumber": null,
"province": null,
"city": null,
"rut": null,
"token": null,
"cnpj": null,
"payinReference": null,
"pspReference": null,
"orderId": null,
"idDocumentType": null,
"idDocumentNumber": null,
"targetProfile": null,
"taxId": null,
"iban": null,
"bic": null,
"IBAN": null,
"BIC": null,
"interacAccount": null
},
"user": <your user ID>,
"active": true,
"ownedByCustomer": true
}
Recipient is a person or institution who is the ultimate beneficiary of your payment.
Recipient data includes three data blocks.
1) General Data
- Recipient full name
- Legal type (private/business)
- Currency
- Owned by customer
Owned by customer is a boolen to flag whether this recipient is the same entity (person or business) as the one sending the funds. i.e. A user sending money to thier own account in another country/currency. This can be used to separate these recipients in your UI.
2) Bank account data
There are many different variations of bank account details needed depending on recipient target currency. For example:
- GBP — sort code and account number
- BGN CHF, DKK, EUR, GEL, GBP, NOK, PKR, PLN, RON, SEK — IBAN
- USD — routing number, account number, account type
- INR — IFSC code, account number
- ...
3) Address data Recipient address data is required only if target currency is USD, PHP, THB or TRY, or if the source currency is USD or AUD.
- Country
- State (US, Canada, Brazil)
- City
- Address line
- Zip code
When creating recipient, the following general rules should be applied to "accountHolderName" field:
- Full names for personal recipients. They must include more than one name, and both first and last name must have more than one character.
- Business names must be in full, but can be just a single name. The full name cannot be just a single character but can be made up of a set of single characters. e.g. "A" is not permitted but "A 1" or "A1" is permitted.
- Digits are not allowed, except in business names.
These requirements may vary depending of recipient type.
A GBP example is provided here. You can find other currency examples below.
As you can see many of the fields are null
, in order to know which fields are required for which currency we expose the Recipients.Requirements endpoint.
Request
POST https://api.sandbox.transferwise.tech/v1/accounts
Field | Description | Format | Optional |
---|---|---|---|
currency | 3 character currency code | Text | false |
type | Recipient type | Text | false |
profile | Personal or business profile id | Integer | false |
accountHolderName | Recipient full name | Text | false |
ownedByCustomer | Whether this account is owned by the sending user | Text | true |
details | Currency specific fields | Object | false |
details.legalType | Recipient legal type: PRIVATE or BUSINESS | Text | false |
details.sortCode | Recipient bank sort code (GBP example) | Text | false |
details.accountNumber | Recipient bank account no (GBP example) | Text | false |
Response
Recipient account id is needed for creating transfers in step 3.
Field | Description | Format |
---|---|---|
id | accountId | Integer |
profile | Personal or business profile id | Integer |
acccountHolderName | Recipient full name | Text |
currency | 3 character country code | Text |
country | 2 character currency code | Text |
type | Recipient type | Text |
ownedByCustomer | Whether this account is owned by the sending user | Text |
details | Currency specific fields | Object |
details.legalType | Recipient legal type | Text |
details.sortCode | Recipient bank sort code (GBP example) | Text |
details.accountNumber | Recipient bank account no (GBP example) | Text |
Create Email Recipient
Example Request (Create email recipient):
curl -X POST https://api.sandbox.transferwise.tech/v1/accounts \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "Ann Johnson",
"currency": "EUR",
"type": "email",
"details": {
"email": "ann.johnson@gmail.com"
}
}'
Example Response (Lookup email recipient):
{
"id": 13967196,
"business": null,
"profile": <your profile id>,
"accountHolderName": "Ann Johnson",
"currency": "EUR",
"country": null,
"type": "email",
"details": {
"address": {
"country": null,
"countryCode": null,
"firstLine": null,
"postCode": null,
"city": null,
"state": null
},
"email": "ann.johnson@gmail.com",
"legalType": "PRIVATE",
"accountNumber": null,
"sortCode": null,
"abartn": null,
"accountType": null,
"bankgiroNumber": null,
"ifscCode": null,
"bsbCode": null,
"institutionNumber": null,
"transitNumber": null,
"phoneNumber": null,
"bankCode": null,
"russiaRegion": null,
"routingNumber": null,
"branchCode": null,
"cpf": null,
"cardNumber": null,
"idType": null,
"idNumber": null,
"idCountryIso3": null,
"idValidFrom": null,
"idValidTo": null,
"clabe": null,
"swiftCode": null,
"dateOfBirth": null,
"clearingNumber": null,
"bankName": null,
"branchName": null,
"businessNumber": null,
"province": null,
"city": null,
"rut": null,
"token": null,
"cnpj": null,
"payinReference": null,
"pspReference": null,
"orderId": null,
"idDocumentType": null,
"idDocumentNumber": null,
"targetProfile": null,
"taxId": null,
"iban": null,
"bic": null,
"IBAN": null,
"BIC": null,
"interacAccount": null
},
"user": <your user id>,
"active": true,
"ownedByCustomer": false
}
If you don't know recipient bank account details you can set up email recipient so that TransferWise will collect bank details directly from the recipient.
TransferWise will email your recipient with a link to collect their bank account details. Once your recipient provides bank account details securely to TransferWise we are able to complete your transfer.
Get By Id
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/accounts/{accountId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": 13967081,
"profile": <your profile id>,
"accountHolderName": "Ann Johnson",
"type": "sort_code",
"country": "GB",
"currency": "GBP",
"details": {
"address": {
"country": null,
"countryCode": null,
"firstLine": null,
"postCode": null,
"city": null,
"state": null
},
"email": null,
"legalType": "PRIVATE",
"accountNumber": "28821822",
"sortCode": "231470",
"abartn": null,
"accountType": null,
"bankgiroNumber": null,
"ifscCode": null,
"bsbCode": null,
"institutionNumber": null,
"transitNumber": null,
"phoneNumber": null,
"bankCode": null,
"russiaRegion": null,
"routingNumber": null,
"branchCode": null,
"cpf": null,
"cardNumber": null,
"idType": null,
"idNumber": null,
"idCountryIso3": null,
"idValidFrom": null,
"idValidTo": null,
"clabe": null,
"swiftCode": null,
"dateOfBirth": null,
"clearingNumber": null,
"bankName": null,
"branchName": null,
"businessNumber": null,
"province": null,
"city": null,
"rut": null,
"token": null,
"cnpj": null,
"payinReference": null,
"pspReference": null,
"orderId": null,
"idDocumentType": null,
"idDocumentNumber": null,
"targetProfile": null,
"taxId": null,
"iban": null,
"bic": null,
"IBAN": null,
"BIC": null,
"interacAccount": null
},
"user": <your user ID>,
"active": true,
"ownedByCustomer": false
}
Get recipient account info by id.
Request
GET https://api.sandbox.transferwise.tech/v1/accounts/{accountId}
List
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/accounts?profile=<profileId>¤cy=GBP \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": 13967081,
"profile": <your profile id>,
"accountHolderName": "Ann Johnson",
"type": "sort_code",
"country": "GB",
"currency": "GBP",
"details": {
"address": {
"country": null,
"countryCode": null,
"firstLine": null,
"postCode": null,
"city": null,
"state": null
},
"email": null,
"legalType": "PRIVATE",
"accountNumber": "28821822",
"sortCode": "231470",
"abartn": null,
"accountType": null,
"bankgiroNumber": null,
"ifscCode": null,
"bsbCode": null,
"institutionNumber": null,
"transitNumber": null,
"phoneNumber": null,
"bankCode": null,
"russiaRegion": null,
"routingNumber": null,
"branchCode": null,
"cpf": null,
"cardNumber": null,
"idType": null,
"idNumber": null,
"idCountryIso3": null,
"idValidFrom": null,
"idValidTo": null,
"clabe": null,
"swiftCode": null,
"dateOfBirth": null,
"clearingNumber": null,
"bankName": null,
"branchName": null,
"businessNumber": null,
"province": null,
"city": null,
"rut": null,
"token": null,
"cnpj": null,
"payinReference": null,
"pspReference": null,
"orderId": null,
"idDocumentType": null,
"idDocumentNumber": null,
"targetProfile": null,
"taxId": null,
"iban": null,
"bic": null,
"IBAN": null,
"BIC": null,
"interacAccount": null
},
"user": <your user ID>,
"active": true,
"ownedByCustomer": false
},
{
"id": 31273090,
"profile": <your profile id>,
"accountHolderName": "George Johnson",
"type": "sort_code",
"country": "GB",
"currency": "GBP",
"details": {
"address": {
"country": null,
"countryCode": null,
"firstLine": null,
"postCode": null,
"city": null,
"state": null
},
"email": null,
"legalType": "PRIVATE",
"accountNumber": "29912211",
"sortCode": "231470",
"abartn": null,
"accountType": null,
"bankgiroNumber": null,
"ifscCode": null,
"bsbCode": null,
"institutionNumber": null,
"transitNumber": null,
"phoneNumber": null,
"bankCode": null,
"russiaRegion": null,
"routingNumber": null,
"branchCode": null,
"cpf": null,
"cardNumber": null,
"idType": null,
"idNumber": null,
"idCountryIso3": null,
"idValidFrom": null,
"idValidTo": null,
"clabe": null,
"swiftCode": null,
"dateOfBirth": null,
"clearingNumber": null,
"bankName": null,
"branchName": null,
"businessNumber": null,
"province": null,
"city": null,
"rut": null,
"token": null,
"cnpj": null,
"payinReference": null,
"pspReference": null,
"orderId": null,
"idDocumentType": null,
"idDocumentNumber": null,
"targetProfile": null,
"taxId": null,
"iban": null,
"bic": null,
"IBAN": null,
"BIC": null,
"interacAccount": null
},
"user": <your user ID>,
"active": true,
"ownedByCustomer": true
}
]
Fetch a list of your recipient accounts. Use the currency
and profile
parameters to filter by currency and/or user profile Id.
This list does not currently support pagination, therefore if you have many recipient accounts defined in your business profile then please filter by currency to ensure a reasonable response time.
Request
GET https://api.sandbox.transferwise.tech/v1/accounts?profile=<profileId>¤cy=<currencyCode>
Both query parameters are optional.
Field | Description | Format |
---|---|---|
profileId | Personal or business profile id | Integer |
currency | Currency code | Text |
Delete
Example Request:
curl -X DELETE https://api.sandbox.transferwise.tech/v1/accounts/{accountId} \
-H "Authorization: Bearer <your api token>"
Deletes a recipient by changing its status to inactive. Only active recipients can be deleted and a recipient cannot be reactivated, however you can create a new recipient with the same details instead.
Response is empty if delete succeeds.
Requesting to delete recipient that is already inactive will return an http status 403 (forbidden).
Request
DELETE https://api.sandbox.transferwise.tech/v1/accounts/{accountId}
Requirements
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/quotes/{quoteId}/account-requirements \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"type": "aba",
"title": "Local bank account",
"fields": [
{
"name": "Recipient type",
"group": [
{
"key": "legalType",
"name": "Recipient type",
"type": "select",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": [
{
"key": "PRIVATE",
"name": "Person"
},
{
"key": "BUSINESS",
"name": "Business"
}
]
}
]
},
{
"name": "ACH routing number",
"group": [
{
"key": "abartn",
"name": "ACH routing number",
"type": "text",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "026009593",
"minLength": 9,
"maxLength": 9,
"validationRegexp": "^\\d{9}$",
"validationAsync": null,
"valuesAllowed": null
}
]
},
{
"name": "Account number",
"group": [
{
"key": "accountNumber",
"name": "Account number",
"type": "text",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "12345678",
"minLength": 4,
"maxLength": 17,
"validationRegexp": "^\\d{4,17}$",
"validationAsync": null,
"valuesAllowed": null
}
]
},
{
"name": "Account type",
"group": [
{
"key": "accountType",
"name": "Account type",
"type": "radio",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "CHECKING",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": [
{
"key": "CHECKING",
"name": "Checking"
},
{
"key": "SAVINGS",
"name": "Savings"
}
]
}
]
},
{
"name": "Country",
"group": [
{
"key": "address.country",
"name": "Country",
"type": "select",
"refreshRequirementsOnChange": true,
"required": true,
"displayFormat": null,
"example": "",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": [
{
"key": "AF",
"name": "Afghanistan"
},
{
"key": "AL",
"name": "Albania"
},
{
...
}
]
}
]
},
{
"name": "City",
"group": [
{
"key": "address.city",
"name": "City",
"type": "text",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": null
}
]
},
{
"name": "Address",
"group": [
{
"key": "address.firstLine",
"name": "Address",
"type": "text",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": null
}
]
},
{
"name": "Post Code",
"group": [
{
"key": "address.postCode",
"name": "Post Code",
"type": "text",
"refreshRequirementsOnChange": false,
"required": true,
"displayFormat": null,
"example": "",
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": null
}
]
}
]
},
Request
GET https://api.sandbox.transferwise.tech/v1/quotes/{quoteId}/account-requirements
POST https://api.sandbox.transferwise.tech/v1/quotes/{quoteId}/account-requirements
The GET
and POST
account-requirements endpoints help you to figure out which fields are required to create a valid recipient for different currencies.
You can use this data to build a dynamic user interface on top of these endpoints.
This is a step-by-step guide on how these endpoints work.
Using account requirements
1.First create a quote to specify currencies and transfer amounts. See Create.Quote.
2.Call GET /v1/quotes/{quoteId}/account-requirements
to get the list of fields you need to fill with values in the "details" section for creating a valid recipient account.
In order to create an "aba" recipient type you need these top level fields:
- legalType (PRIVATE / BUSINESS)
- abartn (ABA routing number)
- accountType (CHECKING / SAVINGS)
- address.country
- address.city
- address.postalCode
- address.firstLine
Some fields require multiple levels of fields in the details request, for example Country followed by State. This should be handled by the client based on the refreshRequirementsOnChange
field. In the example above 'address.country' has this field set to true, indicating that there are additional fields required depending on the selected value. To manage this you should create a request with all of the initially requested data and call the POST account-requirements
endpoint. You will be returned a response similar the previosuly returned data from GET account-requirements
but with additional fields.
3.For example, construct a recipient object with all top level fields and call POST /v1/quotes/{quoteId}/account-requirements with these value to expose sub fields.
For example posting US as country will also add "state" to list of fields.
{
"type": "aba",
"details": {
"legalType": "PRIVATE",
"abartn": "111000025",
"accountNumber": "12345678",
"accountType": "CHECKING",
"address": {
"country": "US"
}
}
}
However, posting GB as country will not add any new fields as GB addresses do not have this extra requirement.
{
"type": "aba",
"details": {
"legalType": "PRIVATE",
"abartn": "111000025",
"accountNumber": "12345678",
"accountType": "CHECKING",
"address": {
"country": "GB"
}
}
}
It is possible that any new fields retuened may also have refreshRequirementsOnChange
field set to true. Therefore you must keep iterating on the partially created details object until POST account-requirements
returns you no new fields that it previously didn't include in the response, you can do this by checking the size of the array returned.
4.Once you have built your full reciepient details object you can use it to create a reciepient.
For example this is a valid request to create a recipient with address in US Arizona:
POST /v1/accounts
:
{
"profile": your-profile-id,
"accountHolderName": "John Smith",
"currency": "USD",
"type": "aba",
"details": {
"legalType": "PRIVATE",
"abartn": "111000025",
"accountNumber": "12345678",
"accountType": "CHECKING",
"address": {
"country": "US",
"state": "AZ"
"city": "New York",
"postCode": "10025",
"firstLine": "45 Sunflower Ave"
}
}
}
We do not require the recipient's address for most receiving currencies and as such do not return these form elements by default. In some cases it may be desirable for you to collect this from users and store it as part of the recipient object in the TransferWise platform. If you wish to do this you can include the parameter &addressRequired=true
in your call to GET /v1/quotes/{quoteId}/account-requirements
, if this is present we will return address fields as part of the form.
Building a user interface
When requesting the form data from the account-requirements several the first level of the response defines different types of recipient you can create, the first thing to do is present the user a choice of which recipient type they wish to create, e.g. to GBP this could be local details or IBAN format. Each recipient type then has mutiple fields
describing the form elements required to be shown to collect information from the user. Each field will have a type
value, these tell you the field type that your front end needs to render to be able to collect the data. A number of field types are permitted, these are:
type | UI element |
---|---|
text | A free text box |
select | A selection box/dialog |
radio | A radio button choice between options |
date | A text box with a date picker |
Example data is also included in each field which should be shown to the user, along with a regex or min and mex length constraints that should be applied as field level validations. You can optionally implement the dynamic validation using the validationAsync
field, however these checks wil also be done when a completed recipient is submitted to POST /v1/accounts
.
Response
Field | Description | Format |
---|---|---|
type | "address" | Text |
fields[n].name | Field description | Text |
fields[n].group[n].key | Key is name of the field you should include in the JSON | Text |
fields[n].group[n].type | Display type of field (e.g. text, select, etc) | Text |
fields[n].group[n].refreshRequirementsOnChange | Tells you whether you should call POST account-requirements once the field value is set to discover required lower level fields. | Boolean |
fields[n].group[n].required | Indicates if the field is mandatory or not | Boolean |
fields[n].group[n].displayFormat | Display format pattern. | Text |
fields[n].group[n].example | Example value. | Text |
fields[n].group[n].minLength | Min valid length of field value. | Integer |
fields[n].group[n].maxLength | Max valid length of field value. | Integer |
fields[n].group[n].validationRegexp | Regexp validation pattern. | Text |
fields[n].group[n].validationAsync | Validator URL and parameter name you should use when submitting the value for validation | Text |
fields[n].group[n].valuesAllowed[n].key | List of allowed values. Value key | Text |
fields[n].group[n].valuesAllowed[n].name | List of allowed values. Value name. | Text |
Validate Recipient Fields
Example Request (Validate sort code (GBP):
curl -X GET https://api.sandbox.transferwise.tech/v1/validators/sort-code?sortCode=231470
Example Response (Validate sort code (GBP):
{
"validation": "success"
}
or
{
"errors": [
{
"code": "VALIDATION_NOT_SUCCESSFUL",
"message": "sortCode has not passed validation.",
"path": "sortCode",
"arguments": [
"2314701"
]
}
]
}
There are several validation URLs that make creating correct recipient accounts easier. These URLs are also included in fields provided by Recipient Accounts.Requirements endpoint.
GBP
Validate UK bank sort code
https://api.transferwise.com/v1/validators/sort-code?sortCode=231470
Validate UK bank account number
https://api.transferwise.com/v1/validators/sort-code-account-number?accountNumber=10000246
BGN CHF, DKK, EUR, GEL, GBP, NOK, PKR, PLN, RON, SEK
Validate IBAN
https://api.transferwise.com/v1/validators/iban?iban=EE867700771000187087
Validate BIC and IBAN
https://api.transferwise.com/v1/validators/bic?bic=LHVBEE22&iban=EE867700771000187087
USD
Validate ABA routing number
https://api.transferwise.com/v1/validators/abartn?abartn=011103093
Validate ABA bank account number
https://api.transferwise.com/v1/validators/aba-account-number?accountNumber=111000025
INR
Validate IFSC code
https://api.transferwise.com/v1/validators/ifsc-code?ifscCode=YESB0236041
Validate Indian bank account number
https://api.transferwise.com/v1/validators/indian-account-number?accountNumber=678911234567891
AUD
Validate BSB code
https://api.transferwise.com/v1/validators/bsb-code?bsbCode=112879
Validate Australian bank account number
https://api.transferwise.com/v1/validators/australian-account-number?accountNumber=123456789
CAD
Validate Canadian institution number
https://api.transferwise.com/v1/validators/canadian-institution-number?institutionNumber=006
Validate Canadian bank transit number
Validate Canadian bank account number
SEK Validate Bank Giro number
https://api.transferwise.com/v1/validators/bankgiro-number?bankgiroNumber=12345674
HUF
Validate Hungarian bank account number
PLN
Validate Polish bank account number
UAH
Validate Ukrainian bank account number
https://api.transferwise.com/v1/validators/privatbank-account-number?accountNumber=1234
Validate Ukrainian phone number
https://api.transferwise.com/v1/validators/privatbank-phone-number?phoneNumber=123456789
NZD
Validate New Zealand bank account number
AED
Validate United Arab Emirates BIC code
https://api.transferwise.com/v1/validators/emirates-bic?bic=AZIZAEAD&iban=AE070331234567890123456
CNY
Validate Chinese Union Pay card number
https://api.transferwise.com/v1/validators/chinese-card-number?cardNumber=6240008631401148
THB
Validate Thailand bank account number
https://api.transferwise.com/v1/validators/thailand-account-number?accountNumber=9517384260
Banks and Branches
Example Request (Get list of banks for Hong Kong):
curl -X GET https://api.sandbox.transferwise.tech/v1/banks/country=HK
Example Response (Get list of banks for Hong Kong):
{
"values": [
{
"code": "003",
"title": "STANDARD CHARTERED BANK (HONG KONG) LIMITED"
},
{
"code": "552",
"title": "AAREAL BANK AG, WIESBADEN, GERMANY"
},
{
"code": "307",
"title": "ABN AMRO BANK N.V."
},
{
"code": "222",
"title": "AGRICULTURAL BANK OF CHINA LIMITED"
},
{
"code": "525",
"title": "ZIBO CITY COMMERCIAL BANK, SHANDONG"
}
]
}
Example Request (Get list of bank branches for a Hong Kong bank with code 003):
curl -X GET https://api.sandbox.transferwise.tech/v1/bank-branches?country=HK&bankCode=003
Example Response (Get list of bank branches for a Hong Kong bank with code 003):
{
"country": "HK",
"values": [
{
"code": "251",
"title": "Quarry Bay Branch [251]",
"parentCode": "003"
},
{
"code": "983",
"title": "Canton Road Branch [983]",
"parentCode": "003"
},
{
"code": "984",
"title": "Tuen Mun Branch [984]",
"parentCode": "003"
},
{
"code": "985",
"title": "Kwun Tong Branch [985]",
"parentCode": "003"
}
]
}
Get list of banks by country code
List of banks is available for these countries: BD, BR, CZ, CL, EG, GH, HK, ID, IL, IN, JP, KE, LK, MA, NG, NP, PE, PH, RU, SG, TH, VN, ZA
GET https://api.sandbox.transferwise.tech/v1/banks?country=HK
Get list of branches by country and bank code
List of bank branches is available for these countries: BD, GH, HK, IL, IN, JP, LK, SG, VN
GET https://api.sandbox.transferwise.tech/v1/bank-branches?country=HK&bankCode=<bankCode>
Countries and States
Example Request (Get list of allowed countries):
curl -X GET https://api.sandbox.transferwise.tech/v1/countries
Example Response (Get list of allowed countries):
{
"values": [
{
"code": "AL",
"name": "Albania"
},
{
"code": "DZ",
"name": "Algeria"
},
...
{
"code": "ZW",
"name": "Zimbabwe"
},
{
"code": "AX",
"name": "Åland Islands"
}
]
}
Example Request (Get list of states for a country code US):
curl -X GET https://api.sandbox.transferwise.tech/v1/countries/US/states
Example Response (Get list of states for a country code US):
{
"values": [
{
"code": "AL",
"name": "Alabama"
},
{
"code": "AK",
"name": "Alaska"
},
...
{
"code": "PR",
"name": "Puerto Rico"
},
{
"code": "VI",
"name": "Virgin Islands"
}
]
}
Get list of countries
List of allowed countries to be used in recipient or user-profile addresses.
GET https://api.sandbox.transferwise.tech/v1/countries
Get list of states by country code
List of states is available for these countries: US, CA, BR, AU.
GET https://api.sandbox.transferwise.tech/v1/countries/{countryCode}/states
Create AED Recipient
Example Request (AED):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "AED",
"type": "emirates",
"legalType": "PRIVATE",
"details": {
"IBAN": "AE070331234567890123456"
}
}'
Send payments to United Arab Emirates.
Private and business recipients are supported.
Recipient type = 'emirates'
Required details: IBAN
Create ARS Recipient
Example Request (ARS):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "ARS",
"type": "argentina",
"details": {
"legalType": "PRIVATE",
"taxId": "20-34149938-1",
"accountNumber": "0110482420048200036238"
}
}'
Send payments to Argentina.
Private and business recipients are supported.
Recipient type = 'argentina'
Required details:
taxId - Recipient’s CUIT / CUIL (Single Tax Identification/ Single Labor Identification), 11 characters
accountNumber - Recipient’s account CBU, 22 characters (Alias not supported)
Create AUD Recipient
Example Request (AUD australian):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "AUD",
"type": "australian",
"details": {
"legalType": "PRIVATE",
"bsbCode": "023604",
"accountNumber": "123456789"
}
}'
Example Request (AUD australian_business):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "AUD",
"type": "australian_business",
"details": {
"legalType": "BUSINESS",
"bsbCode": "023604",
"businessNumber": "12 345 678 910"
"accountNumber": "123456789"
}
}'
Send payments to Australia.
Recipient type = 'australian'
Private recipients are supported.
Required details:
bsbCode - 6 digits
accountNumber - 5..14 digits
OR
Recipient type = 'australian_business'
Business recipients are supported.
Required details:
bsbCode - 6 digits
businessNumber - 9..14 digits
accountNumber - 5..14 digits
Create BDT Recipient
Example Request (BDT):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "BDT",
"type": "bangladesh",
"details": {
"legalType": "PRIVATE",
"bankCode": "015",
"branchCode": "015270362",
"accountNumber": "5060011118"
}
}'
Send payments to Bangladesh.
Recipient type = 'iban'
Required details: bankCode, branchCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create BGN Recipient
Example Request (BGN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "BGN",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "BG89370400440532013000"
}
}'
Send payments to Bulgaria.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
Create BRL Recipient
Example Request (BRL):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "BRL",
"type": "brazil",
"details": {
"legalType": "PRIVATE",
"bankCode": "218",
"branchCode": "1234",
"accountNumber": "12345678-9",
"accountType": "CHECKING",
"cpf": "123.456.789-12",
"phoneNumber": "+55 21 5555 5555"
}
}'
Send payments to Brazil.
Recipient type = 'brazil'
Required details: bankCode, branchCode, accountNumber, accountType (CHECKING or SAVINGS), cpf (tax reg no), recipient phone number
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create CAD Recipient
Example Request (CAD):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "CAD",
"type": "canadian",
"details": {
"legalType": "PRIVATE",
"institutionNumber": "006",
"transitNumber": "04841",
"accountNumber": "3456712",
"accountType": "Checking",
}
}'
Send payments to Canada.
Private and business recipients are supported.
Recipient type = 'canadian'
Required details: institutionNumber, transitNumber, accountNumber, accountType (Checking or Saving)
Create CAD Interac Recipient
Example Request (CAD):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "CAD",
"type": "interac",
"details": {
"interacAccount": "<recipient email>",
}
}'
Send payments to Canada via Interac.
Private and business recipients are supported. 10,000 CAD max per payment.
Recipient type = 'interac'
Required details: interacAccount
Create CHF Recipient
Example Request (CHF):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "CHF",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "CH89370400440532013000"
}
}'
Send payments to Switzerland.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
Create CLP Recipient
Example Request (CLP):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "CLP",
"type": "chile",
"details": {
"legalType": "PRIVATE",
"bankCode": "504",
"accountNumber": "12345678901234567890",
"rut": "760864285",
"accountType": "CHECKING",
"phoneNumber": "+56 33 555 5555"
}
}'
Send payments to Chile.
Private and business recipients are supported.
Recipient type = 'chile'
Required details: bankCode, accountNumber, rut (Rol Único Tributario), accountType (CHECKING, SAVINGS, CUENTA_VISTA), recipient phone number
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create CNY Recipient
Example Request (CNY):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "CNY",
"type": "chinese_card",
"details": {
"legalType": "PRIVATE",
"cardNumber": "6240008631401148"
}
}'
Send payments to China Unionpay cardholder.
Recipient type = 'chinese_card'
Required details: cardNumber
Create CZK Recipient
Example Request (CZK Local):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "CZK",
"type": "czech",
"details": {
"legalType": "PRIVATE",
"prefix": "000000",
"accountNumber": "5060011118",
"bankCode": "5500"
}
}'
Example Request (CZK IBAN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "CZK",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "CZ89370400440532013000"
}
}'
Send payments to Czech Republic.
Private and business recipients are supported.
Recipient type = 'czech'
Required details: prefix, accountNumber, bankCode
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
OR
Recipient type = 'iban'
Required details: IBAN
Create DKK Recipient
Example Request (DKK):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "DKK",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "DK89370400440532013000"
}
}'
Send payments to Denmark.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
Create EGP Recipient
Example Request (EGP):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "EGP",
"type": "egypt_local",
"details": {
"legalType": "PRIVATE",
"bankCode": "ECBAEGCA",
"accountNumber": "123456789"
}
}'
Send payments to Egypt.
Private and business recipients are supported.
Recipient type = 'egypt_local'
Required details: bankCode, accountNumber (Swift code)
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create EUR Recipient
Example Request (EUR):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "EUR",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "DE89370400440532013000"
}
}'
Send payments to Eurozone countries: Austria, Belgium, Cyprus, Estonia, Finland, France, Germany, Greece, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Portugal, Slovakia, Slovenia, Spain.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
Create GBP Recipient
Example Request (GBP Sort Code):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "GBP",
"type": "sort_code",
"details": {
"legalType": "PRIVATE",
"sortCode": "40-30-20",
"accountNumber": "12345678"
}
}'
Example Request (GBP IBAN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "GBP",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "GB89370400440532013000"
}
}'
Send payments to United Kingdom.
Private and business recipients are supported.
Recipient type = 'sort_code'
Required details: sortCode, accountNumber
OR
Recipient type = 'iban'
Required details: IBAN
Create GEL Recipient
Example Request (GEL):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "GEL",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "GE89370400440532013000"
}
}'
Send payments to Georgia.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
Create GHS Recipient
Example Request (GHS):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "GHS",
"type": "ghana_local",
"details": {
"legalType": "PRIVATE",
"bankCode": "030100",
"accountNumber": "0011XXXXXXXXXX"
}
}'
Send payments to Ghana.
Private and business recipients are supported.
Recipient type = 'ghana_local'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create HKD Recipient
Example Request (HKD):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"accountHolderName": "<recipient name>",
"currency": "HKD",
"type": "hongkong",
"details": {
"legalType": "PRIVATE",
"bankCode": "307",
"accountNumber": "005-231289-112"
}
}'
Send payments to Hong Kong.
Private and business recipients are supported.
Recipient type = 'hongkong'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create HRK Recipient
Example Request:
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "HRK",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "HR89370400440532013000"
}
}'
Send payments to Croatia.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
Create HUF Recipient
Example Request (HUF Local):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "HUF",
"type": "hungarian",
"details": {
"legalType": "PRIVATE",
"accountNumber": "12000000-12345678-00000000"
}
}'
Example Request (HUF IBAN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "HUF",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "HU89370400440532013000"
}
}'
Send payments to Hungary.
Private and business recipients are supported.
Recipient type = 'hungarian'
Required details: accountNumber
OR
Recipient type = 'iban'
Required details: IBAN
Create IDR Recipient
Example Request (IDR):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "IDR",
"type": "indonesian",
"details": {
"legalType": "PRIVATE",
"bankCode": "610306",
"accountNumber": "6789112345678"
}
}'
Send payments to Indonesia.
Private and business recipients are supported.
Recipient type = 'indonesian'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create ILS Recipient
Example Request (ILS IBAN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "ILS",
"type": "israeli_local",
"details": {
"legalType": "PRIVATE",
"IBAN": "IL620108000000099999999"
}
}'
Example Request (ILS Local Bank Code):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "ILS",
"type": "israeli_bank_code",
"details": {
"legalType": "PRIVATE",
"bankCode": "054",
"branchCode": "001",
"accountNumber": "123456789"
}
}'
Send payments to Israel.
Private and business recipients are supported.
Recipient type = 'israeli_local'
Required details: IBAN
OR
Recipient type = 'israeli_bank_code'
Required details: bankCode, branchCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create INR Recipient
Example Request (INR):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "INR",
"type": "indian",
"details": {
"legalType": "PRIVATE",
"ifscCode": "YESB0236041",
"accountNumber": "678911234567891",
}
}'
Send payments to India.
Private and business recipients are supported.
Recipient type = 'indian'
Required details: ifscCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create JPY Recipient
Example Request (JPY):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "JPY",
"type": "japanese",
"details": {
"legalType": "PRIVATE",
"bankCode": "6470",
"branchCode": "100",
"accountType": "CURRENT",
"accountNumber": "1234567"
}
}'
Send payments to Japan.
Private and business recipients are supported.
Recipient type = 'japanese'
Required details: bankCode, branchCode accountNumber, accountType (CURRENT, SAVINGS, CHECKING),
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create KES Recipient
Example Request (KES Bank Account):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "KES",
"type": "kenya_local",
"details": {
"legalType": "PRIVATE",
"bankCode": "35",
"accountNumber": "0023183991919"
}
}'
Example Request (KES Mobile MPESA):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "KES",
"type": "kenya_mobile",
"details": {
"legalType": "PRIVATE",
"accountNumber": "2547XXXXXXXX"
}
}'
Send payments to Kenya.
Private and business recipients are supported. However please note that only individuals can hold MPESA accounts.
Recipient type = 'kenya_local'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
OR
Recipient type = 'kenya_mobile'
Required details: accountNumber - mobile number
Create LKR Recipient
Example Request (LKR):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "LKR",
"type": "srilanka",
"details": {
"legalType": "PRIVATE",
"bankCode": "7214",
"branchCode": "100",
"accountNumber": "5060011118"
}
}'
Send payments to Sri Lanka.
Private and business recipients are supported.
Recipient type = 'srilanka'
Required details: bankCode, branchCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create MAD Recipient
Example Request (MAD):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "MAD",
"type": "morocco",
"details": {
"legalType": "PRIVATE",
"bankCode": "BCMAMAMC",
"accountNumber": "123456789012345678901234"
}
}'
Send payments to Morocco.
Private and business recipients are supported. 260,000 MAD per transaction
Recipient type = 'morocco'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create MXN Recipient
Example Request (MXN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "MXN",
"type": "mexican",
"details": {
"legalType": "PRIVATE",
"clabe": "032180000118359719"
}
}'
Send payments to Mexico.
Private and business recipients are supported.
Recipient type = 'mexican'
Required details: clabe
Create MYR Recipient
Example Request (MYR):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "MYR",
"type": "malaysian",
"details": {
"legalType": "PRIVATE",
"swiftCode": "ABNAMYKL",
"accountNumber": "159012938613"
}
}'
Send payments to Malaysia.
Private and business recipients are supported. Maximum amount is 10,000,000 MYR per payment.
Recipient type = 'malaysian'
Required details: swiftCode, accountNumber
Create NGN Recipient
Example Request (NGN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "NGN",
"type": "nigeria",
"details": {
"legalType": "PRIVATE",
"bankCode": "044",
"accountNumber": "0584412903"
}
}'
Send payments to Nigeria.
Private and business recipients are supported. Maximum amount is 2,000,000 NGN per payment.
Recipient type = 'nigeria'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create NOK Recipient
Example Request (NOK):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "NOK",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "DE89370400440532013000"
}
}'
Send payments to Norway.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
Create NPR Recipient
Example Request (NPR):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "NPR",
"type": "nepal",
"legalType": "PRIVATE",
"details": {
"bankCode": "977056",
"accountNumber": "1234567890"
}
}'
Send payments to Nepal.
Private recipients are supported. 1mln NPR per transaction / per month for individual account.
Recipient type = 'nepal'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create NZD Recipient
Example Request (NZD):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "NZD",
"type": "newzealand",
"details": {
"legalType": "PRIVATE",
"accountNumber": "03-1587-0050000-00"
}
}'
Send payments to New Zealand.
Recipient type = 'newzealand'
Required details: accountNumber
Create PEN Recipient
Example Request (PEN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "PEN",
"type": "peru",
"details": {
"legalType": "PRIVATE",
"bankCode": "BCON",
"accountNumber": "12345678901234567890",
"accountType": "CHECKING",
"idDocumentType": "DNI",
"idDocumentNumber": "09740475",
"phoneNumber": "+51 987654321"
}
}'
Send payments to Peru.
Private and business recipients are supported. 1,900 USD per transfer / 9,900 USD per 30 days.
Recipient type = 'peru'
Required details: bankCode, accountNumber, accountType (CHECKING, SAVINGS), ID document type (DNI, RUC, C_EXT, PASSP), ID document number, recipient phone number
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create PHP Recipient
Example Request (PHP):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "PHP",
"type": "philippines",
"details": {
"legalType": "PRIVATE",
"bankCode": "AMA",
"accountNumber": "0044XXXXXXXX",
"address" : {
"country": "GB",
"city": "London",
"postCode": "10025",
"firstLine": "50 Branson Ave"
}
}
}'
Send payments to Philippines.
Private and business recipients are supported. 480,000 PHP per payment.
Recipient type = 'philippines'
Required details: bankCode, accountNumber, recipient address
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create PKR Recipient
Example Request (PKR):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "PKR",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "PK89370400440532013000"
}
}'
Send payments to Pakistan. Max 1 million PKR per payment.
Recipient type = 'iban'
Required details: IBAN
Create PLN Recipient
Example Request (PLN IBAN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "PLN",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "PL89370400440532013000"
}
}'
Example Request (PLN Local):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "PLN",
"type": "polish",
"details": {
"legalType": "PRIVATE",
"accountNumber": "109010140000071219812874"
}
}'
Send payments to Poland.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
OR
Recipient type = 'polish'
Required details: accountNumber
Create RON Recipient
Example Request (RON):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "RON",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "RO89370400440532013000"
}
}'
Send payments to Romania.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
Create RUB Recipient
Example Request (RUB):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "RUB",
"type": "russiarapida",
"details": {
"legalType": "PRIVATE",
"bankCode": "041234567",
"accountNumber": "40820810999999999999",
"russiaRegion": "ALTAIKRAI",
"address" : {
"country": "GB",
"city": "London",
"postCode": "10025",
"firstLine": "50 Branson Ave"
}
}
}'
Send payments to Russia.
Recipient type = 'russiarapida'
Required details: bankCode, accountNumber, region, recipient address.
You have to provide first, last and patronymic names, in order for your transfer to be accepted by the recipient bank. (unless the recipient is registered at the bank with no patronymic)
You can get list of bank, region and country codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Lists of banks and branches can be obtained from Banks and Branches endpoints.
Create SEK Recipient
Example Request (SEK IBAN):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "SEK",
"type": "iban",
"details": {
"legalType": "PRIVATE",
"IBAN": "SE89370400440532013000"
}
}'
Example Request (SEK Local):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "SEK",
"type": "sweden_local",
"details": {
"legalType": "PRIVATE",
"clearingNumber": "1234",
"accountNumber": "1234567"
}
}'
Example Request (SEK BankGiro):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "SEK",
"type": "bankgiro",
"details": {
"legalType": "PRIVATE",
"bankgiroNumber": "1234-5678"
}
}'
Send payments to Sweden.
Private and business recipients are supported.
Recipient type = 'iban'
Required details: IBAN
OR
Recipient type = 'sweden_local'
Required details: clearingNumber, accountNumber
OR
Recipient type = 'bankgiro'
Required details: bankgiroNumber
Create SGD Recipient
Example Request (SGD):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "SGD",
"type": "singapore",
"details": {
"legalType": "PRIVATE",
"bankCode": "7418",
"accountNumber": "1238827822"
}
}'
Send payments to Singapore.
Private and business recipients are supported.
Recipient type = 'singapore'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create THB Recipient
Example Request (THB):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "THB",
"type": "thailand",
"details": {
"legalType": "PRIVATE",
"bankCode": "002",
"accountNumber": "9517384260"
"address" : {
"country": "GB",
"city": "London",
"postCode": "10025",
"firstLine": "50 Branson Ave"
}
}
}'
Send payments to Thailand. Max 2 mln THB per payment.
Private and business recipients are supported.
Recipient type = 'thailand'
Required details: bankCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create TRY Recipient
Example Request (TRY):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "TRY",
"type": "turkish_earthport",
"details": {
"legalType": "PRIVATE",
"IBAN": "TR330006100519786457841326"
}
}'
Send payments to Turkey.
Private and business recipients are supported. 1 000 000 TRY per payment.
Recipient type = 'turkish_earthport'
Required details: IBAN
Create UAH Recipient
Example Request (UAH):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "UAH",
"type": "privatbank",
"details": {
"legalType": "PRIVATE",
"phoneNumber": "777210012",
"accountNumber": "2662"
}
}'
Send payments to Ukraine. Maximum 1,2m UAH per payment.
Recipient type = 'privatbank'
Required details:
- phoneNumber = Use phone number registered in Privat Bank
- accountNumber = Last 4 digits of UAH PrivatBank card
Create USD Recipient
Example Request (USD):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "USD",
"type": "aba",
"details": {
"legalType": "PRIVATE",
"abartn": "111000025",
"accountNumber": "12345678",
"accountType": "CHECKING",
"address" : {
"country": "GB",
"city": "London",
"postCode": "10025",
"firstLine": "50 Branson Ave"
}
}
}'
Send payments to USA.
Private and business recipients are supported. Max 1 Million USD per payment.
Recipient type = 'aba'
Required details:
- abartn = ACH Routing number
- accountNumber = Recipient bank account number
- accountType = CHECKING or SAVINGS
- address = Recipient address
Create VND Recipient
Example Request (VND):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "VND",
"type": "vietname_earthport",
"details": {
"legalType": "PRIVATE",
"swiftCode": "ABBKVNVX",
"branchCode": "001",
"accountNumber": "1234567890"
}
}'
Send payments to Vietnam.
Private and business recipients are supported.
Recipient type = 'vietname_earthport'
Required details: swiftCode, branchCode, accountNumber
Lists of banks and branches can be obtained from Banks and Branches endpoints.
You can also get list of bank and branch codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Create ZAR Recipient
Example Request (ZAR):
curl -X POST "https://api.sandbox.transferwise.tech/v1/accounts" \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"profile": <your profile id>,
"accountHolderName": "<recipient name>",
"currency": "ZAR",
"type": "southafrica",
"details": {
"legalType": "PRIVATE",
"swiftCode": "ALBRZAJJ",
"accountNumber": "0000000052312891"
}
}'
Send payments to South African Republic.
Private and business recipients are supported.
Recipient type = 'southafrica'
Required details: swiftCode, accountNumber
You can get list of bank codes by using /v1/quotes/{quoteId}/account-requirements endpoint.
Lists of banks and branches can be obtained from Banks and Branches endpoints.
Simulation
Simulate Transfer Processing
Example Request:
curl -X GET "https://api.sandbox.transferwise.tech/v1/simulation/transfers/{transferId}/processing" \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": 15574445,
"user": 294205,
"targetAccount": 7993919,
"sourceAccount": null,
"quote": 113379,
"status": "processing",
"reference": "good times",
"rate": 1.2151,
"created": "2017-03-14 15:25:51",
"business": null,
"transferRequest": null,
"details": {
"reference": "good times"
},
"hasActiveIssues": false,
"sourceValue": 1000,
"sourceCurrency": "EUR",
"targetValue": 895.32,
"targetCurrency": "GPB"
}
You can simulate payment processing by changing transfer statuses using these endpoints.
This feature is limited to sandbox only.
Request
GET https://api.sandbox.transferwise.tech/v1/simulation/transfers/{transferId}/processing
Changes transfer status from incoming_payment_waiting to processing.
GET https://api.sandbox.transferwise.tech/v1/simulation/transfers/{transferId}/funds_converted
Changes transfer status from processing to funds_converted.
GET https://api.sandbox.transferwise.tech/v1/simulation/transfers/{transferId}/outgoing_payment_sent
Changes transfer status from funds_converted to outgoing_payment_sent.
GET https://api.sandbox.transferwise.tech/v1/simulation/transfers/{transferId}/bounced_back
Changes transfer status from outgoing_payment_sent to bounced_back.
GET https://api.sandbox.transferwise.tech/v1/simulation/transfers/{transferId}/funds_refunded
Changes transfer status from bounced_back to funds_refunded.
Response
Transfer entity with changed status.
Terms and Conditions
Get Terms and Conditions
Example Request:
curl -X GET "https://api.sandbox.transferwise.tech/v1/terms/default"
Example Response:
<h2><strong>1. How to read this Agreement</strong></h2>
<p>This Agreement contains 30 sections. You may go directly to any section by selecting the appropriate link provided. The headings are for reference only. Some capitalised terms have specific definitions in section [3]. Underlined words in this Agreement contain hyperlinks to further information.</p>
<h2><strong>2. Why you should read this Agreement</strong></h2>
<p>2.1 What this Agreement cover. These are the term and conditions on which we provide our Services to you.</p>
<p>2.2 Why you should read them. Please read this Agreement carefully before you start to use our Services. This Agreement (always together with the documents referred to in it) tell you who we are, how we will provide the Services to you, how this Agreement may be changed or ended, what to do if there is a problem and other important information. If you think that there is a mistake in this Agreement or require any changes, please <u>contact us</u> to discuss.</p>
<p>2.3 Other additional documents which applies to you. This Agreement refers to the following additional documents, which also apply to your use of our Services:</p>
<ul><li>(a) <u>Our Privacy Policy</u>, which sets out the terms on which we process any personal data we collect about you, or that you provide to us. By using our Services, you consent to such processing and you promise that all data provided by you is accurate.</li>
<li>(b) <u>Our Cookie Policy</u>, which sets out information about the “cookies” on our Website.</li>
...
Get TransferWise terms and conditions in HTML format to show to your customers who are signing up for their TransferWise account. This endpoint is applicable for bank integrations and third party application integrators only.
Request
GET https://api.sandbox.transferwise.tech/v1/terms/{clientId}
Use "default" as clientId to fetch Transferwise general terms and conditions.
No authentication is required for this endpoint.
Response
Terms and conditions in HTML format.
Transfers
Create
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/transfers \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"targetAccount": <recipient account id>,
"quote": <quote id>,
"customerTransactionId": "<the UUID you generated for the transfer attempt>",
"details" : {
"reference" : "to my friend",
"transferPurpose": "verification.transfers.purpose.pay.bills",
"sourceOfFunds": "verification.source.of.funds.other"
}
}'
Example Response:
{
"id": 468956,
"user": <your user id>,
"targetAccount": <recipient account id>,
"sourceAccount": null,
"quote": <quote id>,
"status": "incoming_payment_waiting",
"reference": "to my friend",
"rate": 0.9065,
"created": "2018-08-28 07:43:55",
"business": <your business profile id>,
"transferRequest": null,
"details": {
"reference": "to my friend"
},
"hasActiveIssues": false,
"sourceCurrency": "EUR",
"sourceValue": 661.89,
"targetCurrency": "GBP",
"targetValue": 600,
"customerTransactionId": "bd244a95-dcf8-4c31-aac8-bf5e2f3e54c0"
}
Transfer is a payout order to recipient account based on a quote. Once created then a transfer needs to be funded during next 5 working days. In case not it will get automatically cancelled.
Request
POST https://api.sandbox.transferwise.tech/v1/transfers
Field | Description | Format |
---|---|---|
targetAccount | Recipient account id. You can create multiple transfers to same recipient account. | Integer |
quote | Quote id. You can only create one transfer per one quote. You cannot use same quote ID to create multiple transfers. |
Integer |
customerTransactionId | This is required to perform idempotency check to avoid duplicate transfers in case of network failures or timeouts. | UUID |
details.reference (optional) | Recipient will see this reference text in their bank statement. Maximum allowed characters depends on the currency route. Business Payments Tips article has a full list. | Text |
details.transferPurpose (conditionally required) | For example when target currency is THB. See more about conditions at Transfers.Requirements | Text |
details.sourceOfFunds (conditionally required) | For example when target currency is USD and transfer amount exceeds 10k. See more about conditions at Transfers.Requirements | Text |
There are two options to deal with conditionally required fields:
- Always provide values for these fields
- Always call transfers-requirements endpoint and submit values only if indicated so.
Response
You need to save transfer id for tracking its status later.
Field | Description | Format |
---|---|---|
id | Transfer id | Integer |
user | Your user id | Integer |
targetAccount | Recipient account id | Integer |
sourceAccount | Not used | Integer |
quote | Quote id | Integer |
status | Transfer current status | Text |
reference | Deprecated, use details.reference instead | Text |
rate | Exchange rate value | Decimal |
created | Timestamp when transfer was created | Timestamp |
business | Your business profile id | |
transferRequest | Not used | Integer |
details.reference | Payment reference text | Text |
hasActiveIssues | Are there any pending issues which stop executing the transfer? | Boolean |
sourceCurrency | Source currency code | Text |
sourceValue | Transfer amount in source currency | Decimal |
targetCurrency | Target currency code | Text |
targetValue | Transfer amount in target currency | Decimal |
customerTransactionId | UUID format unique identifier assinged by customer. Used for idempotency check purposes. | UUID |
Avoiding duplicate transfers
We use customerTransactionId field to avoid duplicate transfer requests. When your first call fails (error or timeout) then you should use the same value in customerTransactionId field that you used in the original call when you are submitting a retry message. This way we can treat subsequent retry messages as repeat messages and will not create duplicate transfers to your account.
Fund
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v3/profiles/{profileId}/transfers/{transferId}/payments \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"type": "BALANCE"
}'
Example Response:
{
"type": "BALANCE",
"status": "COMPLETED",
"errorCode": null
}
This API call is the final step for executing payouts. TransferWise will now debit funds from your borderless balance and start processing your transfer. If your borderless balance is short of funds then this call will fail with "insufficient funds" error.
Request
POST https://api.sandbox.transferwise.tech/v3/profiles/{profileId}/transfers/{transferId}/payments
Use transfer id that you obtained in previous step.
Field | Description | Format |
---|---|---|
type | "BALANCE". This indicates that your transfer will be funded from your borderless account balance. |
Text |
Response
You need to save transfer id for tracking its status later.
Field | Description | Format |
---|---|---|
type | "BALANCE" | Text |
status | "COMPLETED" or "REJECTED" | Text |
errorCode | Failure reason. For example "balance.payment-option-unavailable" | Text |
Cancel
Example Request:
curl -X PUT https://api.sandbox.transferwise.tech/v1/transfers/{transferId}/cancel \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": 16521632,
"user": 4342275,
"targetAccount": 8692237,
"sourceAccount": null,
"quote": 657171,
"status": "cancelled",
"reference": "reference text",
"rate": 0.89,
"created": "2017-11-24 10:47:49",
"business": null,
"transferRequest": null,
"details": {
"reference": "vambo 3"
},
"hasActiveIssues": false,
"sourceCurrency": "EUR",
"sourceValue": 0,
"targetCurrency": "GBP",
"targetValue": 150,
"customerTransactionId": "54a6bc09-cef9-49a8-9041-f1f0c654cd88"
}
Only transfers which are not funded can be cancelled. Cancellation is final it can not be undone.
Request
PUT https://api.sandbox.transferwise.tech/v1/transfers/{transferId}/cancel
Use transfer id that you obtained when creating a transfer.
Response
Field | Description | Format |
---|---|---|
id | Transfer id | Integer |
user | Your user id | Integer |
targetAccount | Recipient account id | Integer |
sourceAccount | Not used | Integer |
quote | Quote id | Integer |
status | Transfer current status | Text |
reference | Deprecated, use details.reference instead | Text |
rate | Exchange rate value | Decimal |
created | Timestamp when transfer was created | Timestamp |
business | Your business profile id | |
transferRequest | Not used | Integer |
details.reference | Payment reference text | Text |
hasActiveIssues | Are there any pending issues which stop executing the transfer? | Boolean |
sourceCurrency | Source currency code | Text |
sourceValue | Transfer amount in source currency | Decimal |
targetCurrency | Target currency code | Text |
targetValue | Transfer amount in target currency | Decimal |
customerTransactionId | UUID format unique identifier assinged by customer. Used for idempotency check purposes. | UUID |
Get by Id
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/transfers/{transferId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": 15574445,
"user": 294205,
"targetAccount": 7993919,
"sourceAccount": null,
"quote": 113379,
"status": "incoming_payment_waiting",
"reference": "good times",
"rate": 1.2151,
"created": "2017-03-14 15:25:51",
"business": null,
"transferRequest": null,
"details": {
"reference": "good times"
},
"hasActiveIssues": false,
"sourceValue": 1000,
"sourceCurrency": "EUR",
"targetValue": 895.32,
"targetCurrency": "GPB",
"customerTransactionId": "6D9188CF-FA59-44C3-87A2-4506CE9C1EA3"
}
Get transfer info by id. Since we don't have push notifications yet, you can poll this endpoint to track your transfer status.
Request
GET https://api.sandbox.transferwise.tech/v1/transfers/{transferId}
Response
Field | Description | Format |
---|---|---|
id | Transfer id | Integer |
user | Your user id | Integer |
targetAccount | Recipient account id | Integer |
sourceAccount | Not used | Integer |
quote | Quote id | Integer |
status | Transfer current status | Text |
reference | Deprecated, use details.reference instead | Text |
rate | Exchange rate value | Decimal |
created | Timestamp when transfer was created | Timestamp |
business | Your business profile id | |
transferRequest | Not used | Integer |
details.reference | Payment reference text | Text |
hasActiveIssues | Are there any pending issues which stop executing the transfer? | Boolean |
sourceCurrency | Source currency code | Text |
sourceValue | Transfer amount in source currency | Decimal |
targetCurrency | Target currency code | Text |
targetValue | Transfer amount in target currency | Decimal |
customerTransactionId | UUID format unique identifier assinged by customer. Used for idempotency check purposes. | UUID |
Get Issues
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/transfers/{transferId}/issues \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"type": "Payment has bounced back",
"state": "OPENED",
"description": "Inorrect recipient account number"
}
]
Get pending issues that are suspending a transfer from further processing. This is more applicable for Bank Integrations use case when transfers are NOT funded from borderless account but funding is sent via bank transfer. For example "DEPOSIT_AMOUNT_LESS_INVOICE" means that arrived funding does not cover total transfer amount.
Request
GET https://api.sandbox.transferwise.tech/v1/transfers/{transferId}/issues
Response
Field | Description | Format |
---|---|---|
type | Issue type:
|
Text |
status | Issue state: OPENED, IN_PROGRESS, CLOSED | Text |
description | Additional details about issue. For example 'Incorrect recipient account number' | Text |
Get Delivery Time
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/delivery-estimates/{transferId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"estimatedDeliveryDate" : "2018-01-10T12:15:00.000+0000"
}
Get the live delivery estimate for a transfer by the transfer ID.
The delivery estimate is the time at which we currently expect the transfer to arrive in the benificiary's bank account.
This is not a guaranteed time but we are working hard to make these estimates as accurate as possible.
Request
GET https://api.sandbox.transferwise.tech/v1/delivery-estimates/{transferId}
Response
You need to save transfer id for tracking its status later.
Field | Description | Format |
---|---|---|
estimatedDeliveryDate | Estimated time when funds will arrive to recipient's bank account | Timestamp |
Get Receipt PDF
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/transfers/{transferId}/receipt.pdf \
-H "Authorization: Bearer <your api token>"
Example Response:
Receipt presented as application/pdf content-type
Download transfer confirmation receipt in PDF format for transfers that are in status outgoing_payment_sent.
Request
GET https://api.sandbox.transferwise.tech/v1/transfers/{transferId}/receipt.pdf
Response
Transfer confirmation receipt in PDF format.
List
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/transfers?offset=0&limit=100&profile=<your profile id>&status=funds_refunded&createdDateStart=2018-12-15&createdDateEnd=2018-12-30 \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": 15574445,
"user": 294205,
"targetAccount": 7993919,
"sourceAccount": null,
"quote": 113379,
"status": "funds_refunded",
"reference": "good times",
"rate": 1.1179,
"created": "2018-12-16 15:25:51",
"business": null,
"transferRequest": null,
"details": {
"reference": "good times"
},
"hasActiveIssues": false,
"sourceValue": 1000,
"sourceCurrency": "EUR",
"targetValue": 895.32,
"targetCurrency": "GPB",
"customerTransactionId": "6D9188CF-FA59-44C3-87A2-4506CE9C1EA3"
},
{
"id": 14759252,
"user": 294205,
"targetAccount": 5570192,
"sourceAccount": null,
"quote": 113371,
"status": "funds_refunded",
"reference": "",
"rate": 1.1179,
"created": "2018-12-26 15:25:51",
"business": null,
"transferRequest": null,
"details": {
"reference": ""
},
"hasActiveIssues": false,
"sourceValue": 1000,
"sourceCurrency": "EUR",
"targetValue": 895.32,
"targetCurrency": "GPB",
"customerTransactionId": "785C67AD-7E29-4DBC-9D4A-4C45D4D5333A"
}
]
Get the list of transfers for given user's profile (defaults to user's personal profile).
You can add query parameters to specify user's profile (personal or business), time period and/or payment status.
For example you can query:
- all failed payments created since last week
- all completed payments created since yesterday
Request
GET https://api.sandbox.transferwise.tech/v1/transfers/?offset=0&limit=100&profile=<your profile id>&status=funds_refunded&sourceCurrency=EUR&createdDateStart=2018-12-15T01:30:00.000Z&createdDateEnd=2018-12-30T01:30:00.000Z
Field | Description | Format |
---|---|---|
profile | User profile id. If parameter is omitted, defaults to user's personal profile | Integer |
status | Status code or codes list (as comma separated value list) to filter returned transfers with. See Track transfer status for complete list of statuses. | Text |
sourceCurrency | Source currency code | Text |
targetCurrency | Target currency code | Text |
createdDateStart | Starting date to filter transfers, inclusive of the provided date. | yyyy-MM-dd'T'HH:mm:ss.SSS'Z' |
createdDateEnd | Ending date to filter transfers, inclusive of the provided date. | yyyy-MM-dd'T'HH:mm:ss.SSS'Z' |
limit | Maximum number of records to be returned in response | Integer |
offset | Starting record number | Integer |
Response
Field | Description | Format |
---|---|---|
id | Transfer id | Integer |
user | Your user id | Integer |
targetAccount | Recipient account id | Integer |
sourceAccount | Not used | Integer |
quote | Quote id | Integer |
status | Transfer current status | Text |
reference | Deprecated, use details.reference instead | Text |
rate | Exchange rate value | Decimal |
created | Timestamp when transfer was created | Timestamp |
business | Your business profile id | |
transferRequest | Not used | Integer |
details.reference | Payment reference text | Text |
hasActiveIssues | Are there any pending issues which stop executing the transfer? | Boolean |
sourceCurrency | Source currency code | Text |
sourceValue | Transfer amount in source currency | Decimal |
targetCurrency | Target currency code | Text |
targetValue | Transfer amount in target currency | Decimal |
customerTransactionId | UUID format unique identifier assinged by customer. Used for idempotency check purposes. | UUID |
Requirements
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/transfer-requirements \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"targetAccount": <recipient account id>,
"quote": <quote id>,
"details": {
"reference": "good times",
"sourceOfFunds": "verification.source.of.funds.other",
"sourceOfFundsOther": "Trust funds"
},
"customerTransactionId": "6D9188CF-FA59-44C3-87A2-4506CE9C1EA3"
}'
Example Response:
[
{
"type": "transfer",
"fields": [
{
"name": "Transfer reference",
"group": [
{
"key": "reference",
"type": "text",
"refreshRequirementsOnChange": false,
"required": false,
"displayFormat": null,
"example": null,
"minLength": null,
"maxLength": 10,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": null
}
]
},
{
"name": "Transfer purpose",
"group": [
{
"key": "transferPurpose",
"type": "select",
"refreshRequirementsOnChange": true,
"required": true,
"displayFormat": null,
"example": null,
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": [
{
"key": "verification.transfers.purpose.purchase.property",
"name": "Buying property abroad"
},
{
"key": "verification.transfers.purpose.pay.bills",
"name": "Rent or other property expenses"
},
{
"key": "verification.transfers.purpose.mortgage",
"name": "Mortgage payment"
},
{
"key": "verification.transfers.purpose.pay.tuition",
"name": "Tuition fees or studying expenses"
},
{
"key": "verification.transfers.purpose.send.to.family",
"name": "Sending money home to family"
},
{
"key": "verification.transfers.purpose.living.expenses",
"name": "General monthly living expenses"
},
{
"key": "verification.transfers.purpose.other",
"name": "Other"
}
]
}
]
},
{
"name": "Source of funds",
"group": [
{
"key": "sourceOfFunds",
"type": "select",
"refreshRequirementsOnChange": true,
"required": true,
"displayFormat": null,
"example": null,
"minLength": null,
"maxLength": null,
"validationRegexp": null,
"validationAsync": null,
"valuesAllowed": [
{
"key": "verification.source.of.funds.salary",
"name": "Salary"
},
{
"key": "verification.source.of.funds.investment",
"name": "Investments (stocks, properties, etc.)"
},
{
"key": "verification.source.of.funds.inheritance",
"name": "Inheritance"
},
{
"key": "verification.source.of.funds.loan",
"name": "Loan"
},
{
"key": "verification.source.of.funds.other",
"name": "Other"
}
]
}
]
}
]
}
]
Almost every country has their own specific originality when it comes to the nitty gritty details of domestic payment systems and money transfer regulations. Maximum allowed length of reference text is a good example. The US payment system, ACH, supports 10 characters only, but transfers within Mexico allow up to 100 characters and so on.
Same is true for requirements arising from Anti-Money Laundering regulations adopted in different countries. Transfers from and to USD almost always require more details about source of funds and transfer purpose, compared to transfers to EUR or GBP.
Endpoint /transfer-requirements exposes all these specific requirements based on specific quote and target recipient account.
To make sure that processing of your transfers does not get delayed because of missing details, we highly recommend to verify the transfer requirements before before submitting any transfer.
Request
POST https://api.sandbox.transferwise.tech/v1/transfer-requirements
1.Prepare request body to create transfer object first. Now post this request body to transfer-requirements endpoint to figure out if there are any other required fields.
2.Analyze the returned list of fields. Our example includes reference, sourceOfFunds and transferPurpose fields. Field 'reference' is optional. Fields 'sourceOfFunds' and 'transferPurpose' are required and both have refreshRequirementsOnChange=true which indicates that there could be additional fields required depending on the selected value.
In our example you will have to POST request to/v1/transfer-requirements` second time as well with values set for 'transferPurpose' and 'sourceOfFunds'. So in case you set sourceOfFunds = 'verification.source.of.funds.other' then another text field called "sourceOfFundsOther" is also required where you need to specify the details in free format.
3.Once you get to the point where you have provided values for all fields which have refreshRequirementsOnChange=true then you have complete set of fields to compose a valid request to create a transfer object.
For example this is a valid request to create a transfer.
POST /v1/transfers:
{
"targetAccount": ,
"details": {
"reference": "good times",
"sourceOfFunds": "verification.source.of.funds.other",
"sourceOfFundsOther": "Trust funds"
},
"customerTransactionId": "6D9188CF-FA59-44C3-87A2-4506CE9C1EA3"
}
Response
Field | Description | Format |
---|---|---|
type | "transfer" | Text |
fields[n].name | Field description | Text |
fields[n].group[n].key | Key is name of the field you should include in the JSON | Text |
fields[n].group[n].type | Display type of field (e.g. text, select, etc) | Text |
fields[n].group[n].refreshRequirementsOnChange | Tells you whether you should call POST transfer-requirements once the field value is set to discover required lower level fields. | Boolean |
fields[n].group[n].required | Indicates if the field is mandatory or not | Boolean |
fields[n].group[n].displayFormat | Display format pattern. | Text |
fields[n].group[n].example | Example value. | Text |
fields[n].group[n].minLength | Min valid length of field value. | Integer |
fields[n].group[n].maxLength | Max valid length of field value. | Integer |
fields[n].group[n].validationRegexp | Regexp validation pattern. | Text |
fields[n].group[n].validationAsync | Validator URL and parameter name you should use when submitting the value for validation | Text |
fields[n].group[n].valuesAllowed[n].key | List of allowed values. Value key | Text |
fields[n].group[n].valuesAllowed[n].name | List of allowed values. Value name. | Text |
Create Third-Party Transfers
Example Request (Originator Type = PRIVATE):
curl -X POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/third-party-transfers \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"targetAccount": <recipient account id>,
"quote": <quote id>,
"originalTransferId": "<unique transfer id in your system>",
"details" : {
"reference" : "Ski trip"
},
"originator" : {
"legalEntityType" : "PRIVATE",
"reference" : "<unique customer id in your system>",
"name" : {
"givenName": "John",
"middleNames": ["Ryan"],
"familyName": "Godspeed"
},
"dateOfBirth": "1977-07-01",
"address" : {
"firstLine": "Salu tee 100, Apt 4B",
"city": "Tallinn",
"countryCode": "EE",
"postCode": "12112"
}
}
}'
Example Request (Originator Type = BUSINESS):
curl -X POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/third-party-transfers \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"targetAccount": <recipient account id>,
"quote": <quote id>,
"originalTransferId": "<unique transfer id in your system>",
"details" : {
"reference" : "Payment for invoice 22092"
},
"originator" : {
"legalEntityType" : "BUSINESS",
"reference" : "<originator customer id in your system>",
"name" : {
"fullName": "Hot Air Balloon Services Ltd"
},
"businessRegistrationCode": "1999212",
"address" : {
"firstLine": "Aiandi tee 1431",
"city": "Tallinn",
"countryCode": "EE",
"postCode": "12112"
}
}
}'
Example Response:
{
"id": 47755772,
"originalTransferId": "PMT-29991221",
"user": <your user id>,
"targetAccount": <recipient account id>,
"quote": <quote id>,
"status": "incoming_payment_waiting",
"rate": 0.8762,
"details": {
"reference": "Ski trip"
},
"hasActiveIssues": false,
"sourceCurrency": "EUR",
"sourceValue": 0,
"targetCurrency": "GBP",
"targetValue": 500,
"originator": {
"name": {
"givenName": "John",
"middleNames": [
"Ryan"
],
"familyName": "Godspeed",
"patronymicName": null,
"fullName": "John Godspeed"
},
"dateOfBirth": "1977-07-01",
"reference": "CST-2991992",
"legalEntityType": "PRIVATE",
"businessRegistrationCode": null,
"address": {
"firstLine": "Salu tee 14",
"city": "Tallinn",
"stateCode": null,
"countryCode": "EE",
"postCode": "12112"
}
},
"created": "2019-02-18T12:59:42.000Z"
}
This endpoint is applicable for Third-Party Payouts use case only.
Request
POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/third-party-transfers
This is very similar to Create transfers endpoint, but please note these differences:
- originator datablock is additionally required
- originalTransferId field is being used instead of customerTransactionId
Field | Description | Format |
---|---|---|
targetAccount | Recipient account id. You can create multiple transfers to same recipient account. | Integer |
quote | Quote id. You can only create one transfer per one quote. You cannot use same quote ID to create multiple transfers. |
Integer |
originalTransferId | Unique transfer id in your system. We use this field also to perform idempotency check to avoid duplicate transfers in case of network failures or timeouts. You can only submit one transfer with same originalTransferId. | Text |
details.reference (optional) | Recipient will see this reference text in their bank statement. Maximum allowed characters depends on the currency route. Business Payments Tips article has a full list. | Text |
originator | Data block to capture payment originator details. | Group |
originator.legalEntityType | PRIVATE or BUSINESS. Payment originator legal type. | Text |
originator.reference | Unique customer id in your system. This allows us to uniquely identify each originator. Required. | Text |
originator.name.givenName | Payment originator first name. Required if legalEntityType = PRIVATE. | Text |
originator.name.middleNames | Payment originator middle name(s). Used only if legalEntityType = PRIVATE. Optional | Text Array |
originator.name.familyName | Payment originator family name. Required if legalEntityType = PRIVATE. | Text |
originator.name.patronymicName | Payment originator patronymic name. Used only if legalEntityType = PRIVATE. Optional | Text |
originator.name.fullName | Payment originator full legal name. Required if legalEntityType = BUSINESS. | Text |
originator.dateOfBirth | Payment originator date of birth. Required if legalEntityType = PRIVATE. | YYYY-MM-DD |
originator.businessRegistrationCode | Payment originator business registry number / incorporation number. Required if legalEntityType = BUSINESS. | Text |
originator.address.firstLine | Payment originator address first line. Required | Text |
originator.address.city | Payment originator address city. Required | Text |
originator.address.stateCode | Payment originator address state code. Required if address country code in (US, CA, BR, AU). See Countries and states | Text |
originator.address.countryCode | Payment originator address first line. Required | Text |
originator.address.postCode | Originator address zip code. Optional | Text |
Response
You need to save transfer id for tracking its status later.
Field | Description | Format |
---|---|---|
id | Transfer id | Integer |
originalTransferId | Transfer id | Integer |
user | Your user id | Integer |
targetAccount | Recipient account id | Integer |
sourceAccount | Not used | Integer |
quote | Quote id | Integer |
status | Transfer current status | Text |
rate | Exchange rate value | Decimal |
details.reference | Payment reference text | Text |
hasActiveIssues | Are there any pending issues which stop executing the transfer? | Boolean |
sourceCurrency | Source currency code | Text |
sourceValue | Transfer amount in source currency | Decimal |
targetCurrency | Target currency code | Text |
targetValue | Transfer amount in target currency | Decimal |
originator | Data block to capture payment originator details | Group |
originator.legalEntityType | Payment originator legal type. | Text |
originator.reference | Unique customer id in your system. | Text |
originator.name.givenName | Payment originator first name. | Text |
originator.name.middleNames | Payment originator middle name(s). | Text Array |
originator.name.familyName | Payment originator family name. | Text |
originator.name.patronymicName | Payment originator patronymic name. | Text |
originator.name.fullName | Payment originator full legal name. | Text |
originator.dateOfBirth | Payment originator date of birth. | YYYY-MM-DD |
originator.businessRegistrationCode | Payment originator business registry number / incorporation number. | Text |
originator.address.firstLine | Payment originator address first line. | Text |
originator.address.city | Payment originator address city. | Text |
originator.address.stateCode | Payment originator address state code. | Text |
originator.address.countryCode | Payment originator address first line. | Text |
originator.address.postCode | Originator address zip code. | Text |
created | Timestamp when transfer was created | Timestamp |
Avoiding duplicate transfers
We use originalTransferId field to avoid duplicate transfer requests. When your first call fails (error or timeout) then you should use the same value in originalTransferId field that you used in the original call when you are submitting a retry message. This way we can treat subsequent retry messages as repeat messages and will not create duplicate transfers to your account.
Users
Get By Id
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/users/{userId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": 101,
"name": "Example Person",
"email": "person@example.com",
"active": true,
"details": {
"firstName": "Example",
"lastName": "Person",
"phoneNumber": "+37111111111",
"occupation": "",
"address": {
"city": "Tallinn",
"countryCode": "EE",
"postCode": "11111",
"state": "",
"firstLine": "Road 123"
},
"dateOfBirth": "1977-01-01",
"avatar": "https://lh6.googleusercontent.com/photo.jpg",
"primaryAddress": 111
}
}
Get authenticated user details by user id. Response includes also personal user profile info.
Request
GET https://api.sandbox.transferwise.tech/v1/users/{userId}
Response
Field | Description | Format |
---|---|---|
id | userId | Integer |
name | User full name | Text |
User email | Text | |
active | If user is active or not | Boolean |
details.firstName | User first name | Text |
details.lastName | User lastname | Text |
details.phoneNumber | Phone number | Text |
details.dateOfBirth | Date of birth | YYYY-MM-DD |
details.occupation | Person occupation | Text |
details.avatar | Link to person avatar image | Text |
details.primaryAddress | Address object id to use in addesses endpoints | Integer |
details.address.countryCode | Address country code in 2 digits. "US" for example | Text |
details.address.firstLine | Address first line | Text |
details.address.postCode | Address post code | Text |
details.address.city | Address city name | Text |
details.address.state | Address state code State code. Required if country is US, CA, AU, BR. | Text |
details.address.occupation | User occupation. Required for US, CA, JP | Text |
Get the currently logged in user
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/me \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": 101,
"name": "Example Person",
"email": "person@example.com",
"active": true,
"details": {
"firstName": "Example",
"lastName": "Person",
"phoneNumber": "+37111111111",
"occupation": "",
"address": {
"city": "Tallinn",
"countryCode": "EE",
"postCode": "11111",
"state": "",
"firstLine": "Road 123"
},
"dateOfBirth": "1977-01-01",
"avatar": "https://lh6.googleusercontent.com/photo.jpg",
"primaryAddress": 111
}
}
Get authenticated user details for the user's token submitted in the Authorization
header. Response includes also personal user profile info.
Request
GET https://api.sandbox.transferwise.tech/v1/me
Response
Field | Description | Format |
---|---|---|
id | userId | Integer |
name | User full name | Text |
User email | Text | |
active | If user is active or not | Boolean |
details.firstName | User first name | Text |
details.lastName | User lastname | Text |
details.phoneNumber | Phone number | Text |
details.dateOfBirth | Date of birth | YYYY-MM-DD |
details.occupation | Person occupation | Text |
details.avatar | Link to person avatar image | Text |
details.primaryAddress | Address object id to use in addesses endpoints | Integer |
details.address.countryCode | Address country code in 2 digits. "US" for example | Text |
details.address.firstLine | Address first line | Text |
details.address.postCode | Address post code | Text |
details.address.city | Address city name | Text |
details.address.state | Address state code State code. Required if country is US, CA, AU, BR. | Text |
details.address.occupation | User occupation. Required for US, CA, JP | Text |
Sign Up with Registration Code
1) Example Request: Get Client Credentials Token
curl -X "POST" "https://api.sandbox.transferwise.tech/oauth/token" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-u '[your-api-client-id]:[your-api-client-secret]' \
--data-urlencode "grant_type=client_credentials"
1) Example Response: Get Client Credentials Token
{
"access_token":"ba8k1234-00f2-475a-60d8-6g45377b4062",
"token_type":"bearer",
"expires_in": 43199,
"scope":"transfers"
}
2) Example Request: Create User
curl -X POST https://api.sandbox.transferwise.tech/v1/user/signup/registration_code \
-H "Authorization: Bearer <your client credentials token>" \
-H "Content-Type: application/json" \
-d '{
"email": <user email>,
"registrationCode": <registration code>
}'
2) Example Response: Create User (Success (200) user created successfully)
{
"id": 12345,
"name": null,
"email": "new.user@domain.com",
"active": true,
"details": null
}
2) Example Response: Create User (Failure (409): User already exists)
{
"errors": [
{
"code": "NOT_UNIQUE",
"message": "You’re already a member. Please login",
"path": "email",
"arguments": [
"email",
"class com.transferwise.fx.api.ApiRegisterCommand",
"existing.user@domain.com"
]
}
]
}
3) Example Request: Get User Tokens
curl \
-u '[your-api-client-id]:[your-api-client-secret]' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=registration_code' \
-d 'email=<user email>' \
-d 'client_id=[your-api-client-id]' \
-d 'registration_code=<registration code used to create user>' \
'https://api.sandbox.transferwise.tech/oauth/token'
3) Example Response: Get User Tokens (Success: 200)
{
"access_token": "01234567-89ab-cdef-0123-456789abcdef",
"token_type": "bearer",
"refresh_token": "01234567-89ab-cdef-0123-456789abcdef",
"expires_in": 43199,
"scope": "transfers"
}
3) Example Response: Get User Tokens (Failure: 401 - User reclaimed the account or invalid registration code used)
{
"error": "invalid_grant",
"error_description": "Invalid user credentials."
}
This feature is related to Bank Integrations product. It enables onboarding new users to TransferWise via backend API calls only. To get authorization from Transferwise existing users you still need to redirect them to our authorization webpage.
There are 3 steps you need to go through:
1) Get Client Credentials Token
Obtain access_token based on your API client credentials.
Request
POST https://api.sandbox.transferwise.tech/oauth/token
Use Basic Authentication with your api-client-id/api-client-secret as username/pwd and also use the header Content-Type: application/x-www-form-urlencoded
.
Field | Description | Format |
---|---|---|
grant_type | "client_credentials" | Text |
Response
Field | Description | Format |
---|---|---|
access_token | Access token to be used when calling "create user" endpoint. Valid for 12 hours. | uuid |
token_type | "bearer" | Text |
expires_in | Expiry time in seconds | Integer |
scope | "transfers" | Text |
2) Create User
TransferWise uses email address as unique identifier for users. If email is new (there is no active user already) then new user will be created.
When you are submitting an email which already exists amongst our users then you will get a warning that "You’re already a member. Please login". If user already exists then you need to redirect to Get user authorization webpage.
Request
POST https://api.sandbox.transferwise.tech/v1/user/signup/registration_code
Use access_token obtained in first step as authentication header.
Field | Description | Format |
---|---|---|
New user's email address | ||
registrationCode | Randomly generated registration code that is unique to this user. At least 32 characters long. You need to store registration code to obtain access token on behalf of this newly created user in next step. Please apply the same security standards to handling registration code as if it was a password. |
Text, min length is 32 chars |
Response
Field | Description | Format |
---|---|---|
id | userId | Integer |
name | User full name. Empty. | Text |
Customer email | Text | |
active | true | Boolean |
details | User details. Empty. | Group |
3) Get User Tokens
You can now use registration code to obtain user access token and refresh token. This step can be repeated as long as user does not reclaim their TransferWise account. If user has reclaimed the account, then redirect to Get user authorization flow should be used instead.
Refresh user access token works same way for this flow as well.
Request
POST https://api.sandbox.transferwise.tech/oauth/token
Use Basic Authentication with your api-client-id/api-client-secret as username/pwd.
Field | Description | Format |
---|---|---|
grant_type | "registration_code" | Text |
New user's email address | ||
client_id | Your api_client_id | Text |
registration_code | registrationCode from step 2 | Text |
Response
Field | Description | Format |
---|---|---|
access_token | Access token to be used when calling API endpoints on behalf of user. Valid for 12 hours. | uuid |
token_type | "bearer" | Text |
refresh_token | Refresh token which you need to use in order to request new access_token. The lifetime of refresh tokens is 10 years. | uuid |
expires_in | Expiry time in seconds | Integer |
scope | "transfers" | Text |
User Profiles
Create (Personal)
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/profiles \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"type": "personal",
"details": {
"firstName": "Oliver",
"lastName": "Wilson",
"dateOfBirth": "1977-07-01",
"phoneNumber": "+3725064992"
}
}'
Example Response (Personal):
{
"id": <your personal profile id>,
"type": "personal",
"details": {
"firstName": "Oliver",
"lastName": "Wilson",
"dateOfBirth": "1977-07-01",
"phoneNumber": "+3725064992",
"avatar": "",
"occupation": "",
"primaryAddress": null
}
}
Create personal user profile.
Same person cannot have multiple active duplicate user profiles.
Thus creating multiple profiles with the same details will fail. Use the access token
you received to act on behalf of the user in the Authorization
header.
Request
POST https://api.sandbox.transferwise.tech/v1/profiles
Field | Description | Format |
---|---|---|
type | "personal" | Text |
details.firstName | First name | Text |
details.lastName | Last name | Text |
details.dateOfBirth | Date of birth | YYYY-MM-DD |
details.phoneNumber (optional) |
Phone number | Text |
Response
Field | Description | Format |
---|---|---|
id | profileId | Integer |
type | "personal" | Text |
details.firstName | First name | Text |
details.lastName | Last name | Text |
details.dateOfBirth | Date of birth | YYYY-MM-DD |
details.phoneNumber | Phone number | Text |
details.avatar | Link to person avatar image | Text |
details.occupation | Person occupation | Text |
details.primaryAddress | Address object id | Integer |
Create (Business)
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/profiles \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"type": "business",
"details": {
"name": "ABC Logistics Ltd",
"registrationNumber": "12144939",
"acn": null,
"abn": null,
"arbn": null,
"companyType": "LIMITED",
"companyRole": "OWNER",
"descriptionOfBusiness": "Information and communication",
"webpage": "https://abc-logistics.com"
}
}'
Example Response (Business):
{
"id": <your business profile id>,
"type": "business",
"details": {
"name": "ABC Logistics Ltd",
"registrationNumber": "12144939",
"acn": null,
"abn": null,
"arbn": null,
"companyType": "LIMITED",
"companyRole": "OWNER",
"descriptionOfBusiness": "Information and communication",
"webpage": "https://abc-logistics.com",
"primaryAddress": null,
"businessCategory":"CONSULTING_IT_BUSINESS_SERVICES",
"businessSubCategory":"DESIGN"
}
}
Create business user profile. You would need to create personal profile first always. Business profile cannot be created without personal profile.
Request (Business)
POST https://api.sandbox.transferwise.tech/v1/profiles
Field | Description | Format |
---|---|---|
type | "business" | Text |
details.name | Business name | Text |
details.registrationNumber | Business registration number | Text |
details.acn | Australian Company Number (only for AUS businesses) | Text |
details.abn | Australian Business Nnumber (only for AUS businesses) | Text |
details.arbn | Australian Registered Body Number (only for AUS businesses) | Text |
details.companyType | Company legal form. Allowed values:
|
Text |
details.companyRole | Role of person. Allowed Values:
|
Text |
details.descriptionOfBusiness | Sector / filed of activity | Text |
details.webpage | Business webpage | Text |
details.businessCategory | Type of business, see below for permitted values | Text |
details.businessSubCategory | Specifc sub category of the business type, see below for permitted values | Text |
Business Category
Ensure when submitting a business profile that you submit a category and associated sub-category from the list below. You should map from the information you have about the business to one of our categories and sub-categories. If this is problematic please get in touch with the TransferWise for Banks team to discuss alternate solutions.
The categories and their sub-categories are as follows:
- CHARITY_NON_PROFIT
- CHARITY_ALL_ACTIVITIES
- CONSULTING_IT_BUSINESS_SERVICES
- ADVERTISING_AND_MARKETING
- ARCHITECTURE
- COMPANY_ESTABLISHMENT_FORMATION_SERVICES
- DESIGN
- FINANCIAL_CONSULTING_ACCOUNTING_TAXATION_AUDITING
- IT_DEVELOPMENT
- IT_HOSTING_SERVICES
- IT_CONSULTING_AND_SERVICES
- LEGAL_SERVICES
- MANAGEMENT_CONSULTING
- SCIENTIFIC_AND_TECHNICAL_CONSULTING
- SOFTWARE_AS_A_SERVICE
- TRANSLATION_AND_LANGUAGE_SERVICES
- CONSULTING_OTHER
- SERVICES_OTHER
- FREELANCE_PLATFORMS
- DESIGN_MARKETING_COMMUNICATIONS
- ADVERTISING_AND_MARKETING
- ARCHITECTURE
- AUDIO_AND_VIDEO
- DESIGN
- PHOTOGRAPHY
- PRINT_AND_ONLINE_MEDIA
- TELECOMMUNICATIONS_SERVICES
- TRANSLATION_AND_LANGUAGE_SERVICES
- MEDIA_COMMUNICATION_ENTERTAINMENT
- ADULT_CONTENT
- AUDIO_AND_VIDEO
- FINE_ARTS
- ARTS_OTHER
- EVENTS_AND_ENTERTAINMENT
- GAMBLING_BETTING_AND_ONLINE_GAMING
- NEWSPAPERS_MAGAZINES_AND_BOOKS
- PERFORMING_ARTS
- PHOTOGRAPHY
- TELECOMMUNICATIONS_SERVICES
- VIDEO_GAMING
- EDUCATION_LEARNING
- SCHOOLS_AND_UNIVERSITIES,
- TEACHING_AND_TUTORING
- ONLINE_LEARNING
- FINANCIAL_SERVICES_PRODUCTS_HOLDING_COMPANIES
- CROWDFUNDING
- CRYPTOCURRENCY_FINANCIAL_SERVICES
- FINANCIAL_CONSULTING_ACCOUNTING_TAXATION_AUDITING
- HOLDING_COMPANIES
- INSURANCE
- INVESTMENTS
- MONEY_SERVICE_BUSINESSES
- FINANCIAL_SERVICES_OTHER
- FOOD_BEVERAGES_TOBACCO
- ALCOHOL
- FOOD_MANUFACTURING_RETAIL
- RESTAURANTS_AND_CATERING
- SOFT_DRINKS
- TOBACCO
- VITAMINS_AND_DIETARY_SUPPLEMENTS
- HEALTH_PHARMACEUTICALS_PERSONAL_CARE
- HEALTH_AND_BEAUTY_PRODUCTS_AND_SERVICES,
- DENTAL_SERVICES,
- DOCTORS_AND_MEDICAL_SERVICES,
- ELDERLY_OR_OTHER_CARE_HOME,
- FITNESS_SPORTS_SERVICES,
- MEDICAL_EQUIPMENT,
- NURSING_AND_OTHER_CARE_SERVICES,
- PHARMACEUTICALS,
- PHARMACY,
- VITAMINS_AND_DIETARY_SUPPLEMENTS
- PUBLIC_GOVERNMENT_SERVICES
- PUBLIC_ALL_SERVICES
- REAL_ESTATE_CONSTRUCTION
- ARCHITECTURE
- CONSTRUCTION
- REAL_ESTATE_DEVELOPMENT
- REAL_ESTATE_SALE_PURCHASE_AND_MANAGEMENT
- RETAIL_WHOLESALE_MANUFACTURING
- AGRICULTURE_SEEDS_PLANTS
- FINE_ARTS
- ARTS_OTHER
- AUTOMOTIVE_SALES_SPARE_PARTS_TRADE
- AUTOMOTIVE_MANUFACTURING
- CHEMICALS
- CLOTHING
- ELECTRICAL_PRODUCTS
- FIREARMS_WEAPONS_AND_MILITARY_GOODS_SERVICES
- HOME_ACCESSORIES_FURNITURE
- FINE_JEWELLERY_WATCHES
- FASHION_JEWELLERY
- LEGAL_HIGHS_AND_RELATED_ACCESSORIES
- MACHINERY
- PETS
- PRECIOUS_STONES_DIAMONDS_AND_METALS
- SPORTING_EQUIPMENT
- MANUFACTURING_OTHER
- RETAIL_WHOLESALE_MARKETPLACE_AUCTION
- RETAIL_WHOLESALE_OTHER
- TRAVEL_TRANSPORT_TOUR_AGENCIES
- ACCOMMODATION_HOTELS
- PASSENGER_TRANSPORT
- FREIGHT_TRANSPORT
- RIDESHARING_TRANSPORT_SHARING_SERVICES
- TRANSPORT
- TRAVEL_AGENCIES
- TOUR_OPERATORS
- TRAVEL_OR_TOUR_ACTIVITIES_OTHER
- OTHER
- OTHER_NOT_LISTED_ABOVE
Response (Business)
Field | Description | Format |
---|---|---|
id | profileId | Integer |
type | "business" | Text |
details.name | Business name | Text |
details.registrationNumber | Business registration number | Text |
details.acn | Australian Company Number (only for AUS businesses) | Text |
details.abn | Australian Business Nnumber (only for AUS businesses) | Text |
details.arbn | Australian Registered Body Number (only for AUS businesses) | Text |
details.companyType | Company legal form | Text |
details.companyRole | Role of person | Text |
details.descriptionOfBusiness | Sector / filed of activity | Text |
details.webpage | Business webpage | Text |
details.primaryAddress | Address object id | Integer |
details.businessCategory | Type of business | Text |
details.businessSubCategory | Specifc sub category of the business type | Text |
Update
Example Request:
curl -X PUT https://api.sandbox.transferwise.tech/v1/profiles \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"type": "personal",
"details": {
"firstName": "Oliver",
"lastName": "Wilson",
"dateOfBirth": "1977-07-01",
"phoneNumber": "+3725064992"
}
}'
Example Response:
{
"id": <your personal profile id>,
"type": "personal",
"details": {
"firstName": "Oliver",
"lastName": "Wilson",
"dateOfBirth": "1977-07-01",
"phoneNumber": "+3725064992",
"avatar": "",
"occupation": "",
"primaryAddress": null
}
}
Update user profile information. If user profile has been verified by TransferWise then there are restrictions on what information is allowed to change.
Request
PUT https://api.sandbox.transferwise.tech/v1/profiles
Request and response is same as described in Create (Personal) and Create (Business)
Get By Id
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/profiles/{profileId} \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": <your personal profile id>,
"type": "personal",
"details": {
"firstName": "Oliver",
"lastName": "Wilson",
"dateOfBirth": "1977-07-01",
"phoneNumber": "+3725064992",
"avatar": "",
"occupation": "",
"primaryAddress": null
}
}
Get profile info by id.
Request
GET https://api.sandbox.transferwise.tech/v1/profiles/{profileId}
List
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/profiles \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": <your personal profile id>,
"type": "personal",
"details": {
"firstName": "Oliver",
"lastName": "Wilson",
"dateOfBirth": "1977-07-01",
"phoneNumber": "+3725064992",
"avatar": "",
"occupation": "",
"primaryAddress": null
}
},
{
"id": <your business profile id>,
"type": "business",
"details": {
"name": "ABC Logistics Ltd",
"registrationNumber": "12144939",
"acn": null,
"abn": null,
"arbn": null,
"companyType": "LIMITED",
"companyRole": "OWNER",
"descriptionOfBusiness": "CHARITY_AND_NOT_FOR_PROFIT",
"webpage": "https://abc-logistics.com",
"primaryAddress": null,
"businessCategory": "CHARITY_AND_NOT_FOR_PROFIT",
"businessSubCategory": "CHARITY_ALL_ACTIVITIES"
}
}
]
List of all profiles belonging to user.
Request
GET https://api.sandbox.transferwise.tech/v1/profiles
Create Identification Document
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/verification-documents \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Oliver",
"lastName": "Wilson",
"type": "IDENTITY_CARD",
"uniqueIdentifier": "AA299822313",
"issueDate": "2017-12-31",
"issuerCountry": "EE",
"issuerState": "",
"expiryDate": "2027-12-31"
}'
Example Response:
{
"errorMessage": null,
"success": true
}
Add identification document details to user profile. Applicable to personal profiles (not business) only.
Returns empty result if successful.
When sending a social security number (SSN) only type
and uniqueIdentifier
(only 9 digits no letters or symbols) are required.
Request (Business)
POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/verification-documents
Field | Description | Format |
---|---|---|
firstName | Person first name in document | Text |
lastName | Person last name in document | Text |
type | Document type. Allowed Values:
|
Text |
uniqueIdentifier | Document number. Only digits when SSN. | Text |
issueDate | Document issue date | YYYY-MM-DD |
issuerCountry | Issued by country code. For example "US" | Text |
issuerState | Issued by state code. For example "NY" | Text |
expiryDate | Document expiry date. (optional) | YYYY-MM-DD |
Get business directors
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/directors \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": 10,
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa"
},
{
"id": 11,
"firstName": "Jane",
"lastName": "Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa"
}
]
Returns the list of all directors associated with the business profile.
Request (Business)
GET https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/directors
Add business directors
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/directors \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '[
{
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa"
},
{
"firstName": "Jane",
"lastName": "Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa"
}
]'
Example Response:
[
{
"id": 10,
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa"
},
{
"id": 11,
"firstName": "Jane",
"lastName": "Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa"
},
{
"id": 7,
"firstName": "Oliver",
"lastName": "Wilson",
"dateOfBirth": "2017-12-31",
"countryOfResidenceIso3Code": "gbr"
}
]
Adds new directors to the business profile. Returns the list of all directors associated with the business profile.
Request (Business)
POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/directors
Field | Description | Format |
---|---|---|
firstName | Director first name | Text |
lastName | Director last name | Text |
dateOfBirth | Date of birth | YYYY-MM-DD |
countryOfResidenceIso3Code | 3 character country code | Text |
Update business directors
Example Request:
curl -X PUT https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/directors \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '[
{
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa"
},
{
"firstName": "Jane",
"lastName": "Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa"
}
]'
Example Response:
[
{
"id": 14,
"firstName": "John",
"lastName": "Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa"
},
{
"id": 15,
"firstName": "Jane",
"lastName": "Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa"
}
]
Overrides directors in the business profile. Returns the list of all directors associated with the business profile.
Request (Business)
PUT https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/directors
Field | Description | Format |
---|---|---|
firstName | Director first name | Text |
lastName | Director last name | Text |
dateOfBirth | Date of birth | YYYY-MM-DD |
countryOfResidenceIso3Code | 3 character country code | Text |
Get business ultimate beneficial owners
Example Request:
curl -X GET https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/ubos \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": "013ab1c2688d0185b582ee7e0bcb28b2",
"name": "John Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "123 Fake St",
"postCode": "FK 12345",
"ownershipPercentage": 30
},
{
"id": "912ce3f31c8b3a10572137e78417caa3",
"name": "Jane Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "125 Fake St",
"postCode": "FK 12545",
"ownershipPercentage": 70
}
]
Returns the list of all ultimate beneficial owners associated with the business profile.
Request (Business)
GET https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/ubos
Add business ultimate beneficial owners
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/ubos \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '[
{
"name": "John Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "123 Fake St",
"postCode": "FK 12345",
"ownershipPercentage": 30
},
{
"name": "Jane Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "125 Fake St",
"postCode": "FK 12545",
"ownershipPercentage": 40
}
]'
Example Response:
[
{
"id": "f3e71aa1c97448d0b1eb5bdc0bacdcce",
"name": "John Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "123 Fake St",
"postCode": "FK 12345",
"ownershipPercentage": 30
},
{
"id": "c6008d58a1664413b4c4dcacec1377f4",
"name": "Jane Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "125 Fake St",
"postCode": "FK 12545",
"ownershipPercentage": 40
},
{
"id": "63bbdd1cf5ec4dd587597e74dbace376",
"name": "Oliver Wilson",
"dateOfBirth": "2017-12-31",
"countryOfResidenceIso3Code": "gbr",
"addressFirstLine": "222 Fake St",
"postCode": "FK 22222",
"ownershipPercentage": 30
}
]
Adds new ultimate beneficial owners to the business profile. Returns the list of all ultimate beneficial owners associated with the business profile.
Request (Business)
POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/ubos
Field | Description | Format |
---|---|---|
name | Owner full name | Text |
dateOfBirth | Date of birth | YYYY-MM-DD |
countryOfResidenceIso3Code | 3 character country code | Text |
addressFirstLine | First line of address | Text |
postCode | Address post code | Text |
ownershipPercentage | Percentage of ownership | Integer |
Update business ultimate beneficial owners
Example Request:
curl -X PUT https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/ubos \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '[
{
"name": "John Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "123 Fake St",
"postCode": "FK 12345",
"ownershipPercentage": 30
},
{
"name": "Jane Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "125 Fake St",
"postCode": "FK 12545",
"ownershipPercentage": 70
}
]'
Example Response:
[
{
"id": "ff01cf3f206b40c090a14a1e51163e9e",
"name": "John Doe",
"dateOfBirth": "1982-05-20",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "123 Fake St",
"postCode": "FK 12545",
"ownershipPercentage": 30
},
{
"id": "c36b687d28ad44ad8c3864411f5f2612",
"name": "Jane Doe",
"dateOfBirth": "1981-12-07",
"countryOfResidenceIso3Code": "usa",
"addressFirstLine": "125 Fake St",
"postCode": "FK 12545",
"ownershipPercentage": 70
}
]
Overrides ultimate beneficial owners in the business profile. Returns the list of all ultimate beneficial owners associated with the business profile.
Request (Business)
PUT https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/ubos
Field | Description | Format |
---|---|---|
name | Owner full name | Text |
dateOfBirth | Date of birth | YYYY-MM-DD |
countryOfResidenceIso3Code | 3 character country code | Text |
addressFirstLine | First line of address | Text |
postCode | Address post code | Text |
ownershipPercentage | Percentage of ownership | Integer |
Open update window
Example Request:
curl -X POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/update-window \
-H "Authorization: Bearer <your api token>"
Example Response:
Opens the update window for updating the profile information: details, addresses, directors, owners, others.
Request
POST https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/update-window
Close update window
Example Request:
curl -X DELETE https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/update-window \
-H "Authorization: Bearer <your api token>"
Example Response:
Deletes the update window for updating the profile.
Request
DELETE https://api.sandbox.transferwise.tech/v1/profiles/{profileId}/update-window
Language Support
Internationalisation support for translation of strings returned by the API is supported for the following endpoints:
Endpoint |
---|
/v1/quotes |
/v1/quotes/<quoteId>/account-requirements |
/v1/accounts |
/v1/transfers |
When calling these endpoints if you include an Accept-Language
header with a supported language code as the value then stings will be returned in the requested language. The languages supported by TransferWise are:
Language | Code |
---|---|
American English | en_US |
British English | en |
Dutch | nl |
French | fr |
German | de |
Hungarian | hu |
Italian | it |
Japanese | ja |
Korean | ko |
Polish | pl |
Portuguese | pt |
Romanian | ro |
Russian | ru |
Spanish | es |
If you request an unsupported language then British English will be returned by default.
Application Webhooks
Application webhook subscription is a mechanism that will allow you to receive notifications to your servers whenever various events happen in relation to different resources created by an application.
Before proceeding, make sure the endpoint where you intend to receive webhooks satisfies the following requirements:
- Has a valid domain name (IP addresses are disallowed)
- Listens to HTTPS requests on port
443
- Has a valid HTTPS certificate signed by a trusted Certificate Authority - CA (self-signed or expired certificates are not accepted)
- Does not include any query arguments in the URL
https://webhooks.example.com/balance-change
is a valid URL; http://webhooks.example.com:8080/hook.php?type=balance
is not.
You can have multiple subscriptions per event type though be mindful you will receive duplicate callbacks, one for each subscription. Find out more about webhook events here.
Client token
Request
POST https://api.sandbox.transferwise.tech/oauth/token
Use Basic Authentication with your api-client-id/api-client-secret as username/pwd and also use the header Content-Type: application/x-www-form-urlencoded
.
Field | Description | Format |
---|---|---|
grant_type | "client_credentials" | Text |
Response
Field | Description | Format |
---|---|---|
access_token | Access token to be used when creating an application subscription. Valid for 12 hours. | uuid |
token_type | "bearer" | Text |
expires_in | Expiry time in seconds | Integer |
scope | Text |
Create
Example Request:
curl -X POST "https://api.transferwise.com/v3/applications/{clientKey}/subscriptions" \
-H "Authorization: Bearer <your client level token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Webhook Subscription #1",
"trigger_on": "transfers#state-change",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
}
}'
Example Response:
{
"id": "72195556-e5cb-495e-a010-b37a4f2a3043",
"name": "Webhook Subscription #1",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
},
"trigger_on": "transfers#state-change",
"scope": {
"domain": "application",
"id": "<your client key>"
},
"created_by": {
"type": "application",
"id": "<your client ID>" // clientId and key are not always the same
},
"created_at": "2019-10-10T13:55:57Z"
}
Request
POST https://api.transferwise.com/v3/applications/{clientKey}/subscriptions
{clientKey}
can be received upon obtaining client credentials from our tech support.
All fields listed below are required for creating a webhook subscription.
Field | Description | Format |
---|---|---|
name | A custom name for your webhook to ease with identification | Text |
trigger_on | Choose from a list of available events | Text |
delivery.version | The event representation semantic version | Text |
delivery.url | Required. The URL where your server will be listening for events. | Text |
Response
Field | Description | Format |
---|---|---|
id | UUID that uniquely identifies the subscription | Text |
name | A custom name for your webhook to ease with identification | Text |
trigger_on | transfers#state-change , transfers#active-cases or balances#credit |
Text |
delivery.version | The event representation semantic version | Text |
delivery.url | The URL where your server will be listening for events. | Text |
scope.domain | Scope of this subscription, always "application" in this case | Text |
scope.id | Client key used to create this subscription | Text |
created_by.type | Creator type. Always application in this case | Text |
created_by.id | Client ID of the creator. Not always the same as the client key | Text |
created_at | Timestamp of when the subscription was created | Text |
Delete
Deletes a subscription by its identifier.
Example Request:
curl -X DELETE "https://api.transferwise.com/v3/applications/{clientKey}/subscriptions/{id}" \
-H "Authorization: Bearer <your client level token>"
Example Response:
Request
DELETE https://api.transferwise.com/v3/applications/{clientKey}/subscriptions/{id}
Get by ID
Retrieves a subscription by its identifier.
Example Request:
curl -X GET "https://api.transferwise.com/v3/applications/{clientKey}/subscriptions/{id}" \
-H "Authorization: Bearer <your client level token>"
Example Response:
{
"id": "f215f353-35fd-405b-b27f-4fd603c905ed",
"name": "Webhook Subscription #1",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
},
"trigger_on": "balances#credit",
"scope": {
"domain": "application",
"id": "<your client key>"
},
"created_by": {
"type": "application",
"id": "<your client ID>" // clientId and key are not always the same
},
"created_at": "2008-09-15T15:53:00Z"
}
Request
GET https://api.transferwise.com/v3/applications/{clientKey}/subscriptions/{id}
Test notifications
Test notifications can be generated for existing application subscriptions using the API.
Test notifications will have the correct structure for their source subscription's event type and version, and will contain "dummy" data. These data include random UUIDs, entity IDs of zero, current dates and times, and hard-coded status codes.
Test notifications are delivered with the usual notification HTTP request headers, including a unique delivery ID for the notification, and a "test notification" flag set to true. You can check for the presence of this test flag to determine that an incoming notification is a test notification which should not be processed as real data. See the section Event HTTP requests for more information on request headers.
When test notifications are created with the API, they are queued for sending in the same way as non-test notifications. This means that there may be some delay in notification delivery, and delivery failures will result in attempts to redeliver the notification later. The API returns the delivery IDs of the notifications that have been successfully queued for sending, which can be correlated with the delivery ID header values for notifications you later receive.
Please note that this test notification API is only available for application-based subscriptions. Profile-based subscriptions do not currently support this testing feature.
Example Request:
curl -X POST "https://api.transferwise.com/v3/applications/{clientKey}/subscriptions/{subscriptionId}/test-notifications" \
-H "Authorization: Bearer <your client level token>"
Example Response:
[
{
"delivery_id": "4a6b9810-4279-4de5-8d8d-1a6cf3b92a75",
"created_at": "2019-03-28T11:22:33Z"
}
]
Example Test Notification:
x-signature: bnho0q9JhjR6IPJIOZqWVP...
x-delivery-id: 4a6b9810-4279-4de5-8d8d-1a6cf3b92a75
x-test-notification: true
{
"data": {
"resource": {
"id": 0,
"profile_id": 0,
"account_id": 0,
"type": "transfer"
},
"current_state": "processing",
"previous_state": "incoming_payment_waiting",
"occurred_at": "2019-03-28T11:22:33Z"
},
"subscription_id": "39f241b7-293d-439e-beb3-4bf947bd4ff8",
"event_type": "transfers#state-change",
"schema_version": "2.0.0",
"sent_at": "2019-03-28T11:22:33Z"
}
Request
POST https://api.transferwise.com/v3/applications/{clientKey}/subscriptions/{subscriptionId}/test-notifications
Response
List of test notifications that were scheduled for delivery.
Field | Description | Format |
---|---|---|
delivery_id | UUID that uniquely identifies the notification | Text |
created_at | Time the notification was created | Text |
List
List all your subscriptions.
Example Request:
curl -X GET "https://api.transferwise.com/v3/applications/{clientKey}/subscriptions" \
-H "Authorization: Bearer <your client level token>"
Example Response:
[
{
"id": "e889e085-3677-4110-be26-3e9160ac9f25",
"name": "#1 subscription",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
},
"trigger_on": "transfers#state-change",
"created_by": {
"type": "application",
"id": "<your client ID>"
},
"scope": {
"domain": "application",
"id": "<your client key>"
}
},
{
"id": "eabeb3f5-c134-4a1c-99e2-86a1163daf1b",
"name": "#2 subscription",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
},
"trigger_on": "transfers#state-change",
"created_by": {
"type": "application",
"id": "<your client ID>"
},
"scope": {
"domain": "application",
"id": "<your client key>"
}
}
]
Request
GET https://api.transferwise.com/v3/applications/{clientKey}/subscriptions
Profile Webhooks
Profile webhook subscription is a mechanism that will allow you to receive notifications to your servers whenever various events happen in relation to different resources created under a specific profile.
Before proceeding, make sure the endpoint where you intend to receive webhooks satisfies the following requirements:
- Has a valid domain name (IPs are disallowed)
- Listens to HTTPS requests on port
443
- Has a valid HTTPS certificate signed by a trusted Certificate Authority - CA (self-signed or expired certificates are not accepted)
- Does not include any query arguments in the URL
https://webhooks.example.com/balance-change
is a valid URL; http://webhooks.example.com:8080/hook.php?type=balance
is not.
You can have multiple subscriptions per event type though be mindful you will receive duplicate callbacks, one for each subscription. Find out more about webhook events here.
If you will be dealing with multiple profiles in your integration, check out application webhooks. You will have to subscribe only once and you will receive updates concerning all resources that were created in your application.
There are two ways you can manage profile webhooks:
- via API (read more below)
- via user interface (go to your settings page)
Create
Example Request:
curl -X POST "https://api.transferwise.com/v3/profiles/{profileId}/subscriptions" \
-H "Authorization: Bearer <your user token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Webhook Subscription #1",
"trigger_on": "transfers#state-change",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
}
}'
Example Response:
{
"id": "72195556-e5cb-495e-a010-b37a4f2a3043",
"name": "Webhook Subscription #1",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
},
"trigger_on": "transfers#state-change",
"scope": {
"domain": "profile",
"id": "<profile ID>"
},
"created_by": {
"type": "user",
"id": "<your user ID>"
},
"created_at": "2008-09-15T15:53:00Z"
}
Request
POST https://api.transferwise.com/v3/profiles/{profileId}/subscriptions
profileId
- ID of the profile you are subscribing to.
All fields listed below are required for creating a webhook subscription.
Field | Description | Format |
---|---|---|
name | A custom name for your webhook to ease with identification | Text |
trigger_on | Choose from a list of available events | Text |
delivery.version | The event representation semantic | Text |
delivery.url | Required. The URL where your server will be listening for events. | Text |
Response
Field | Description | Format |
---|---|---|
id | UUID that uniquely identifies the subscription | Text |
name | A custom name for your webhook to ease with identification | Text |
trigger_on | transfers#state-change , transfers#active-cases or balances#credit |
Text |
delivery.version | The event representation semantic | Text |
delivery.url | Required. The URL where your server will be listening for events. | Text |
scope.domain | Scope of this subscription, always "profile" in this case | Text |
scope.id | Profile ID used to create this subscription | Text |
created_by.type | Creator type. Always user in this case | Text |
created_by.id | User id of the creator | Text |
created_at | Timestamp of when the subscription was created | Text |
Delete
Deletes a subscription by its identifier.
Example Request:
curl -X DELETE "https://api.transferwise.com/v3/profiles/{profileId}/subscriptions/{id}" \
-H "Authorization: Bearer <your user token>"
Example Response:
Request
DELETE https://api.transferwise.com/v3/profiles/{profileId}/subscriptions/{id}
Get by ID
Retrieves a subscription by its identifier.
Example Request:
curl -X GET "https://api.transferwise.com/v3/profiles/{profileId}/subscriptions/{id}" \
-H "Authorization: Bearer <your user token>"
Example Response:
{
"id": "f215f353-35fd-405b-b27f-4fd603c905ed",
"name": "Webhook Subscription #1",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
},
"trigger_on": "balances#credit",
"scope": {
"domain": "profile",
"id": "<profile ID>"
},
"created_by": {
"type": "user",
"id": "<your user ID>"
},
"created_at": "2008-09-15T15:53:00Z"
}
Request
GET https://api.transferwise.com/v3/profiles/{profileId}/subscriptions/{id}
List
List all your subscriptions
Example Request:
curl -X GET "https://api.transferwise.com/v3/profiles/{profileId}/subscriptions" \
-H "Authorization: Bearer <your user token>"
Example Response:
[
{
"id": "e889e085-3677-4110-be26-3e9160ac9f25",
"name": "#1 subscription",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
},
"trigger_on": "transfers#state-change",
"created_by": {
"type": "user",
"id": "<your user ID>"
},
"scope": {
"domain": "profile",
"id": "<profile ID>"
}
},
{
"id": "eabeb3f5-c134-4a1c-99e2-86a1163daf1b",
"name": "#2 subscription",
"delivery": {
"version": "2.0.0",
"url": "https://your.webhook.url/12345"
},
"trigger_on": "transfers#state-change",
"created_by": {
"type": "user",
"id": "<your user ID>"
},
"scope": {
"domain": "profile",
"id": "<profile ID>"
}
}
]
Request
GET https://api.transferwise.com/v3/profiles/{profileId}/subscriptions
Webhook events
Events are messages that will be sent to your server as HTTP POST
requests if you create a webhook subscription for
the type of event and a relevant resource you have access to is updated.
Events will not contain any personally identifiable information.
For example, an event may describe a change in the status of a transfer you have made.
To acknowledge that you have successfully processed an event, make sure your server answers with a 2xx
-series HTTP status
code within 5 seconds. Otherwise, we will consider the delivery attempt as having failed and will later try to resend the
message.
We will attempt to redeliver messages at increasing intervals over a two week period. We will try at most 25 times to do this.
Event HTTP requests
Event HTTP request bodies have a type-specific structure. Events using version 2 of our type schema will contain a common base structure with additional event-specific details. Each event type is described in detail later in this section.
Event HTTP requests also contain the following custom headers:
Signature header X-Signature
TransferWise public key for production environment:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvO8vXV+JksBzZAY6GhSO
XdoTCfhXaaiZ+qAbtaDBiu2AGkGVpmEygFmWP4Li9m5+Ni85BhVvZOodM9epgW3F
bA5Q1SexvAF1PPjX4JpMstak/QhAgl1qMSqEevL8cmUeTgcMuVWCJmlge9h7B1CS
D4rtlimGZozG39rUBDg6Qt2K+P4wBfLblL0k4C4YUdLnpGYEDIth+i8XsRpFlogx
CAFyH9+knYsDbR43UJ9shtc42Ybd40Afihj8KnYKXzchyQ42aC8aZ/h5hyZ28yVy
Oj3Vos0VdBIs/gAyJ/4yyQFCXYte64I7ssrlbGRaco4nKF3HmaNhxwyKyJafz19e
HwIDAQAB
How to verify signatures (in Java):
public boolean verifySignature(String encodedPublicKey, String signature, String payload) {
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.getMimeDecoder().decode(encodedPublicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
Signature sign = Signature.getInstance("SHA1WithRSA");
sign.initVerify(publicKey);
sign.update(payload.getBytes());
byte[] signatureBytes = Base64.getDecoder().decode(signature);
return sign.verify(signatureBytes);
}
Each outgoing webhook request is signed. Although event payloads do not contain any sensitive information, you may want to verify if the request is coming from TransferWise (however this is optional). We advise you not to process any requests where signature appears to be forged.
Each POST
request includes the X-Signature
header, which contains the message-specific signature.
Delivery ID header X-Delivery-Id
Each outgoing notification is assigned a unique delivery UUID.
Test notification header X-Test-Notification
This header is present with the value true
if the notification is a test message.
Test messages can be sent to verify callback URLs when subscriptions are being set up.
Event payload
Basic event payload:
{
"data": {},
"subscription_id": "db463333-3333-3333-3333-185d1ee81585",
"event_type": "...",
"schema_version": "2.0.0",
"sent_at": "2019-10-14T12:43:37Z"
}
All events share same high-level payload structure.
Depending on the event_type
, the only object that differs between events is data
.
Field | Description | Format |
---|---|---|
data | Object with information about updated resource | Object |
subscription_id | ID of the subscription that triggered the event | UUID |
event_type | Type of event, which defines data object |
Integer |
schema_version | The event representation semantic version | String |
sent_at | Timestamp when update happened | Timestamp |
Transfer status change event
Example event:
{
"data": {
"resource": {
"id": 99330022,
"profile_id": 11121314,
"account_id": 1514131211,
"type": "transfer"
},
"current_state": "processing",
"previous_state": "incoming_payment_waiting",
"occurred_at": "2019-10-14T12:43:37Z"
},
"subscription_id": "db463333-3333-3333-3333-185d1ee81585",
"event_type": "transfers#state-change",
"schema_version": "2.0.0",
"sent_at": "2019-10-14T12:43:37Z"
}
Event type: transfers#state-change
This event will be triggered every time a transfer's status is updated. Each event contains a timestamp.
As we do not guarantee the order of events, please use data.occured_at
to reconcile the order.
If you would like to subscribe to transfer state change events, please use transfers#state-change
when creating your subscription.
Schema version 2.0.0
(latest)
Field | Description | Format |
---|---|---|
data.resource.id | ID of the transfer that got updated | String |
data.resource.profile_id | ID of the profile that owns the transfer | Integer |
data.resourceI.account_id | ID of transfer's recipient | Integer |
data.resource.type | Type of the resource that was updated | String |
data.current_state | Newly acquired state of the resource, possible values are same as transfer statuses | String |
data.previous_state | Previous state of the resource, possible values are same as transfer statuses | String |
data.occured_at | Timestamp when the update happened | Timestamp |
Transfer issue event
Example event:
{
"data": {
"resource": {
"id": 99330022,
"profile_id": 11121314,
"account_id": 1514131211,
"type": "transfer"
},
"active_cases": ["deposit_amount_less_invoice"]
},
"subscription_id": "db463333-3333-3333-3333-185d1ee81585",
"event_type": "transfers#active-cases",
"schema_version": "2.0.0",
"sent_at": "2019-10-14T12:43:37Z"
}
Event type: transfers#active-cases
This event will be triggered every time a transfer's list of active issues is updated. Issues indicate potential problems with transfer processing.
If you would like to subscribe to transfer active issue events, please use transfers#active-cases
when creating
your subscription.
Schema version 2.0.0
(latest)
Field | Description | Format |
---|---|---|
data.resource.id | ID of the transfer that got updated | String |
data.resource.profile_id | ID of the profile that owns the transfer | Integer |
data.resourceI.account_id | ID of transfer's recipient | Integer |
data.resource.type | Type of the resource that was updated | String |
data.active_cases | List of ongoing issues related to the transfer | String |
Balance deposit event
Example event:
{
"data": {
"resource": {
"id": 99887766,
"type": "balance-account",
"profile_id": 11121314
},
"amount": 50.00,
"currency": "EUR",
"transaction_type": "credit",
"post_transaction_balance_amount": 150,
"occurred_at": "2019-10-14T12:43:37Z"
},
"subscription_id": "db463333-3333-3333-3333-185d1ee81585",
"event_type": "balances#credit",
"schema_version": "2.0.0",
"sent_at": "2019-10-14T12:43:37Z"
}
Event type: balances#credit
This event will be triggered every time a balance account is credited.
Please note: This event is not currently delivered to application subscriptions.
If you would like to subscribe to balance credit events, please use balances#credit
when creating your subscription.
Schema version 2.0.0
(latest)
Field | Description | Format |
---|---|---|
subscriptionId | ID of subscription that triggers this notification | String |
profileId | ID of the profile that owns the balance | Integer |
amount | Deposit amount | Decimal |
currency | Currency of the balance that got updated | String |
eventType | Type of update | String |
Webhooks version 1 (deprecated)
You can use profile webhooks or application webhooks instead.
List
Example Request:
curl -X GET https://api.transferwise.com/v1/subscriptions?channelId=webhook \
-H "Authorization: Bearer <your api token>"
Example Response:
[
{
"id": "abcde123-abcd-abcd-abcd-abcde1234567",
"name": "Webhook Subscription #1",
"channel_id": "WEBHOOK",
"user_id": "TW::<your user ID>",
"status": "ENABLED",
"created_on": "2019-03-10T09:32:15.663Z",
"url": "<URL of your server>",
"profile_id": <ID of the profile you want to receive notifications from>,
"enabled_notifications": [
"balance"
]
},
{
"id": "abcde123-abcd-abcd-abcd-abcde1234568",
"name": "Webhook Subscription #2",
"channel_id": "WEBHOOK",
"user_id": "TW::<your user ID>",
"status": "ENABLED",
"created_on": "2019-03-11T09:32:15.663Z",
"url": "<URL of your server>",
"profile_id": <ID of the profile you want to receive notifications from>,
"enabled_notifications": [
"transfers"
]
}
]
List all created webhook subscriptions.
Response
Field | Description | Format |
---|---|---|
id | Subscription ID | UUID |
name | Custom name of your webhook | String |
channel_id | ID of the channel through which you're receiving notifications, always equal to WEBHOOK |
String |
user_id | Your user ID | Integer |
status | Status of the subscription | String |
created_on | Timestamp when subscription was created | Timestamp |
url | URL of your server | String |
profile_id | ID of the profile you want to receive notifications from | Integer |
enabled_notifications | List of resources you would like to receive notifications about | [String] |
Get by ID
Example Request:
curl -X GET https://api.transferwise.com/v1/subscriptions/{subscriptionId}/ \
-H "Authorization: Bearer <your api token>"
Example Response:
{
"id": "abcde123-abcd-abcd-abcd-abcde1234567",
"name": "Webhook Subscription #1",
"channel_id": "WEBHOOK",
"user_id": "TW::<your user ID>",
"status": "ENABLED",
"created_on": "2019-03-10T09:32:15.663Z",
"url": "<URL of your server>",
"profile_id": <ID of the profile you want to receive notifications from>,
"enabled_notifications": [
"balance",
"transfers"
]
}
Get subscription information by ID.
Response
Field | Description | Format |
---|---|---|
id | Subscription ID | UUID |
name | Custom name of your webhook | String |
channel_id | ID of the channel through which you're receiving notifications, always equal to WEBHOOK |
String |
user_id | Your user ID | Integer |
status | Status of the subscription | String |
created_on | Timestamp when subscription was created | Date |
url | URL of your server | String |
profile_id | ID of the profile you want to receive notifications from | Integer |
enabled_notifications | List of resources you would like to receive notifications about | [String] |
Delete
Example Request:
curl -X DELETE https://api.transferwise.com/v1/subscriptions/{subscriptionId}/ \
-H "Authorization: Bearer <your api token>"
Example Response:
{
}
Delete a subscription.
Events
Events are messages that will be sent to your server as HTTP POST
requests.
They will not contain any personally identifiable information.
To acknowledge that you have successfully processed an event, make sure your server answers with a 2xx
-series HTTP status
code within 5 seconds. Otherwise, we will consider the delivery attempt as having failed and will later try to resend the message.
We will attempt to redeliver messages at increasing intervals over a two week period. We will try at most 25 times to do this.
Signature header
TransferWise public key for production environment:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvO8vXV+JksBzZAY6GhSO
XdoTCfhXaaiZ+qAbtaDBiu2AGkGVpmEygFmWP4Li9m5+Ni85BhVvZOodM9epgW3F
bA5Q1SexvAF1PPjX4JpMstak/QhAgl1qMSqEevL8cmUeTgcMuVWCJmlge9h7B1CS
D4rtlimGZozG39rUBDg6Qt2K+P4wBfLblL0k4C4YUdLnpGYEDIth+i8XsRpFlogx
CAFyH9+knYsDbR43UJ9shtc42Ybd40Afihj8KnYKXzchyQ42aC8aZ/h5hyZ28yVy
Oj3Vos0VdBIs/gAyJ/4yyQFCXYte64I7ssrlbGRaco4nKF3HmaNhxwyKyJafz19e
HwIDAQAB
How to verify signatures (in Java):
public boolean verifySignature(String encodedPublicKey, String signature, String payload) {
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.getMimeDecoder().decode(encodedPublicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
Signature sign = Signature.getInstance("SHA1WithRSA");
sign.initVerify(publicKey);
sign.update(payload.getBytes());
byte[] signatureBytes = Base64.getDecoder().decode(signature);
return sign.verify(signatureBytes);
}
Each outgoing webhook request is signed. Whilst event payloads do not contain any sensitive information, you may want to verify if the request is coming from TransferWise (however this is optional). We advise you not to process any requests where signature appears to be forged.
Each POST
request includes X-Signature
header, which contains a signature.
Test event
Example Request:
curl -X POST https://api.transferwise.com/v1/webhooks/ping \
-H "Authorization: Bearer <your api token>" \
-H "Content-Type: application/json" \
-d '{
"callback_url": "<URL of your server>"
}'
Example Response:
{
"status": "SUCCESS",
"code": 200,
"elapsed": 228
}
You can trigger a test event to be delivered to your server to check the connection between systems.
Request
Field | Description | Format |
---|---|---|
callback_url | URL of your server | String |
Response
Field | Description | Format |
---|---|---|
status | Status of test notification delivery | String |
code | HTTP status code we have received from your server | Integer |
elapsed | Time taken to deliver notification, in ms | Integer |
Transfer status change event
Example event:
{
"subscriptionId": "abcde123-abcd-abcd-abcd-abcde1234567",
"profileId": 123456,
"resourceId": {transferId},
"newState": "outgoing_payment_sent",
"eventTime": 1481713589566
}
Event
Event will be triggered every time transfer status is updated. Each event contains a timestamp. As we do not guarantee the order of events, please use that eventTime
to reconcile the order.
Field | Description | Format |
---|---|---|
subscriptionId | ID of subscription that triggers this notification | String |
profileId | ID of the profile that owns the resource | Integer |
resourceId | ID of the resource that got updated | Integer |
newState | New status of the resource, possible values are same as transfer statuses | String |
eventTime | Timestamp when update happened | Timestamp |
Balance deposit event
Example event:
{
"subscriptionId": "abcde123-abcd-abcd-abcd-abcde1234567",
"profileId": 123456,
"amount": 1000,
"currency": "GBP",
"eventType": "balance-deposit-received"
}
Event
Event will be triggered every time balance is credited.
Field | Description | Format |
---|---|---|
subscriptionId | ID of subscription that triggers this notification | String |
profileId | ID of the profile that owns the balance | Integer |
amount | Deposit amount | Decimal |
currency | Currency of the balance that got updated | String |
eventType | Type of update | String |
Errors
HTTP Status Codes
We use common HTTP status codes included in the response header to indicate success or failure.
Code | Description |
---|---|
200 | OK. Successful request. |
201 | OK. Resource created. |
400 | Bad request. Request message data did not pass validation. |
401 | Unauthorised. Not authorised to access requested data. |
403 | Forbidden. Access to requested data is forbidden. |
404 | Not Found. Requested resource does not exist. |
408 | Timeout. Operation timed out. |
422 | Unprocessable entity. Request message data did not pass validation. |
500 | TransferWise server error. |
Validation Errors
Example Validation Error:
{
"errors": [
{
"code": "error.route.not.supported",
"message": "This route is not supported",
"arguments": [
"CNY-EUR"
]
}
]
}
Data validation or violation of business rules related errors. Response could contain multiple errors.
Authentication Errors
Example Authentication Error:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
Security related errors.
System Errors
Example System Error:
{
"timestamp": "2017-02-02T13:07:39.644+0000",
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.NullPointerException",
"message": "No message available",
"path": "/v1/quotes/106031/account-requirements"
}
Something went wrong in our side.