Payments

List of endpoints

Description Endpoint

Creating a Payment within a Self-Managed Recurring Plan

POST/payments/charge

Capturing the Funds for a Pre-Authorization Payment

POST/payments/{paymentID}/captures

Adjusting the Amount for a Pre-Authorization Payment

POST/payments/{paymentID}/authorization_adjustments

Marking a Payment as processed

POST/payments/{paymentID}/process

Cancelling a Payment

POST/payments/{paymentID}/cancel

Getting a List of all Payments

GET/payments

Getting Details about a Payment

GET/payments/{paymentID}

Creating a Refund for a Payment

POST/payments/{paymentID}/refunds

What is a Payment?

In everyday usage, a "payment" usually refers to the entire process of making a payment through Flywire. But the term "payment" has a specific meaning in Flywire: 

  1. A payment is considered created when a payment reference is assigned to it, not any earlier stage in the process.

  2. When the payment reference is assigned, two things happen:

    • The FX rate is locked in for FX payments (FX = "foreign exchange", a payment where one currency has to be converted to a different currency).

    • The payment starts its journey in status initiated, and its progress traceable via the payment reference. If you are using Flywire Dashboard, you can view the payment on your dashboard.

Creating a Payment within a Self-Managed Recurring Plan

Request

This endpoint is only for creating follow-up payments of a self-managed plan (see Use Case: Self-Managed Recurring Payments).

Why?

This endpoint creates a recurring payment within a self-managed plan. This is a manual step since Flywire doesn't know your payment schedule, meaning you have to ensure that recurring payments are created on time. If you want recurring payments to get created automatically, you can use Flywire-Managed Plans.

What do I need to use this endpoint?

You need a payment method token and mandate ID to create the payment:

  1. The payment method token lets you create the payment with known payer and payment information.

    The payer and payment information has been gathered via a UI form and stored in the payment_method object. This information is used for the future payments. The payer information is passed via the payment_method_token when you charge a payment.

  2. It is mandatory to include the mandate ID when charging the payment.

Important information for payments within a self-managed plan

Mandatory emails

Self-managed recurring payments require you to send mandatory emails to your payer. For details refer to Recurring Payments: Emails to Your Payer.

Charging direct debit payments

  • For direct debit payments (SEPA and BACS), the payer must be informed about the upcoming charge. To ensure this, charging a direct debit payment will trigger an email to inform the payer, and the actual charge will automatically be delayed for 3 business days.

    The email is sent by Flywire (for SEPA) or Finastra (for BACS), see List of Emails for Recurring Payments for Cards and Direct Debit.

  • After charging a direct debit payment it can take up to 10 business days before the funds appear in your bank account (3 days of charge delay plus up to 7 days of collecting and processing the charge).

Parameters for the Request Body

charge_intent object

recipient object

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.

items array

metadata object

You can specify up to 20 metadata pairs.

Maximum length for keys: 40 characters

Maximum length for values: 500 characters

POST/payments/charge

curl https://base-url-placeholder/payments/charge
  -X POST
  -H "Content-Type: application/json"
  -H "X-Authentication-Key: {api_key}"
  -d '{
    "charge_intent": {
        "mode": "subscription"
    },
    "mandate_id": "MCHUV20220526UAUTYQ8W",
    "payment_method_token": "e1278a8863eaef9b7a7c",
    "payor_id": "payor_CCC",
	"recipient": {
		"id": "FWU",
   		"fields": [
            {
                "id": "custom_field_1",
                "value": "ID12345"
            },
			{
				"id": "custom_field_2",
				"value": "2020"
			}
        ]
	},
    "items": [
        {
            "id": "default",
            "amount": 5000,
        }
    ],
    "metadata": {
       "Internal-ID": "12345",
       "Int-Comment": "A comment about this payment"
    },
    "notifications_url": "http://a-callback-url.com/callback",
    "external_reference": "a-reference"
}

Response

There are three possible outcomes:

The payment was created and successfully charged.

The payment was created but the charging was not successful.

There was an error and the payment was not created.

 

If you provided a notifications URL for the payment, you’ll start receiving notifications that let you track the payment’s progress (refer to Payment Status Notifications).

charge_info object

charge_result object

{
    "payment_reference": "TQQ921794790",
    "charge_info": {
        "amount": 70000,
        "currency": "EUR"
    },
    "charge_result": {
        "status": "success"
    }
}

