Testing One Off Payments
This page guides you through testing your integration - it guides you through creating payments and testing various behaviors. It does not cover all possible payment flows. For simulating payment flows and testing callbacks for each payment status, refer to Testing Payment Flows.
Testing requires you to make API calls in the Sandbox environment:
https://api-platform-sandbox.flywire.com/
Card Payments
1. Choose the recipient for the test payment.
A recipient - also called a portal - contains the information that is needed for receiving funds, like the receiving bank account, the currency in which Flywire takes payments from your payers, or specific fields your system requires to process a payment. Flywire assigns each recipient a unique identifier, called recipient ID or portal code.
You as a client can have multiple recipients, for example for different bank accounts or currencies.
The list of recipients contains all the recipients that are available to you as a client. You can display this list in your UI, for example as a drop down, so that the person creating the payment in your system can choose one of the recipients.
Parameters for the Request Body
No request body needed.
Optional Query Parameters for Pagination
This endpoint supports pagination. If you are not providing any pagination parameters, the response is returned with default pagination settings.
Pagination parameters are added as query parameters with the request in the format {endpoint_path}?page=2&per_page=10
The default setting is:
page=1 (start on page 1)
per_page=10 (display 10 entries per page)
Enables you to access a specific page of the results.
Possible values: Any positive number except zero.
Enables you to define how many results will be included per page.
Possible values: min 1, max 100
curl https://base-url-placeholder/recipients?page=1&per_page=100
-X GET
-H "Content-Type: application/json"
-H "X-Authentication-Key: {api_key}" 2. Create a Checkout Session.
Parameters for the Request Body
The type of the Checkout Session. Must be one_off for One Off Payments.
Must be cards.
charge_intent object
Must be one_off (since this is a One Off Payment).
payor object
These fields enable you to pass payer data to pre-fill the fields of the form.
For a description of all fields and their valid values form see:
-
Payment Element if you are using Flywire Elements
-
Checkout Experience if you are using Checkout
-
Pre-filling fields is optional. If no values are provided, the fields will be empty for the payer to complete.
-
Pre-filling fields alone does not affect if fields are editable. Pre-filled fields remain editable unless you explicitly made them read-only or hide them via the settings.
Best practice
Before pre-filling payer fields, consider who the actual payer is.
The form asks for the cardholder or bank account owner’s information. There can be cases when the personal data you have on stored (for example, in your ERP system) is different from the data for the actual payer. Always consider which information you store in your system and how useful it is for pre-filling fields.
Example: Students log into your school portal to pay tuition. In most cases, their parents pay the tuition with their credit card. If you automatically pre-fill the payer fields with the student's profile info, every student has to correct the info and change it to their parent's information.
This distinction is crucial if you plan to hide fields or make them read-only. If you use the wrong data for pre-filling fields and make it impossible for the payer to change it, you could prevent them from completing the payment.
You can to set these fields to hidden or read-only for the payer through settings in the options object.
When using Elements, you can control which payer fields can be edited by your payer - either by setting them to read-only or be completely hiding the field from the payer.
|
You can configure read-only at three levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field > Global Form This means Smart Rendering settings win over individual field settings, and individual field settings win over global form settings. |
|
You can configure the visibility of fields at two levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field This means Smart Rendering settings win over individual field settings. |
What happens if something goes wrong? - Automatic Field Unlocking
All payer fields are required to send the form. If your settings would prevent the payer from submitting the form - for example you're hiding the email field but provided an invalid address- the field automatically becomes visible and editable.
Automatic field unlocking happens for a hidden or read-only field when:
-
you didn't submit a value through the Checkout Session (results in an empty field for the payer to fill out)
-
you submitted an invalid value through the Checkout Session (results in a field showing the invalid value, highlighted with an error message so that the payer can correct it)
The payer's first name.
The field only accepts Latin characters from A-Z and 0-9. Max. 256 characters.
The last name (family name) of the payer.
The field only accepts Latin characters from A-Z and 0-9. Max. 256 characters.
The payer's address.
The field only accepts Latin characters from A-Z and 0-9 and the following special characters:
-
, (comma)
-
/ (slash)
-
- (hyphen)
The address can’t be a PO box. If the words "PO" or “box” is detected in this field, it will show an error message.
The payer's city.
The field only accepts Latin characters from A-Z and 0-9. Max. 256 characters.
The city needs to contain at least a vowel and have more than one character. For example, NY won’t be accepted and must be corrected to New York.
The country of the payer.
Format:
Two-letter format (ISO 3166-1 alpha-2), for example US for USA or GB for the United Kingdom.
The state field is only displayed when the country is “United States” or “China”. When it is displayed, it is required for sending the form.
The state where the payer resides in.
Format:
Only the second part of the ISO 3166-2 code, for example for US-NY the value is NY.
The phone number of the payer (including the country code).
Validation rules when you're pre-filling the field via the API:
To fill out the country code field of the phone number, you need to put 00 in front of it. For example, "0044123456" will be turned into "44" in the country code field and "123456" in the phone number field. If you don't use 00, the country code field will be left empty and only the phone number field will be populated.
Validation rules in the Elements form:
The country code can be picked from a dropdown with fixed values. The phone number field only accepts digits. Max. 15 digits.
The payer's email address.
The field accepts Latin characters from A-Z and 0-9 and the following special characters:
-
+ (plus)
-
_ (underscore)
Max. 256 characters.
The payer's zip code.
If the country is “United States” the field only accepts exactly 5 digits, for any other country it accepts a maximum of 10 digits or characters.
options object
These settings affect how the Elements form is displayed to your payer.
When using Elements, you can control which payer fields can be edited by your payer - either by setting them to read-only or be completely hiding the field from the payer.
|
You can configure read-only at three levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field > Global Form This means Smart Rendering settings win over individual field settings, and individual field settings win over global form settings. |
|
You can configure the visibility of fields at two levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field This means Smart Rendering settings win over individual field settings. |
What happens if something goes wrong? - Automatic Field Unlocking
All payer fields are required to send the form. If your settings would prevent the payer from submitting the form - for example you're hiding the email field but provided an invalid address- the field automatically becomes visible and editable.
Automatic field unlocking happens for a hidden or read-only field when:
-
you didn't submit a value through the Checkout Session (results in an empty field for the payer to fill out)
-
you submitted an invalid value through the Checkout Session (results in a field showing the invalid value, highlighted with an error message so that the payer can correct it)
form object
Controls the label for the action button of the UI form.
Possible values
-
save (default value)
-
next
-
pay
Note: The label will be translated according to the locale parameter.
The language you want to translate the form to. The localization affects the labels of the form fields and the action button.
The default is English (“en”).
| Language | Value for locale |
|---|---|
| English | en |
| Spanish | es-ES |
| Chinese | zh-CN |
| Korean | ko |
| Portuguese | pt-PT |
| Japanese | ja |
| French | fr-FR |
| Bahasa Indonesia | id |
| Arabic | ar |
| Vietnamese | vi |
| Italian | it-IT |
| German | de-DE |
Controls if the "Powered by Flywire" logo is shown at the bottom of the form.
true displays the logo, false hides the logo.
You can use this parameter to hide the amount you will receive in the Elements form to avoid redundant info if your UI already displays it. If hidden, you must ensure the amount you will receive remains visible elsewhere for transparency. The form will only display the amount the payer has to send, which may differ from your requested amount due to FX or fees.
If this parameter is not provided, the default is true.
Possible values:
Controls if the payer fields in the Element form can be edited by the payer:
-
true: All payer fields will be displayed but are not editable.
-
false (default): All payer fields will be displayed and are editable.
You can set all fields to read-only and then overwrite the setting for individual fields.
When using Elements, you can control which payer fields can be edited by your payer - either by setting them to read-only or be completely hiding the field from the payer.
|
You can configure read-only at three levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field > Global Form This means Smart Rendering settings win over individual field settings, and individual field settings win over global form settings. |
|
You can configure the visibility of fields at two levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field This means Smart Rendering settings win over individual field settings. |
What happens if something goes wrong? - Automatic Field Unlocking
All payer fields are required to send the form. If your settings would prevent the payer from submitting the form - for example you're hiding the email field but provided an invalid address- the field automatically becomes visible and editable.
Automatic field unlocking happens for a hidden or read-only field when:
-
you didn't submit a value through the Checkout Session (results in an empty field for the payer to fill out)
-
you submitted an invalid value through the Checkout Session (results in a field showing the invalid value, highlighted with an error message so that the payer can correct it)
payor_fields object
Here you can define hidden and read_only settings for individual payer fields.
-
first_name
-
last_name
-
business_name (only displayed for direct debit payments with account type business)
-
address
-
city
-
country
-
state
-
phone
-
email
-
zip
If you defined a global setting via the payor_fields_read_only parameter, the settings for an individual field will overwrite the global setting.
When using Elements, you can control which payer fields can be edited by your payer - either by setting them to read-only or be completely hiding the field from the payer.
|
You can configure read-only at three levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field > Global Form This means Smart Rendering settings win over individual field settings, and individual field settings win over global form settings. |
|
You can configure the visibility of fields at two levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field This means Smart Rendering settings win over individual field settings. |
What happens if something goes wrong? - Automatic Field Unlocking
All payer fields are required to send the form. If your settings would prevent the payer from submitting the form - for example you're hiding the email field but provided an invalid address- the field automatically becomes visible and editable.
Automatic field unlocking happens for a hidden or read-only field when:
-
you didn't submit a value through the Checkout Session (results in an empty field for the payer to fill out)
-
you submitted an invalid value through the Checkout Session (results in a field showing the invalid value, highlighted with an error message so that the payer can correct it)
Example:
first_name object
Controls if this payer field will be visible to the payer in the Element form:
-
true: This field will not be displayed in the form.
-
false (default): This field will be displayed in the form.
Controls if this payer field will be editable for the payer in the Element form:
-
true: This field will not be editable in the form.
-
false (default): This field will be editable in the form.
recipient object
Contains the fields of the recipient.
fields array
It depends on the recipient which fields are optional or required. If a field is required, you must provide it here. Optional fields can be left out.
You have two options:
Checking via the API
You can check which fields are required for a recipient (portal) with this request (replace {recipientId} with the recipient ID):
Required fields have the required parameter set to true. For more info see Getting Details about a Recipient.
Checking online
You can check which fields are required by checking your portal configuration.
Identifier of the field.
The value for this field.
items array
An item is something that your payer can pay for (for example: tuition fees, housing, etc.). When you create a payment, you display the items to your payer and they can choose for which items they want to pay. How many items there are depends on the recipient's configuration.
You can only use one item in this request. The id of the item must be called default.
Identifier of the item.
You can only use one item in this request. The id of the item must be called default.
The amount for this item in the billing currency,
The billing currency is the currency in which the recipient of the payment is billing their payer. The billing currency depends on the
The amount is specified in the smallest unit of the currency, called subunits. For example, in USD, the subunit is cents, and 100 cents equal 1 USD. So, an amount of 12025 (cents) is equivalent to 120.25 USD.
Note that the subunit-to-unit ratio varies by currency, it is not always 100. See Currencies for the subunits of each currency.
The notifications URL enables you to receive callbacks about the payment status (see Payment Status Notifications).
The notifications URL is the dynamic URL for receiving callbacks.
There are two different URLs for receiving callbacks:
Static URL
For API integrations:
When you set up your application that accesses the Flywire API, you had the option to define a notifications URL. This is the static notifications URL. Callbacks will be sent to this URL for all payments you created via the Flywire API.
The recipient of a payment may also have a static notifications URL defined which might be different from your static notifications URL as a client. In that case, callbacks will also be sent to the recipient's notifications URL.For other integrations:
When you set up your portal together with Flywire, you had the option to define a callback URL for that portal. Callbacks will be sent to this URL for all payments for this portal.
If you don't use a static callback URL yet and want to start using it, please contact the Solutions team.
Dynamic URL
The URL you can set in a parameter when you are creating a payment is the dynamic notifications URL. Since this URL can be different for every payment you create, it is called dynamic.
How defining static and dynamic URLs affect callbacks
= not set |
= set |
| Static URL |
Dynamic URL |
Result |
|
|
You won't receive notifications. |
|
|
You'll receive notifications to your static URL. |
|
|
For API integrations: The dynamic URL will override the static URL and you'll receive notifications only to the dynamic URL. For other integrations: You'll receive callbacks to both URLs. This is called "dual callback URL". A dual callback URL means you defined a static URL in your portal and you are sending callbacks to a different callback URL via the parameter for the payment. In this case, callbacks will be sent to both URLs. This
approach can be useful if you want to update two separate systems.
|
|
|
You'll receive notifications to your dynamic URL |
The external reference.
The external reference helps you to identify a payment, since the Flywire-generated payment reference might not be the way you typically identify payments. With the external reference, you can enter your own identifier, such as an ID or invoice number.
The external reference is included in all status notifications to help you map a payment to a callback notification. (see Payment Status Notifications)
The recipient ID (also called portal code).
The recipient ID identifies the recipient (also called portal). The recipient ID has been assigned by Flywire when the recipient has been set up.
Format:
Either: 3 letters (ABC)
Or: 5 alphanumeric characters, always starting with a letter (ABC1D)
You can use this request to get a list of all recipients that are available to you as a client and what their recipient ID is:
For details see Getting a List of all available Recipients.
The payor_id depends on how you want to uniquely identify a payer. Usually, you use an ID from another system, for example your ERP. Spaces are not allowed.
When you are creating follow-up payments you must use the same payor_id you used when you created the Checkout Session.
With this parameter you can decide if you want to send the emails to your payer yourself or if you want Flywire to automatically send the emails for you:
-
true: Flywire sends the emails for you
-
false: You send the emails yourself
Default: false
Refer to One Off Payments: Emails to Your Payer for which emails need to be send for One Off Payments.
Mandatory emails
If you keep the default setting (false), you have to send mandatory emails to your payer yourself, see One Off Payments: Emails to Your Payer.
curl https://base-url-placeholder/checkout/sessions
-X POST
-H "Content-Type: application/json"
-H "X-Authentication-Key: {api_key}"
-d '{
"type": "one_off",
"schema": "cards",
"charge_intent": {
"mode": "one_off"
},
"payor": {
"first_name": "Peter",
"last_name": "Payer",
"address": "123 High Street",
"city": "London",
"country": "GB",
"state": "",
"phone": "0044123456789",
"email": "[email protected]",
"zip": "SW1A 1AA"
},
"options": {
"form": {
"action_button": "save",
"locale": "en",
"show_flywire_logo": true,
"show_amount_to": false,
"payor_fields_read_only": true,
"payor_fields": {
"first_name": {
"hidden": false,
"read_only": false
},
"last_name": {
"hidden": true,
"read_only": false
}
}
},
"recipient": {
"fields": [
{
"id": "custom_field_1",
"value": "ID12345"
},
{
"id": "custom_field_2",
"value": "2020"
}
]
},
"items": [
{
"id": "default",
"amount": 33000
}
],
"notifications_url": "https://webhook.site/9bf9cf8d-1d8c-46d1-b147-ca5841ff2ede",
"external_reference": "My payment reference",
"recipient_id": "TQQ",
"payor_id": "my_payer_ID",
"enable_email_notifications": true
}
You'll receive a URL for the UI form in the API response.
3. Open the URL for the form in your browser.
4. In your browser, add the event listener code to the page.
|
Open the developer tools for your browser and add the following event listener code via the console. |
|
5. Fill out the payer information fields.
The fields do not affect the test scenario, you can fill them with any data you want.
6. Enter the magic values and credit card data for your scenario.
-
Enter magic values as the card holder’s first and last name depending on which scenario you want to test:
First Name Last Name Will 3DS be triggered? Will the payment be successful? Statuses for the payment Scenario Description MAGICVALUE AUTH yes
yes
Initiated
→
Processed
→
Guaranteed"Happy path" with 3DS
Use this scenario if you want to test 3DS behavior.MAGICVALUE APPROVED no
yes
Initiated
→
Processed
→
Guaranteed"Happy path" without 3DS
Use this scenario if you want to skip the 3DS verification.
PAYMENT DELIVERED no
yes
Initiated →
Processed →
Guaranteed →
Delivered"Happy path" with delivered payments
Use this scenario if you want to create payments that go into the delivered status.
MAGICVALUE EXPIRED no
no
Initiated →
FailedCard is expired
Use these scenarios if you want to test payments that fail. MAGICVALUE FRAUD no
no
Initiated →
FailedCard is declined
MAGICVALUE NOT ENOUGH BALANCE no
no
Initiated →
FailedCard doesn't have enough balance
-
Use one of the demo credit cards for the credit card details:
Does it matter which card I use for the scenario?
No. All test cards work with all magic values and trigger the chosen scenario.
What is the purpose of the different test cards?
You can try out different cards from different countries to test the behavior of the element when card country and payer country don't match.
How can non-matching countries affect the element behavior?
Choose currency
If the card currency doesn't match the currency of the payer's country, and if there is an option to pay in either of them, the payer can choose which currency they want to pay in. They have two options: The currency of the card they are paying with and the currency of the country they have chosen for their address.

