Payment Intents

We are currently not accepting new customers on to this product

If you have access to test mode, please check with your
Duffel contact that you’re able to use the product in
live mode before starting your integration.

A payment intent is used to collect and capture a payment from a customer to top-up your balance and then pay for an offer, order, or order change offer. You're able to include markup here.

amount
string

The amount of the payment intent that covers the cost of the flight being sold and any additional markup.

The card payment will be charged this amount.

Example: "300.10"
card_country_code
stringnullable

The ISO 3166-1 alpha-2 code of the country that issued the card used to confirm the payment intent.

It will be null until the payment intent is confirmed.

Example: "GB"
card_last_four_digits
stringnullable

The last four digits of the card used to confirm the payment intent.

It will be null until the payment intent is confirmed.

Example: "4242"
card_network
enumnullable

The card network in which the payment intent was processed on.

It will be null until the payment intent is confirmed.

Possible values: "amex", "cartes_bancaires", "diners", "discover", "interac", "jcb", "mastercard", "unionpay", "visa", or "unknown"
client_token
string

This value is used when displaying the payment collection form to securely identify and transmit the values to Duffel.

Example: "eyJjbGllbnRfc2VjcmV0IjoicGlfMUl5YTBiQW5rMVRkeXJvRE1iWkJPN0ZSX3NlY3JldF9TbGFrYnJjYnFHZGZha2VrcjdCNE5jZWVyIiwicHVibGlzaGFibGVfa2V5IjoicGtfbGl2ZV81MUl0Q3YwQW5rMUdkeXJvRFlFU3M3RnBTUEdrNG9kbDhneDF3Y1RBNVEzaUcyWEFWVEhxdFlKSVhWMUxoSU5GQUtFMjA1dFdmRGVIcXhwUVdnYkIzTkVFbzAwMmdVY1hzR0YifQ=="
confirmed_at
datetimenullable

The ISO 8601 datetime at which the payment intent was confirmed.

It will be null until the payment intent is confirmed.

Example: "2020-04-11T15:49:02.642Z"
created_at
datetime

The ISO 8601 datetime at which the payment intent was created

Example: "2020-04-11T15:48:11.642Z"
currency
string

The currency of the amount, as an ISO 4217 currency code.

The card payment will be charged in this currency.

If it's different to your balance currency, it will be converted to your balance currency before the balance is topped up.

Example: "GBP"
fees_amount
stringnullable

The amount of the fees to process the payment intent.

It will be null until the payment intent is confirmed.

Example: "3.00"
fees_currency
stringnullable

The currency of the fees_amount, as an ISO 4217 currency code.

This currency will match your balance currency.

It will be null until the payment intent is confirmed.

Example: "GBP"
id
string

Duffel's unique identifier for the resource

Example: "pit_00009hthhsUZ8W4LxQgkjo"
live_mode
boolean

Whether the payment intent was created in live mode. This field will be set to true if the payment intent was created in live mode, or false if it was created in test mode.

Example: true
net_amount
stringnullable

The amount of the payment intent that was added to the balance.

It'll be amount (in the balance currency) less the fees_amount.

It will be null until the payment intent is confirmed.

Example: "297.10"
net_currency
stringnullable

The currency of the net_amount, as an ISO 4217 currency code.

This currency will match your balance currency.

It will be null until the payment intent is confirmed.

Example: "GBP"
refunds
list

The refunds for this payment intent


A refund is used to refund money to a customer for part or all of a payment intent.

You can issue multiple refunds from the same payment intent.

status
enum

The status of this Payment Intent

Possible values: "requires_payment_method", "requires_confirmation", "requires_action", "processing", "requires_capture", "cancelled", or "succeeded"
updated_at
datetime

The ISO 8601 datetime at which the payment intent was updated

Example: "2020-04-11T15:48:11.642Z"

To begin the process of collecting a card payment from your customer, you need to create a payment intent.

The payment intent will contain a client_token that you use to collect the card payment in the frontend of your application. Read our guide on how to do this.

If the payment intent is created in test mode you should use a test card.

Body parameters

amount
stringrequired

This is the amount that the card payment being taken will be charged.

It should be enough to cover the service(s) you want to sell (enough to book an offer for example) and the processing fees.

If the currency is different from your Balance currency you should also account for foreign exchange.

It can be higher than that, in which case the remainder will be considered your markup.

If it's higher than the maximum allowed for you organisation you will get a validation error. By default the maximum is 5,000.00 GBP (or equivalent in the same currency). If you need a maximum higher than the default please get in touch with us via help@duffel.com.

Example: "30.20"
currency
stringrequired

The currency of the amount, as an ISO 4217 currency code.

This is going to be the currency that the card payment being taken in will be charged in.

Example: "GBP"

Endpoint

POST https://api.duffel.com/payments/payment_intents

Request

curl -X POST --compressed "https://api.duffel.com/payments/payment_intents" \
-H "Accept-Encoding: gzip" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Duffel-Version: v2" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>" \
-d '{
"data": {
"currency": "GBP",
"amount": "30.20"
}
}'

Response