If the payment was successfully created but could not be charged, the response contains the payment_reference and information why the charging failed.

At the moment, it is not possible to try to charge the same payment again. You need to create a new payment to try a new charge.

When does charging fail?

A failed charge means that the third-party (for example card issuer or bank) refused the charge. This can happen for example when the card was rejected (expired card, insufficient funds etc.) or the bank account number is invalid.

 

charge_info object

charge_result object

errors object

{
  "payment_reference": "UUI754118889",
  "charge_info": {
    "amount": 5000,
    "currency": "EUR"
  },
  "charge_result": {
    "status": "failed",
    "errors": [
      {
        "type": 006,
        "message": "Your transaction has been declined by your bank.
        Please try inserting correct, valid card/bank account 
        details to complete the payment or contact your bank 
        to resolve the issue."
      }
    ]
  }
}

Creating the Payment failed - Resource not found

The payment has not been created.

404 Error

When does this happen?

The payment method token (payment_method_token) or payer ID payor_id is not correct.

What should you do?

  1. Check if you used the correct payment method token and payer ID.

  2. Check if you used the same payor_id for charging the payment you used for creating the Checkout Session.

{
    "type": "https://developers.flywire.com",
    "title": "Not Found",
    "status": 404,
    "detail": "The provided payment_method_token 88b669e924fc46e41fe3 is not valid 
    or it's not associated to the provided payor_id i_23456789"
}

Creating the Payment failed - Missing or invalid parameter

The payment has not been created.

422 Error

When does this happen?

Your request was either missing a parameter or a parameter contained an invalid value.

What should you do?

The error response will tell you which parameter is affected. It could be the parameter itself or the value for the parameter.

  1. If there's a missing parameter, check your request if you misspelled the parameter or left it out.

  2. If there's an invalid value, check the validation rules for the value. You'll find descriptions of parameters and their allowed values for each request in this documentation.

{
    "type": "https://developers.flywire.com",
    "title": "Unprocessable entity",
    "status": 422,
    "detail": "Invalid parameters",
    "errors": [
        {
            "source": "/",
            "param": "payor_id",
            "type": "missing_param",
            "message": "is missing"
        }
    ]
}

Creating the Payment failed - Internal Server Error

The payment has not been created.

500 - Internal Server Error

Communication with the API failed.

When does this happen?

The server is unavailable or an unexpected condition was encountered. This can have various reasons, for example:

  • Authentication issues

  • API being unavailable

  • Server time out (the request took longer than 8 secs)

  • Network issues

  • Rate limits exceeded

What should you do?

Check the following and then try again:

  1. Authentication

    • Ensure that you are using the right API key and it is correctly implemented in the request.

  2. Flywire API Status

  3. Rate Limits

    • Ensure you haven't exceeded the rate limits, see Rate Limits.

  4. Network Connectivity

    • Confirm that your server has a stable internet connection, and no firewall or network issues blocking the connection to the API.

{
  "type": "https://developers.flywire.com",
  "status": "500",
  "title": "Internal Server Error"
}

Capturing the Funds for a Pre-Authorization Payment

Request

When you capture a Pre-Authorization Payment the card is being charged and Flywire starts processing the payment.

Mandatory emails

There are mandatory emails you need to send to your payer when charging Pre-Authorization Payments, for details see Pre-Authorization Payments: Emails to Your Payer.

 

How to Resolve the Path Placeholders of the Endpoint

Replace {paymentID} in the endpoint with the payment reference.

Parameters for the Request Body

You can capture the exact blocked amount or less, but not more.

POST/payments/{paymentID}/captures

curl https://base-url-placeholder/payments/UUI754118889/captures
  -X POST
  -H "Content-Type: application/json"
  -H "X-Authentication-Key: {api_key}"
  -d '
  
{
    "amount": 60000
}

Response

charge_info object

charge_result object

{
    "payment_reference": "TQQ921794790",
    "charge_info": {
        "amount": 70000,
        "currency": "EUR"
    },
    "charge_result": {
        "status": "success"
    }
}

Capturing the Pre-Authorization Payment failed - Amount higher than authorized

422 Error

When does this happen?

The amount you tried to capture was higher than the authorized amount.

What should you do?

If you want to capture a higher amount than authorized, you need to adjust the amount before capturing it.

{
	"type": "https://developers.flywire.com",
	"title": "Unprocessable entity",
	"status": 422,
	"detail": "Invalid parameters",
	"errors": null
				}

