Send money on behalf of a third party

Sending money with Wise Platform is a process with four stages. The journey for your customers starts with a quote which indicates the potential cost of the transaction, and the exchange rate. You can present this first quote to your customer as a guide, and as you go through the process, more detail is added to make the quote more precise.

Once your customer has agreed to the quote and added more information about the transaction, you can give an updated, authenticated quote along with confirmation of the rest of the transfer details. You can then fund and complete the transfer.

You must have a license to be in the flow of funds if you want to send money on behalf of your customer.

To send money on behalf of a third party:

  1. Create an unauthenticated quote using POST /quotes - this optional step allows your customer can see how much the transaction is likely to cost, and the exchange rate.
  2. Authenticate the quote. At this stage, you need to use POST /profiles to create an authenticated quote. This quote is more accurate than the unauthenticated quote, and is required to create the transfer itself.
  3. Add a recipient's account details using POST /accounts - the recipient is the party receiving the money being transferred. You receive a recipientId in the response to this request.
  4. Create the transfer using POST /profiles/{{profileId}}/third-party-trasnfers. In this request, you must include:
    • Details of your customer as the originator of the transfer.
    • The authenticated quote ID.
    • Recipient account ID.
  5. Fund the transfer using POST /profiles/{{profileId}}/transfers/{{transferId}}/payments once this step is complete the money is sent.

When sending money on behalf of your customer - you must include information about them as the originator (ultimate sender) of the transfer. You can do this by including the originator object in the POST /transfers request.

To create an unauthenticated quote, you only need the most basic information about a proposed transfer:

  • The amount of money to be sent or received.
  • The source currency and the target currency.

In return, you get an estimate of the transaction fees and exchange rate. In many cases, this quote is displayed to the customer who wants to make the transaction, so they can proceed to add more details.

Once you have the details of the recipient’s account, you can create an authenticated quote which is more precise and may include a reduced fee, depending on the recipient’s account type.

To create an unauthenticated quote:

Send a POST /quotes request including:

  • sourceCurrency - The currency that will be used to pay for the transfer.
  • targetCurrency - The currency the recipient will receive.
  • One of:
    • sourceAmount - The fixed amount of money that will be paid into the transfer. For example, I want to send 110 USD to the UK, and I want to know how much the person I am sending to will receive in GBP.
    • targetAmount - The fixed amount of money that the recipient needs to receive. For example, I want to send someone in the USA 110 USD and I want to know how much this will cost me in GBP.

In this sample request, you can see that the quote is for a target amount of 110 USD being taken from a GBP source currency.

Sample request to create an unauthenticated quote
curl -X POST https://api.sandbox.transferwise.tech/v3/quotes/ \
-H 'Authorization: Bearer <client credential token>' \
-H 'Content-type: application/json' \
-d '{
"sourceCurrency": "GBP",
"targetCurrency": "USD",
"sourceAmount": null,
"targetAmount": 110,
"pricingConfiguration": {
"fee": {
"type": "OVERRIDE",
"variable": 0.011,
"fixed": 15.42
}
}
}'

In the response, you receive a quoteId which you must use to create your transfer.

PATCH /v3/profiles/{{profileId}}/quotes/{{quoteId}}

You should update a quote using a PATCH call to add a recipient. This will update the saved quote's data based on who and where the money will be sent to.

Updating the quote with a recipient may cause the available payment options, prices and estimated delivery times to change from the original quoted amounts. This is due to the fact that sending some currencies to some destinations costs a different amount based on the payment networks we use, for example sending USD to a country outside the USA uses international rather than domestic payment networks and as such costs more, or sending CAD over the Interac network is a more expensive operation.

When updating a quote the payOut field may change to denote the payment option you should select when sending to this recipient. For example sending USD to a swift_code recipient or CAD to an interac recipient with change payOut to SWIFT or INTERAC respectively. This field defaults to BANK_TRANSFER so it can be used in all cases to help select the correct paymentOption and hence show the correct pricing to users.

If you want to provide more transparency in terms of fees charged when your customers create quote with swift recipient for global currencies, you might consider to set payOut field with SWIFT_OUR value. This will ensure that the recipient receives complete target amount.

In this case, where pricing changes after a user selects recipient, you should show a message to your customer before confirming the transfer. Please see the section on Global Currencies to learn more how and why this works and the messaging you need to display.