Accept to pay in card currency
This message appears if the card currency doesn't match the currency of the payer's country and there is no option to pay in the country's currency.
After clicking "Accept", the payer can proceed to pay. Alternatively, they can use a different card for the payment.

The demo cards must be used together with cardholder name magic values.
Number Expiration date CVV Currency Issuing Country Type Visa
4010 1000 0000 0016 03/30 737 EUR DE Debit 4988 4388 4000 0012 03/30 737 EUR ES Debit 4242 4201 0000 0017 03/30 737 GBP GB Credit 4761 3600 0000 0017 03/30 737 INR IN Debit 4111 1111 1111 1111 03/30 737 USD US Credit Mastercard
2222 4000 1000 0016 03/30 737 CAD CA Credit 5163 6136 0000 0014 03/30 737 AUD AU Debit 5252 5202 0000 0017 03/30 737 JPY JP Debit 5454 5454 5454 5454 03/30 737 USD US Credit American Express (Amex)
3700 0000 0000 002 03/30 7373 USD US
Credit
7. Send the form.
|
If you used a scenario that triggers 3DS authentication, you now see the Flywire 3DS authentication simulator. Enter the word password in the password field and click on continue to complete the authentication. |
8. Check the console in your browser's development tools.
The event listener will return the URL for confirming the Checkout Session.
9. Confirm the Checkout Session.
As a security measure to ensure that you are the one who created the session, you have to confirm the Checkout Session.
How to Resolve the Path Placeholders of the Endpoint
You don't need to manually resolve the {ID} in the endpoint, as Flywire provides the fully resolved URL via the postMessage (see 3. The postMessage of the Event Listener).
Why should you use the confirm url from the postMessage?
Parameters for the Request Body
No request body needed.
curl https://base-url-placeholder/checkout/sessions/494d2e9d-c0c9-407c-9094-5b3b2a02c00f/confirm
-X POST
-H "Content-Type: application/json"
-H "X-Authentication-Key: {api_key}" You'll receive the payment reference in the response.
10. Check the notifications.
The payment is now created according to your scenario. You'll receive the following notifications:
- For "Success" Scenarios
- For "Failed" Scenarios
Within the next 30 seconds:
Initiated
Processed
Guaranteed
This is the end of this scenario.
Within the next 1 minute:
Initiated
Failed (immediately after initiated)
This is the end of this scenario.
Bank Transfer Payments
1. Choose the recipient for the test payment.
A recipient - also called a portal - contains the information that is needed for receiving funds, like the receiving bank account, the currency in which Flywire takes payments from your payers, or specific fields your system requires to process a payment. Flywire assigns each recipient a unique identifier, called recipient ID or portal code.
You as a client can have multiple recipients, for example for different bank accounts or currencies.
The list of recipients contains all the recipients that are available to you as a client. You can display this list in your UI, for example as a drop down, so that the person creating the payment in your system can choose one of the recipients.
Parameters for the Request Body
No request body needed.
Optional Query Parameters for Pagination
This endpoint supports pagination. If you are not providing any pagination parameters, the response is returned with default pagination settings.
Pagination parameters are added as query parameters with the request in the format {endpoint_path}?page=2&per_page=10
The default setting is:
page=1 (start on page 1)
per_page=10 (display 10 entries per page)
Enables you to access a specific page of the results.
Possible values: Any positive number except zero.
Enables you to define how many results will be included per page.
Possible values: min 1, max 100
curl https://base-url-placeholder/recipients?page=1&per_page=100
-X GET
-H "Content-Type: application/json"
-H "X-Authentication-Key: {api_key}" 2. Create a Checkout Session.
Parameters for the Request Body
The type of the Checkout Session. Must be one_off for One Off Payments.
There are two options for the bank transfer element. They use the same form for collecting the payer details, but differ in the instructions they display:
| bank_transfer |
Standard bank transfer Use this for all international and local transfers (US, UK, Europe, etc.) except domestic Mexico SPEI. The instructions provide dynamically the correct bank account details based on the payer's country (e.g., ABA for the US, IBAN for Europe, or SWIFT for others). |
| bank_transfer_spei |
SPEI bank transfer (Mexico only) Use this exclusively for domestic payments within Mexico. The instructions provide the specific 18-digit CLABE required to process payments via the SPEI network. |
charge_intent object
Must be one_off (since this is a One Off Payment).
payor object
These fields enable you to pass payer data to pre-fill the fields of the form.
For a description of all fields and their valid values form see:
-
Payment Element if you are using Flywire Elements
-
Checkout Experience if you are using Checkout
-
Pre-filling fields is optional. If no values are provided, the fields will be empty for the payer to complete.
-
Pre-filling fields alone does not affect if fields are editable. Pre-filled fields remain editable unless you explicitly made them read-only or hide them via the settings.
Best practice
Before pre-filling payer fields, consider who the actual payer is.
The form asks for the cardholder or bank account owner’s information. There can be cases when the personal data you have on stored (for example, in your ERP system) is different from the data for the actual payer. Always consider which information you store in your system and how useful it is for pre-filling fields.
Example: Students log into your school portal to pay tuition. In most cases, their parents pay the tuition with their credit card. If you automatically pre-fill the payer fields with the student's profile info, every student has to correct the info and change it to their parent's information.
This distinction is crucial if you plan to hide fields or make them read-only. If you use the wrong data for pre-filling fields and make it impossible for the payer to change it, you could prevent them from completing the payment.
You can to set these fields to hidden or read-only for the payer through settings in the options object.
When using Elements, you can control which payer fields can be edited by your payer - either by setting them to read-only or be completely hiding the field from the payer.
|
You can configure read-only at three levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field > Global Form This means Smart Rendering settings win over individual field settings, and individual field settings win over global form settings. |
|
You can configure the visibility of fields at two levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field This means Smart Rendering settings win over individual field settings. |
What happens if something goes wrong? - Automatic Field Unlocking
All payer fields are required to send the form. If your settings would prevent the payer from submitting the form - for example you're hiding the email field but provided an invalid address- the field automatically becomes visible and editable.
Automatic field unlocking happens for a hidden or read-only field when:
-
you didn't submit a value through the Checkout Session (results in an empty field for the payer to fill out)
-
you submitted an invalid value through the Checkout Session (results in a field showing the invalid value, highlighted with an error message so that the payer can correct it)
The payer's first name.
The field only accepts Latin characters from A-Z and 0-9. Max. 256 characters.
The last name (family name) of the payer.
The field only accepts Latin characters from A-Z and 0-9. Max. 256 characters.
The payer's address.
The field only accepts Latin characters from A-Z and 0-9 and the following special characters:
-
, (comma)
-
/ (slash)
-
- (hyphen)
The address can’t be a PO box. If the words "PO" or “box” is detected in this field, it will show an error message.
The payer's city.
The field only accepts Latin characters from A-Z and 0-9. Max. 256 characters.
The city needs to contain at least a vowel and have more than one character. For example, NY won’t be accepted and must be corrected to New York.
The country of the payer.
Format:
Two-letter format (ISO 3166-1 alpha-2), for example US for USA or GB for the United Kingdom.
The state field is only displayed when the country is “United States” or “China”. When it is displayed, it is required for sending the form.
The state where the payer resides in.
Format:
Only the second part of the ISO 3166-2 code, for example for US-NY the value is NY.
The phone number of the payer (including the country code).
Validation rules when you're pre-filling the field via the API:
To fill out the country code field of the phone number, you need to put 00 in front of it. For example, "0044123456" will be turned into "44" in the country code field and "123456" in the phone number field. If you don't use 00, the country code field will be left empty and only the phone number field will be populated.
Validation rules in the Elements form:
The country code can be picked from a dropdown with fixed values. The phone number field only accepts digits. Max. 15 digits.
The payer's email address.
The field accepts Latin characters from A-Z and 0-9 and the following special characters:
-
+ (plus)
-
_ (underscore)
Max. 256 characters.
The payer's zip code.
If the country is “United States” the field only accepts exactly 5 digits, for any other country it accepts a maximum of 10 digits or characters.
options object
These settings affect how the Elements form is displayed to your payer.
When using Elements, you can control which payer fields can be edited by your payer - either by setting them to read-only or be completely hiding the field from the payer.
|
You can configure read-only at three levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field > Global Form This means Smart Rendering settings win over individual field settings, and individual field settings win over global form settings. |
|
You can configure the visibility of fields at two levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field This means Smart Rendering settings win over individual field settings. |
What happens if something goes wrong? - Automatic Field Unlocking
All payer fields are required to send the form. If your settings would prevent the payer from submitting the form - for example you're hiding the email field but provided an invalid address- the field automatically becomes visible and editable.
Automatic field unlocking happens for a hidden or read-only field when:
-
you didn't submit a value through the Checkout Session (results in an empty field for the payer to fill out)
-
you submitted an invalid value through the Checkout Session (results in a field showing the invalid value, highlighted with an error message so that the payer can correct it)
form object
Controls the label for the action button of the UI form.
Possible values
-
save (default value)
-
next
-
pay
Note: The label will be translated according to the locale parameter.
The language you want to translate the form to. The localization affects the labels of the form fields and the action button.
The default is English (“en”).
| Language | Value for locale |
|---|---|
| English | en |
| Spanish | es-ES |
| Chinese | zh-CN |
| Korean | ko |
| Portuguese | pt-PT |
| Japanese | ja |
| French | fr-FR |
| Bahasa Indonesia | id |
| Arabic | ar |
| Vietnamese | vi |
| Italian | it-IT |
| German | de-DE |
Controls if the "Powered by Flywire" logo is shown at the bottom of the form.
true displays the logo, false hides the logo.
You can use this parameter to hide the amount you will receive in the Elements form to avoid redundant info if your UI already displays it. If hidden, you must ensure the amount you will receive remains visible elsewhere for transparency. The form will only display the amount the payer has to send, which may differ from your requested amount due to FX or fees.
If this parameter is not provided, the default is true.
Possible values:
Controls if the payer fields in the Element form can be edited by the payer:
-
true: All payer fields will be displayed but are not editable.
-
false (default): All payer fields will be displayed and are editable.
You can set all fields to read-only and then overwrite the setting for individual fields.
When using Elements, you can control which payer fields can be edited by your payer - either by setting them to read-only or be completely hiding the field from the payer.
|
You can configure read-only at three levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field > Global Form This means Smart Rendering settings win over individual field settings, and individual field settings win over global form settings. |
|
You can configure the visibility of fields at two levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field This means Smart Rendering settings win over individual field settings. |
What happens if something goes wrong? - Automatic Field Unlocking
All payer fields are required to send the form. If your settings would prevent the payer from submitting the form - for example you're hiding the email field but provided an invalid address- the field automatically becomes visible and editable.
Automatic field unlocking happens for a hidden or read-only field when:
-
you didn't submit a value through the Checkout Session (results in an empty field for the payer to fill out)
-
you submitted an invalid value through the Checkout Session (results in a field showing the invalid value, highlighted with an error message so that the payer can correct it)
payor_fields object
Here you can define hidden and read_only settings for individual payer fields.
-
first_name
-
last_name
-
business_name (only displayed for direct debit payments with account type business)
-
address
-
city
-
country
-
state
-
phone
-
email
-
zip
If you defined a global setting via the payor_fields_read_only parameter, the settings for an individual field will overwrite the global setting.
When using Elements, you can control which payer fields can be edited by your payer - either by setting them to read-only or be completely hiding the field from the payer.
|
You can configure read-only at three levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field > Global Form This means Smart Rendering settings win over individual field settings, and individual field settings win over global form settings. |
|
You can configure the visibility of fields at two levels: |
|
|
What happens if a field has conflicting settings at multiple levels? Smart Rendering > Individual Field This means Smart Rendering settings win over individual field settings. |
What happens if something goes wrong? - Automatic Field Unlocking
All payer fields are required to send the form. If your settings would prevent the payer from submitting the form - for example you're hiding the email field but provided an invalid address- the field automatically becomes visible and editable.
Automatic field unlocking happens for a hidden or read-only field when:
-
you didn't submit a value through the Checkout Session (results in an empty field for the payer to fill out)
-
you submitted an invalid value through the Checkout Session (results in a field showing the invalid value, highlighted with an error message so that the payer can correct it)
Example:
first_name object
Controls if this payer field will be visible to the payer in the Element form:
-
true: This field will not be displayed in the form.
-
false (default): This field will be displayed in the form.
Controls if this payer field will be editable for the payer in the Element form:
-
true: This field will not be editable in the form.
-
false (default): This field will be editable in the form.
recipient object
Contains the fields of the recipient.
fields array
It depends on the recipient which fields are optional or required. If a field is required, you must provide it here. Optional fields can be left out.
You have two options:
Checking via the API
You can check which fields are required for a recipient (portal) with this request (replace {recipientId} with the recipient ID):
Required fields have the required parameter set to true. For more info see Getting Details about a Recipient.
Checking online
You can check which fields are required by checking your portal configuration.
Identifier of the field.
The value for this field.
items array
An item is something that your payer can pay for (for example: tuition fees, housing, etc.). When you create a payment, you display the items to your payer and they can choose for which items they want to pay. How many items there are depends on the recipient's configuration.
You can only use one item in this request. The id of the item must be called default.
Identifier of the item.
You can only use one item in this request. The id of the item must be called default.
The amount for this item in the billing currency,
The billing currency is the currency in which the recipient of the payment is billing their payer. The billing currency depends on the
The amount is specified in the smallest unit of the currency, called subunits. For example, in USD, the subunit is cents, and 100 cents equal 1 USD. So, an amount of 12025 (cents) is equivalent to 120.25 USD.
Note that the subunit-to-unit ratio varies by currency, it is not always 100. See Currencies for the subunits of each currency.
The notifications URL enables you to receive callbacks about the payment status (see Payment Status Notifications).
The notifications URL is the dynamic URL for receiving callbacks.
There are two different URLs for receiving callbacks:
Static URL
For API integrations:
When you set up your application that accesses the Flywire API, you had the option to define a notifications URL. This is the static notifications URL. Callbacks will be sent to this URL for all payments you created via the Flywire API.
The recipient of a payment may also have a static notifications URL defined which might be different from your static notifications URL as a client. In that case, callbacks will also be sent to the recipient's notifications URL.For other integrations:
When you set up your portal together with Flywire, you had the option to define a callback URL for that portal. Callbacks will be sent to this URL for all payments for this portal.
If you don't use a static callback URL yet and want to start using it, please contact the Solutions team.
Dynamic URL
The URL you can set in a parameter when you are creating a payment is the dynamic notifications URL. Since this URL can be different for every payment you create, it is called dynamic.
How defining static and dynamic URLs affect callbacks
= not set |
= set |
| Static URL |
Dynamic URL |
Result |
|
|
You won't receive notifications. |
|
|
You'll receive notifications to your static URL. |
|
|
For API integrations: The dynamic URL will override the static URL and you'll receive notifications only to the dynamic URL. For other integrations: You'll receive callbacks to both URLs. This is called "dual callback URL". A dual callback URL means you defined a static URL in your portal and you are sending callbacks to a different callback URL via the parameter for the payment. In this case, callbacks will be sent to both URLs. This
approach can be useful if you want to update two separate systems.
|
|
|
You'll receive notifications to your dynamic URL |
The external reference.
The external reference helps you to identify a payment, since the Flywire-generated payment reference might not be the way you typically identify payments. With the external reference, you can enter your own identifier, such as an ID or invoice number.
The external reference is included in all status notifications to help you map a payment to a callback notification. (see Payment Status Notifications)
The recipient ID (also called portal code).
The recipient ID identifies the recipient (also called portal). The recipient ID has been assigned by Flywire when the recipient has been set up.
Format:
Either: 3 letters (ABC)
Or: 5 alphanumeric characters, always starting with a letter (ABC1D)
You can use this request to get a list of all recipients that are available to you as a client and what their recipient ID is:
For details see Getting a List of all available Recipients.
The payor_id depends on how you want to uniquely identify a payer. Usually, you use an ID from another system, for example your ERP. Spaces are not allowed.
When you are creating follow-up payments you must use the same payor_id you used when you created the Checkout Session.
With this parameter you can decide if you want to send the emails to your payer yourself or if you want Flywire to automatically send the emails for you:
-
true: Flywire sends the emails for you
-
false: You send the emails yourself
Default: false
Refer to One Off Payments: Emails to Your Payer for which emails need to be send for One Off Payments.
Mandatory emails
If you keep the default setting (false), you have to send mandatory emails to your payer yourself, see One Off Payments: Emails to Your Payer.
curl https://base-url-placeholder/checkout/sessions
-X POST
-H "Content-Type: application/json"
-H "X-Authentication-Key: {api_key}"
-d '{
"type": "one_off",
"schema": "bank_transfer",
"charge_intent": {
"mode": "one_off"
},
"payor": {
"first_name": "Peter",
"last_name": "Payer",
"address": "123 High Street",
"city": "London",
"country": "GB",
"state": "",
"phone": "0044123456789",
"email": "[email protected]",
"zip": "SW1A 1AA"
},
"options": {
"form": {
"action_button": "save",
"locale": "en",
"show_flywire_logo": true,
"show_amount_to": false,
"payor_fields_read_only": true,
"payor_fields": {
"first_name": {
"hidden": false,
"read_only": false
},
"last_name": {
"hidden": true,
"read_only": false
}
}
},
"recipient": {
"fields": [
{
"id": "custom_field_1",
"value": "ID12345"
},
{
"id": "custom_field_2",
"value": "2020"
}
]
},
"items": [
{
"id": "default",
"amount": 33000
}
],
"notifications_url": "https://webhook.site/9bf9cf8d-1d8c-46d1-b147-ca5841ff2ede",
"external_reference": "My payment reference",
"recipient_id": "TQQ",
"payor_id": "my_payer_ID",
"enable_email_notifications": true
}
You'll receive a URL for the UI form in the API response.
3. Open the URL for the form in your browser.
4. In your browser, add the event listener code to the page.
|
Open the developer tools for your browser and add the following event listener code via the console. |
|
5. Fill out the payer information fields.
Fill the payer information fields with dummy data. You have two options depending on what you want to test:
A) You don't use any magic values in the payer name fields.
This enables you to test displaying the instructions element on demand after you displayed the bank transfer payment element. You need a test payment that stays in status
Initiated for this, and any non-magic-value test name like Peter Payer will put the payment in this status.
Why does the payment need to be in
Initiated?
Bank transfer instructions are only available as long as the payment is in status
Initiated. If you try to display the instructions when the payment is in any other status, a blank page will be displayed.
B) You use magic values in the payer name fields to make the test payment go into a specific status.
Note that if you do this, you won't be able to test displaying the instructions element on demand.
Why?
Bank transfer instructions are only available as long as the payment is in status
Initiated. If you try to display the instructions when the payment is in any other status, a blank page will be displayed.
First Name Last Name Statuses for payments with this card Scenario Description PAYMENT GUARANTEED
Initiated →
Processed →
Guaranteed → moved daily at 4:00 PM UTC (Monday through Friday)
Delivered
"Happy path" with realistic delivered payments
Use this scenario if you want to create payments that go into the delivered status after 24 hours.
PAYMENT DELIVERED
Initiated →
Processed →
Guaranteed →
Delivered
"Happy path" with immediately delivered payments
Use this scenario if you want to create payments that go into the delivered status immediately.
In both cases, the instructions will be displayed to you after filling out the payer information and confirming them.
6. Check the console in your browser's development tools.
The event listener will return the URL for confirming the Checkout Session.
7. Confirm the Checkout Session.
Confirm the session using the url you received from the event listener.
As a security measure to ensure that you are the one who created the session, you have to confirm the Checkout Session.
How to Resolve the Path Placeholders of the Endpoint
You don't need to manually resolve the {ID} in the endpoint, as Flywire provides the fully resolved URL via the postMessage (see 3. The postMessage of the Event Listener).
Why should you use the confirm url from the postMessage?
Parameters for the Request Body
No request body needed.
curl https://base-url-placeholder/checkout/sessions/494d2e9d-c0c9-407c-9094-5b3b2a02c00f/confirm
-X POST
-H "Content-Type: application/json"
-H "X-Authentication-Key: {api_key}" The response returns the url you need to display the instructions on demand.
The payment reference.
The payment reference is an ID generated by Flywire to identify a payment.
Format:
Either: ABC123456789
3-letter portal/recipient ID 9 numbers
Or: 1AB12CD452ABC1D
number 8 alphanums number 5-alphanum portal/recipient ID
With the payment reference, the payment can be tracked through the different stages of the payment process.
The payment reference is also important in other situations, for example:
-
When a payer is using bank transfer as payment method, they usually must provide the payment reference when sending the funds.
-
The payment reference helps Flywire to identify the payment if you or your payer needs support.
charge_info object
The payment amount in the payer currency.
The amount is specified in the smallest unit of the currency, called subunits. For example, in USD, the subunit is cents, and 100 cents equal 1 USD. So, an amount of 12025 (cents) is equivalent to 120.25 USD.
Note that the subunit-to-unit ratio varies by currency, it is not always 100. See Currencies for the subunits of each currency.
The payer currency.
Format:
Three-letter ISO 4217 currency code, for example EUR.
payment_instructions object
The payment instructions allow you to display the bank transfer instructions on demand via the instructions element.
To be able to make a bank transfer payment, it is crucial that the payer has access to the bank transfer instructions. There are multiple options for the payer to access the information:
-
The instructions are displayed to the payer after they entered their details in the bank transfer payment element.
-
The payer also has the option to download the instructions from the element, including an authorization letter if one is needed.
-
You can display the instructions on demand with the instructions element. The payer also has the option to download the instructions here.
-
You should also send a link to the instructions to the payer via email. This can either happen automatically or you can do it manually, see One Off Payments: Emails to Your Payer.
hosted_form object
The hosted-form-URL. This is the URL your iframe displays.
The method (GET).
The hosted form is relevant when you use iframe rendering for displaying the bank transfer instructions..
The payment token that has been generated.
The payment token maps a payment to its bank transfer instructions for Smart Rendering.
Format:
A 36-character string in 8-4-4-4-12 format, for example
4b265027-bc17-4fab-ae83-e76705128758
The payment token is relevant when you use Smart Rendering for displaying the bank transfer instructions.
payor object
This information is returned so you can confirm the payer's country and email address.
Why is confirming the payer's country necessary?
Payments in the USA require delivering the receipt to the payer. If Flywire handles emails for you, Flywire will send the receipt automatically. If you are handling emails yourself, you need to ensure to send the receipt to your payer.
-
How to check whether the payer is from the USA:
You get the payer country information in the response after confirming a Checkout Session.
Alternatively, you also get the information by Getting Details about a Payment
-
How to get the receipt for the payment:
You can use the endpoint for Getting a Payment Receipt to download the receipt that Flywire created for you.
-
How to send the receipt to your payer:
For self-managed recurring payments, in the "Charge Successful" email for each payment, see Recurring Payments: Emails to Your Payer.
For One Off payments and Pre-Authorization Payments, in the "Payment Guaranteed" email for the payment, see One Off Payments: Emails to Your Payer or Pre-Authorization Payments: Emails to Your Payer.
Why is confirming the payer's email address necessary?
Even if you pre-filled the payer information with an email address, your payer might have changed it when filling out the form.
If you are handling emails yourself, you need to ensure you have the correct email address for the payer.
The ISO2 code of the payer country (the country the money was sent from).
The payer's email address.
The payer's state.
{
"payment_reference": "RUC208967136",
"charge_info": {
"amount": 100000,
"currency": "EUR"
},
"payment_instructions": {
"hosted_form": {
"url": "https://payment-checkout.flywire.com/v1/payments/TQQ639538199/payment_instructions/form?token=2fa802c8-fcd2-4be0-b2f8-5896ba0e700d",
"method": "GET"
},
"payment_token": "2fa802c8-fcd2-4be0-b2f8-5896ba0e700d"
},
"payor": {
"country": "US",
"email": "[email protected]",
"state": "NY"
}
}
8. Check the notifications.
You will receive the following callbacks:
- If you did not use magic values
- If you used magic values
Within the next 30 seconds:
Initiated
You can now display the instructions element.
If you put the payment into
Guaranteed:
Initiated
Processed
Guaranteed
If you put the payment into
Delivered:
Initiated
Processed
Guaranteed
Delivered
This is the end of this scenario.
9. Displaying the instructions element on demand
If you didn't use any magic values, you can now display the instructions again.
1. Open the url for the instructions in your browser.
You received the url for displaying the instructions in this step: 7. Confirm the Checkout Session.
2. Add the event listener code for receiving the postMessages for instructions in your browser.
|
Open the developer tools for your browser and add the following event listener code via the console. |
|
4. Click the button that confirms you read the instructions and closes them.
Check the postMessage after clicking the button to ensure you got a success message back.
-
Success -
Cancelled -
Not found
After your payer read the instructions, they can click on the action button to close the instructions. In that case, the event listener will return a successful postMessage.
The postMessage contains the following information:
This parameter helps you filter the PostMessages to only return the result of the Checkout Session. This is only necessary when you render via iframe.
Indicates if the Checkout Session was successful.
-
true: Checkout Session successful
-
false: Checkout Session failed
You can use this parameter to filter the PostMessages to only return successful ones. This is only necessary when you render via iframe.
{
source: "checkout_session",
success: true
}
This error is returned if your payer closes the instructions with the X close button instead of the action button.
This could still mean that your payer read the instructions. In any case, you should make sure that the instructions are available to your payer to look them up again. You can achieve this by making them available again through a button in the UI or by sending them to your payer via email (see One Off Payments: Emails to Your Payer - Bank Transfer Instructions).
errors array
Array of errors. Each error contains:
The type of error, for example cancelled.
A more detailed description of the error.
This parameter helps you filter the PostMessages to only return the result of the Checkout Session. This is only necessary when you render via iframe.
Indicates if the Checkout Session was successful.
-
true: Checkout Session successful
-
false: Checkout Session failed
You can use this parameter to filter the PostMessages to only return successful ones. This is only necessary when you render via iframe.
{
"errors": [
"0":{
"type": "cancelled",
"message": "The session has been cancelled by the user."
}
],
source: "checkout_session",
success: false
}
This error is returned if the bank transfer instructions are not available. This can be the case if the payment is in any other status than
Initiated.
errors array
Array of errors. Each error contains:
The type of error, for example cancelled.
A more detailed description of the error.
This parameter helps you filter the PostMessages to only return the result of the Checkout Session. This is only necessary when you render via iframe.
Indicates if the Checkout Session was successful.
-
true: Checkout Session successful
-
false: Checkout Session failed
You can use this parameter to filter the PostMessages to only return successful ones. This is only necessary when you render via iframe.
{
"errors": [
"0":{
"type": "unavailable",
"message": "The bank transfer instructions are not available."
}
],
source: "checkout_session",
success: false
}
= not set
= set