Adjusting the Amount for a Pre-Authorization Payment

Request

You can adjust the Pre-Authorization Payment amount during the holding period if you used the authorization type preauth when you created the payment.

How to Resolve the Path Placeholders of the Endpoint

Replace {paymentID} in the endpoint with the payment reference.

Parameters for the Request Body

You can change the amount to a higher amount, not to a lower amount.

POST/payments/{paymentID}/authorization_adjustments

curl https://base-url-placeholder/payments/UUI754118889/authorization_adjustments
  -X POST
  -H "Content-Type: application/json"
  -H "X-Authentication-Key: {api_key}"
  -d '
  
{
    "amount": 70000
}

Response

charge_info object

charge_result object

{
    "payment_reference": "TQQ921794790",
    "charge_info": {
        "amount": 70000,
        "currency": "EUR"
    },
    "charge_result": {
        "status": "success"
    }
}

Adjusting the Pre-Authorization Payment failed - Amount is lower than original amount

422 Error

When does this happen?

The amount you tried to adjust to was lower than the originally authorized amount.

What should you do?

If you want to capture a lower amount, you don't need to adjust the amount before capturing.

{
    "type": "https://developers.flywire.com",
    "title": "Unprocessable entity",
    "status": 422,
    "detail": "Invalid parameters",
    "errors": null
}

Marking a Payment as processed

Request

This endpoint is only relevant for 529 Payments.

Usually, Flywire takes care of the payment process and captures the funds for you. After capturing the funds, Flywire moves the status of a payment to processed. For 520 Payments, since you are capturing the funds yourself, you have to move the payment into processed yourself.

This is necessary because:

  • It ensures that the payment is following the correct payment workflow.

  • It notifies Flywire that you received the funds.

  • It notifies your payer that you received the funds (if you implemented a system that sends notifications about status changes to your payers).

    After a payment is processed by you, you should notify your payer that their payment was processed to avoid duplicate payments.
  • It prevents that a payment expires (if payment is not processed it will expire after its due date).

 

How to Resolve the Path Placeholders of the Endpoint

Replace {paymentID} in the endpoint with the payment reference.

Parameters for the Request Body

POST/payments/{paymentID}/process

curl https://base-url-placeholder/payments/FWU125675432/process
  -X POST
  -H "Content-Type: application/json"
  -H "X-Authentication-Key: {api_key}"
  -d '{
  "external_reference": "My reference for the payment"
  }

Response

A 204 response will let you know that the payment has been successfully processed.

If you provided a notifications URL, you'll also receive a notification about the status change of the payment.

204 NO CONTENT

Cancelling a Payment

Request

Cancelling a payment puts a payment into the cancelled status.

When you cancel a Pre-Authorization Payment the blocked amount immediately returns back to the cardholder's credit.

Guaranteed and delivered payments should not be cancelled. If you have to cancel them, please contact Flywire.

The payment status cancelled means that the payment has been cancelled and will not be processed. If Flywire already received the funds, Flywire will return the funds to the payer.

See Payment Status Notifications for information about notifications for this status.

 

How to Resolve the Path Placeholders of the Endpoint

Replace {paymentID} in the endpoint with the payment reference.

Digest Header

Add X-Flywire-Digest as a header to your request.

Exchange {your_digest_header} with the digest header you generated, see Authentication (via Digest Header).

Parameters for the Request Body

No request body needed.

POST/payments/{paymentID}/cancel

curl https://base-url-placeholder/payments/FWU125675432/cancel
  -X POST
  -H "Content-Type: application/json"
  -H "X-Authentication-Key: {api_key}"

Response

A 204 response will let you know that the payment has been successfully cancelled.

If you provided a notifications URL, you'll also receive a notification about the status change of the payment.

204 NO CONTENT

Getting a List of all Payments

Request

You can use this endpoint to display a list of all payments in a UI.

Which payments will be returned in the list?

The list will contain all payments that have been created by you as a client with your API credentials via the Flywire API .

Don't use the list of payments as a source of truth regarding the payment status. If you want to get immediate updates about a payment's status, use notifications (see Payment Status Notifications).

Example for displaying a list of payments

Each parameter can be used as a column (for example payment reference or status). You can decide which parameters you want to display to help you identify a payment before you get more detailed information about it (see Getting Details about a Payment). Check the response to see which parameters of the payments are returned in the list.

 

Parameters for the Request Body

No request body needed.

Optional Query Parameters for Filtering