Request
targetAccountinteger

ID of transfer recipient, found in response from POST v1/accounts (recipient creation)

payOuttext

Optional. Preferred payout method. Default value is BANK_TRANSFER. Other possible values are BALANCE, SWIFT, SWIFT_OUR and INTERAC.

paymentMetadataobject

Optional. Used to pass additional metadata about the intended transfer.

paymentMetadata.transferNaturestring

Optional. Used to pass transfer nature for calculating proper tax amounts (IOF) for transfers to and from BRL. Accepted values are shown dynamically in transfer requirements.

pricingConfigurationobject

Required when configured for your client ID. Includes a pricingConfiguration to be used for pricing calculations with the quote. If previously passed, the existing pricingConfiguration will remain and not be updated.

pricingConfiguration.fee.typetext

Identifies the type of fee that will be configured. Options include only OVERRIDE

pricingConfiguration.fee.variabledecimal

The selected variable percentage (in decimal format) that should be used in the pricingConfiguration

pricingConfiguration.fee.fixeddecimal

The selected fixed fee (in source currency) that should be used in the pricingConfiguration

Transfer Nature for BRL

When creating or updating a quote, the transfer nature can be set. This is a requirement for transfers to or from BRL and impacts the fees we charge on the quote, specifically the IOF.

Note that IOF is determined based on the transfer nature, sender information, and recipient information. The default IOF will be included in a quote until all relevant information has been included.

Example Request
curl -X PATCH https://api.sandbox.transferwise.tech/v3/profiles/{{profileId}}/quotes/{{quoteId}} \
-H 'Authorization: Bearer <your api token>' \
-H 'Content-Type: application/merge-patch+json' \
-d '{
"targetAccount": 12345,
"payOut": "SWIFT_OUR",
"paymentMetadata": {
"transferNature": "MOVING_MONEY_BETWEEN_OWN_ACCOUNTS"
},
"pricingConfiguration": {
"fee": {
"type": "OVERRIDE",
"variable": 0.011,
"fixed": 15.42
}
}
}'

A recipient is a person or institution who is the ultimate beneficiary of your payment.

Recipient data includes three data blocks:

  • General data - the personal details of an individual and basic information about a business.
  • Bank details - account numbers, routing numbers, and other region-specific bank details.
  • Address details - country and street address of an individual or business.

General Data

  • Recipient full name
  • Legal type (private/business)
  • Currency
  • Date of Birth
  • Owned by customer

Date of Birth is optional. Its usually not required, but consult with the /account-requirements APIs to confirm if it is needed, or contact Wise Support.

Owned by customer is an optional boolean to flag to record whether this recipient is the same entity (person or business) as the one sending the funds. i.e. A user sending money to their own bank account in another country/currency. This field can be used to separate these recipients in your UI, however we do not recommend this as it adds unnecessary complexity to the solution. It is safe to ignore this field and display recipients with both true and false values.

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
  • etc.

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 the 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. Numbers are not allowed in personal recipient names.
  • 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.
  • Special characters _()'*,. are allowed for personal and business names.
  • In general the following regex describes our permitted characters for a name: [0-9A-Za-zÀ-ÖØ-öø-ÿ-_()'*,.\s].

Recipient requirements will vary depending on recipient type. A GBP example is provided here.
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 /v1/accounts

currencytext

3 character currency code

typetext

Recipient type

profileinteger

Personal or business profile ID. It is highly advised to pass the business profile ID in this field if your business account is managed by multiple users, so that the recipient can be accessed by all users authorized on the business account.

accountHolderNametext

Recipient full name

ownedByCustomerboolean

Whether this account is owned by the sending user

detailsobject

Currency specific fields

details.legalTypetext

Recipient legal type: PRIVATE or BUSINESS

details.sortCodetext

Recipient bank sort code (GBP example)

details.accountNumbertext

Recipient bank account no (GBP example)

details.dateOfBirthtext

Optional. Recipient Date of Birth in ISO 8601 date format.

Response

A complete Recipient object is returned when created.

Example Request - 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": 30000000,
"ownedByCustomer": true,
"accountHolderName": "John Doe",
"details": {
"legalType": "PRIVATE",
"sortCode": "040075",
"accountNumber": "37778842",
"dateOfBirth": "1961-01-01"
}
}'

POST /v2/profiles/{{profileId}}/third-party-transfers