{
"data": {
"updated_at": "2020-04-11T15:48:11.642Z",
"status": "requires_payment_method",
"refunds": [],
"live_mode": true,
"id": "pit_00009hthhsUZ8W4LxQgkjo",
"currency": "GBP",
"created_at": "2020-04-11T15:48:11.642Z",
"client_token": "eyJjbGllbnRfc2VjcmV0IjoicGlfMUl5YTBiQW5rMVRkeXJvRE1iWkJPN0ZSX3NlY3JldF9TbGFrYnJjYnFHZGZha2VrcjdCNE5jZWVyIiwicHVibGlzaGFibGVfa2V5IjoicGtfbGl2ZV81MUl0Q3YwQW5rMUdkeXJvRFlFU3M3RnBTUEdrNG9kbDhneDF3Y1RBNVEzaUcyWEFWVEhxdFlKSVhWMUxoSU5GQUtFMjA1dFdmRGVIcXhwUVdnYkIzTkVFbzAwMmdVY1hzR0YifQ==",
"amount": "300.10"
}
}

Once you've successfully collected the customer's card details, using the client_token from when you first created the Payment Intent, you then need to confirm it using this endpoint.

Once confirmed, the amount charged to your customer's card will be added to your balance (minus any Duffel Payment fees). Attempting to confirm it more than once will have no effect.

URL parameters

id
stringrequired

Duffel's unique identifier for the resource

Example: "pit_00009hthhsUZ8W4LxQgkjo"

Endpoint

POST https://api.duffel.com/payments/payment_intents/{id}/actions/confirm

Request

curl -X POST --compressed "https://api.duffel.com/payments/payment_intents/{id}/actions/confirm" \
-H "Accept-Encoding: gzip" \
-H "Accept: application/json" \
-H "Duffel-Version: v2" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"

Response

{
"data": {
"updated_at": "2020-04-11T15:48:11.642Z",
"status": "succeeded",
"refunds": [],
"net_currency": "GBP",
"net_amount": "297.10",
"live_mode": true,
"id": "pit_00009hthhsUZ8W4LxQgkjo",
"fees_currency": "GBP",
"fees_amount": "3.00",
"currency": "GBP",
"created_at": "2020-04-11T15:48:11.642Z",
"confirmed_at": "2020-04-11T15:49:02.642Z",
"client_token": "eyJjbGllbnRfc2VjcmV0IjoicGlfMUl5YTBiQW5rMVRkeXJvRE1iWkJPN0ZSX3NlY3JldF9TbGFrYnJjYnFHZGZha2VrcjdCNE5jZWVyIiwicHVibGlzaGFibGVfa2V5IjoicGtfbGl2ZV81MUl0Q3YwQW5rMUdkeXJvRFlFU3M3RnBTUEdrNG9kbDhneDF3Y1RBNVEzaUcyWEFWVEhxdFlKSVhWMUxoSU5GQUtFMjA1dFdmRGVIcXhwUVdnYkIzTkVFbzAwMmdVY1hzR0YifQ==",
"card_network": "visa",
"card_last_four_digits": "4242",
"card_country_code": "GB",
"amount": "300.10"
}
}

You should use this API to get the complete, up-to-date information about a payment intent.

URL parameters

id
stringrequired

Duffel's unique identifier for the resource

Example: "pit_00009hthhsUZ8W4LxQgkjo"

Endpoint

GET https://api.duffel.com/payments/payment_intents/{id}

Request

curl -X GET --compressed "https://api.duffel.com/payments/payment_intents/{id}" \
-H "Accept-Encoding: gzip" \
-H "Accept: application/json" \
-H "Duffel-Version: v2" \
-H "Authorization: Bearer <YOUR_ACCESS_TOKEN>"

Response

{
"data": {
"updated_at": "2020-04-11T15:48:11.642Z",
"status": "succeeded",
"refunds": [
{
"updated_at": "2020-04-11T15:48:11.642Z",
"status": "succeeded",
"payment_intent_id": "pit_00009hthhsUZ8W4LxQgkjo",
"net_currency": "GBP",
"net_amount": "300.10",
"live_mode": true,
"id": "ref_00009hthhsUZ8W4LxQgkjo",
"destination": "original_form_of_payment",
"currency": "GBP",
"created_at": "2020-04-11T15:48:11.642Z",
"arrival": "Credit approximately 5-10 business days later, depending upon the bank.",
"amount": "300.10"
}
],
"net_currency": "GBP",
"net_amount": "297.10",
"live_mode": true,
"id": "pit_00009hthhsUZ8W4LxQgkjo",
"fees_currency": "GBP",
"fees_amount": "3.00",
"currency": "GBP",
"created_at": "2020-04-11T15:48:11.642Z",
"confirmed_at": "2020-04-11T15:49:02.642Z",
"client_token": "eyJjbGllbnRfc2VjcmV0IjoicGlfMUl5YTBiQW5rMVRkeXJvRE1iWkJPN0ZSX3NlY3JldF9TbGFrYnJjYnFHZGZha2VrcjdCNE5jZWVyIiwicHVibGlzaGFibGVfa2V5IjoicGtfbGl2ZV81MUl0Q3YwQW5rMUdkeXJvRFlFU3M3RnBTUEdrNG9kbDhneDF3Y1RBNVEzaUcyWEFWVEhxdFlKSVhWMUxoSU5GQUtFMjA1dFdmRGVIcXhwUVdnYkIzTkVFbzAwMmdVY1hzR0YifQ==",
"card_network": "visa",
"card_last_four_digits": "4242",
"card_country_code": "GB",
"amount": "300.10"
}
}