You can filter the list of results by the following parameters:

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

GET/payments
curl https://base-url-placeholder/payments
  -X GET
  -H "Content-Type: application/json"
  -H "X-Authentication-Key: {api_key}"

Response

Pagination Parameters

payments array

status_transitions object

The status transitions provide you with a log when a payment went through different statuses. For this reason, the parameters only contain dates if the payment already went through the specific status.

See Payment Status Notifications for details about the statuses.

Name Description

guaranteed_at

string

The date and time when the payment was in status guaranteed.

delivered_at

string

The date and time when the payment was in status delivered.

cancelled_at

string

The date and time when the payment was in status cancelled.

authorized_at

string

The date and time when the payment was authorized. Note that the status of an authorized payment is initiated and will stay in this status until the funds are captured.

 

{
"total_entries": 367,
"total_pages": 37,
"page": 1,
"per_page": 10,
"payments": [
	{
		"payment_id": "TQQ871958420",
		"created_at": "2024-04-30T06:37:19Z",
		"expiration_date": "2024-05-03T06:37:19Z",
		"status": "delivered",
		"amount_from": 50000,
		"currency_from": "EUR",
		"amount_to": 50000,
		"currency_to": "EUR",
		"external_reference": "My external reference",
		"disbursement_id": "TQQ2024-04-30-1714459077",
		"status_transitions": {
		"guaranteed_at": "2024-04-30T06:37:32Z",
 		"delivered_at": "2024-04-30T06:37:57Z",
		"cancelled_at": null,
		"authorized_at": null
	},
		"payor_id": "My_payer_1"
	},
	{
...
	},
	{
		"payment_id": "TQQ963354950",
		"created_at": "2024-04-30T05:00:10Z",
		"expiration_date": "2024-05-04T05:00:09Z",
		"status": "guaranteed",
		"amount_from": 15000,
		"currency_from": "GBP",
		"amount_to": 17500,
		"currency_to": "EUR",
		"external_reference": "My external reference",
		"disbursement_id": null,
		"status_transitions": {
			"guaranteed_at": "2024-05-01T05:00:12Z",
			"delivered_at": null,
			"cancelled_at": null
			},
		"payor_id": "My_payer_2"
		}
	]
}

Getting Details about a Payment

Request

You can use this endpoint to show details about a payment in a UI.

The payment details show real-time information about the payment and can be used as a source of truth. There is no latency like there is for Getting a List of all Payments.

Example for displaying payment details

See Response for which details of the payment are returned so you can display them.

 

Parameters for the Request Body

No request body needed.

How to Resolve the Path Placeholders of the Endpoint

Replace {paymentID} in the endpoint with the payment reference.

GET/payments/{paymentID}

curl https://base-url-placeholder/payments/FWU928923284
  -X GET
  -H "Content-Type: application/json"
  -H "X-Authentication-Key: {api_key}"

Response

status_transitions object

The status transitions provide you with a log when a payment went through different statuses. For this reason, the parameters only contain dates if the payment already went through the specific status.

See Payment Status Notifications for details about the statuses.

Name Description

guaranteed_at

string

The date and time when the payment was in status guaranteed.

delivered_at

string

The date and time when the payment was in status delivered.

cancelled_at

string

The date and time when the payment was in status cancelled.

authorized_at

string

The date and time when the payment was authorized. Note that the status of an authorized payment is initiated and will stay in this status until the funds are captured.

payer object

The payer information is not automatically included. Returning payer information is disabled by default and needs to be enabled by Flywire.

Please contact the Solutions team if you require payer information to be returned.

recipient object

fields array

items array

charge_intent object

payment_method-details object

reason object

Only if the payment failed.

metadata object

There are different kinds of metadata for a payment:

Metadata added by Flywire

Not present for 529 Payments.

Metadata added by you

Only for 520 Payments and self-managed recurring payments. Not present for One Off Payments and Flywire-managed recurring payments.

Custom metadata is additional data entered by you when you create the payment, for example data you need to identify the payment in your system. Metadata can be useful when you want to add data that is not already covered by recipient fields, for example if you are not the one who set up the recipient and have no influence on the fields.

Metadata consist of pairs of keys and values, for example key Payer_ID_From_My_System and value ID12345.

instructions array

The payment instructions are only returned for One Off Payments when the payment method type is bank transfer.

This array of objects contains the payment instructions for your payer to enable them to send the money to Flywire via bank transfer.