When creating a transfer on behalf of a third party, you must take note that:

  • The originator datablock is required. This details the ultimate sender of funds in the transfer.
  • Depending on the legal entity type of the originator (PRIVATE or BUSINESS), the required fields vary. Please refer the two sample request examples on the right.
  • OriginalTransferId field must be used. This is your own ID for the transfer.
Request
targetAccountinteger

Recipient account ID. You can create multiple transfers to same recipient account.

quotetext

V2 quote ID. You can only create one transfer per one quote.
You cannot use same quote ID to create multiple transfers.

originalTransferIdtext

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.

details.reference (optional)text

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.

originatorgroup

Data block to capture payment originator details.

originator.legalEntityTypetext

PRIVATE or BUSINESS. Payment originator legal type.

originator.referencetext

Unique customer ID in your system. This allows us to uniquely identify each originator. Required.

originator.nametext

Data block to capture the originator name details.
Depends on the type of legal entity (PRIVATE or BUSINESS), the required fields and inputs are different.

originator.name.givenNametext

Payment originator first name. Required if legalEntityType = PRIVATE.

originator.name.middleNames (optional)text array

Payment originator middle name(s). Used only if legalEntityType = PRIVATE.

originator.name.familyNametext

Payment originator family name. Required if legalEntityType = PRIVATE.

originator.name.patronymicName (optional)text

Payment originator patronymic name. Used only if legalEntityType = PRIVATE.

originator.name.fullNametext

Payment originator full legal name. Required if legalEntityType = BUSINESS.

originator.dateOfBirthyyyy-mm-dd

Payment originator date of birth. Required if legalEntityType = PRIVATE.

originator.businessRegistrationCodetext

Payment originator business registry number / incorporation number. Required if legalEntityType = BUSINESS.

originator.address.firstLinetext

Payment originator address first line. Required

originator.address.citytext

Payment originator address city. Required

originator.address.stateCodetext

Payment originator address state code. Required if address country code in (US, CA, BR, AU). See Countries and states

originator.address.countryCodetext

Payment originator address first line. Required

originator.address.postCode (optional)text

Originator address zip code.

originator.accountDetails (optional)text

Originator account number.

Response

Returns an originator transfer object.

You need to save the transfer ID for tracking its status later via webhooks.

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.

Example Request - Personal
curl -X POST https://api.sandbox.transferwise.tech/v2/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 - Business
curl -X POST https://api.sandbox.transferwise.tech/v2/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 Request - Canadian Personal
curl -X POST https://api.sandbox.transferwise.tech/v2/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": "102-3393 Capilano Road",
"city": "North Vancouver",
"countryCode": "CA",
"postCode": "V7R 4W7"
},
"accountDetails": "<the unique account number of the customer>"
}
}'

POST /v3/profiles/{{profileId}}/transfers/{{transferId}}/payments

This API call is the final step for executing payouts when using a balance with Wise. Upon calling the endpoint, Wise will begin the processing of the transfer, depending on the status of funds.

When using the transfer by transfer settlement model, the following funding type(s) must be used:

  • BALANCE - Funds are pulled from a multi-currency account held with Wise.

When funding through the Bulk Settlement model, the following funding type(s) must be used:

  • TRUSTED_PRE_FUND_BULK - Funds for the transfer will be settled through a bulk payment at a later date.

If funding from BALANCE, and your multi-currency account does not have the required funds to complete the action, then this call will fail with an "insufficient funds" error. Once funds are added and available, you must call this endpoint again.

{{profileId}} refers to the profile that created the transfer. It can be either your personal profile ID, or your business profile ID.

Request
typetext

"BALANCE"
This indicates the type of funding you would like to apply to the transfer.

partnerReference (conditionally required)string

The transaction/payment identifier in your system, uniquely identifies the transfer in your platform. This is required for the Cross Currency Bulk Settlement model.

Response
typetext

"BALANCE"
This indicates the type of funding you would like to apply to the transfer.

statustext

"COMPLETED" or "REJECTED"

errorCodetext

Failure reason. For example "balance.payment-option-unavailable".

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 Request - Balance - Completed
{
"type": "BALANCE",
"status": "COMPLETED",
"errorCode": null
}
Example Request - Balance - Insufficient Funds
{
"type": "BALANCE",
"status": "REJECTED",
"errorCode": "transfer.insufficient_funds"
}