Which objects are returned depend on various factors, for example from which country the payer is sending money.

Each object consists of an internal name, a label, and a value.

For displaying the instructions to your payer, use the label and the value.

UI Example: 

There are two ways to give your payer the payment instructions for bank transfers:

  1. You can use the instructions parameters and display them in your UI or an email.

  2. You can display the tracking_url in your UI or an email. If your payer needs an authorization letter, they need to use the tracking URL and download the payment instructions from there, since the PDF download contains the authorization letter.

{
	"payment_id": "RUC928923284",
	"created_at": "2023-02-14T14:06:32Z",
	"expiration_date": "2023-02-16T14:06:32Z",
	"status": "initiated",
    "status_detail": "processing"
    "status_transitions": {
        "guaranteed_at": null,
        "delivered_at": null,
        "cancelled_at": null,
        "authorized_at": null
    },
	"amount_from": 94000,
	"currency_from": "EUR",
	"amount_to": 100000,
	"currency_to": "USD",
	"payer": {
		"first_name": "Peter",
		"last_name": "Payer",
		"middle_name": null,		
		"address1": "789 Calle Mayor",
		"address2": null,
		"city": "Madrid",
		"country": "ES",
		"state": null,
		"zip": "28013",
		"phone": "0034912345678",
		"email": "[email protected]"
    },
	"recipient": {
		"id": "FWU",
   		"fields": [
            {
                "id": "custom_field_1",
                "value": "ID12345"
            },
			{
				"id": "custom_field_2",
				"value": "2020"
			}
        ]
	},
    "items": [
        {
            "id": "default",
            "amount": 50000,
        }
    ],
    "charge_intent": {
        "initiator": "MERCHANT",
        "mode": "SUBSCRIPTION",
        "mandate_id": "MCZER20230214E2PEBOEF",
        "payor_id": "studentORparent123",
        "payment_method_token": "4ec7373376b0edc050d4"
        }
    },
    "payment_method_details": {
        "type": "card",
        "brand": "VISA",
        "card_classification": "credit",
        "card_expiration": "3/2030",
        "last_four_digits": "1111",
        "status": "failed",
        "reason": {
            "code": "012",
            "description": "Your transaction has been declined by your bank. Please try increasing the available balance of your account, use a different card/bank account or contact your bank for further assistance."
        }
    },    
    "external_reference": "My internal reference",
    "notifications_url": "https://webhook.site/c1e8",
    "disbursement_id": "FLW2018-02-26",
    "metadata": {
        "payor_id": "studentORparent123",
        "tracking_url": "https://payment.demo.flywire.com/tracking/f240fcd8-7337-4110-a472-afabaafb07da?token=bf54dbc0-6d96-469d-8197-f15b2741215d",
        "MyOwnMetadata": "My system info about the payment"
         }, 
    "instructions": [
        {
            "name": "iban",
            "label": "IBAN",
            "value": "ES3814740000140660146008"
        },
        {
            "name": "beneficiary",
            "label": "Beneficiary",
            "value": "Flywire"
        },
...
        {
            "name": "beneficiary_address",
            "label": "Beneficiary Address",
            "value": "Av. Aragón 30, 13J\r\n46021 Valencia, Spain"
        }
    ]
}

Creating a Refund for a Payment

Request

This endpoint lets you create a refund for a payment.

What happens after I created a refund?

After you created a refund, you need to use the resource Refunds to manage refunds.

For a detailed walkthrough about how to create and manage refunds see Use Case: Refunds.

 

How to Resolve the Path Placeholders of the Endpoint

Replace {paymentID} in the endpoint with the payment reference.

A payment needs to be in status delivered before you can create a refund for it (see Payment Statuses for details about payment statuses).

Parameters for the Request Body

POST/payments/{paymentID}/refunds

curl https://base-url-placeholder/payments/FWU125675432/refunds
  -X POST
  -H "Content-Type: application/json"
  -H "X-Authentication-Key: {api_key}"
  -d '{
		“amount”: 10000,
		“external_reference”: “my-refunds-29”,
		“notifications_url”: “https://webhooks/notifications/refunds”
}

Response

{
  "refund_id": "RUUI123456789",
  "payment_id": "UUI123456789",
  "bundle_id": "BUUI123456789",
  "status": "pending",
  "amount": 10000,
  "currency": "USD",
  "external_reference": "my-refunds-29",
  "notifications_url": "https://webhooks/notifications/refunds"
}