Pre-authorizations and Authorization Adjustments for Developers
Tags: adyen, preauthorization, payments, hotel
Published: 2023-10-18 16:43:20

> _This technical blog post explains how developers can implement a hotel booking payment process using Adyen's API. It covers pre-authorizations, amount adjustments, extending authorization expiry dates, capturing payments, refunding payments and webhook payloads._

At Adyen, we understand that modern businesses across different industries require various payment solutions for different use cases. In a basic payment flow, the amount from your payment request is authorized and then captured. But sometimes you may want to change the amount or extend the length of the authorization. This is known as a pre-authorization, followed by an authorization adjustment.


## Introduction

The use of authorization adjustment in various industries may differ. One could increase the amount, decrease the amount after a successful pre-authorization or extend the expiry date of the authorization. 

In the hospitality sector, for example, hotels use pre-authorizations to facilitate payment processes before a guest checks into their hotel. During their stay, if the guest incurs additional expenses at the hotel, these expenses can be added to the pre-authorized amount by adjusting the authorization. Once the guest checks out, the hotel captures the final amount or, optionally, cancels the payment if the guest prefers to settle their bill with a different payment method. 

In other cases such as taxi rides, car rentals, or parking, you can use pre-authorizations to handle situations where the final amount for the service is not known at the time of payment. 

Another common use-case is in the United States. As tax regulation can differ widely between states, it is common that the final amount of an order for clothing and apparel deliveries has to be adjusted due to tax regulation changes in applicable tax due to last minute changes of origin or destination of the package.

## Overview

Let’s start by taking a look at a high-level technical overview where a guest reserves a hotel room for $249.99 and chooses to accumulate extra costs during their stay. Here’s an overview of the three main request:

1. **Pre-authorization request:** The merchant initiates a pre-authorization request of $249.99.
2. **Authorization adjustment request:** Once the pre-authorization is successfully authorized, the merchant sends an authorization adjustment request of $500. 
  - **Extension request:** Once a pre-authorization request is successfully authorized, the merchant can optionally extend the authorization to increase the expiry window of this authorization. 
3. **Capture request:** Once the authorization adjustment is successful. The merchant confirms the final payment by sending a capture request of $500. This will finalize the payment.
  - **Reversal request:** Optionally, a merchant can cancel or refund the authorization with a reversal request.


## 1. Pre-authorization

First, we create a pre-authorization request to the /payments endpoint. We specify a merchant reference to keep track of the payment throughout the whole payment lifecycle. 

![Image of sending a pre-authorization request to the Adyen /payments/ endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yw7b68m6c35gf9cbnvmw.png)

**Pre-authorization request:**
```json
{
  "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
  "reference": "7a5d8be7-cceb-4442-b17f-3a10a8fa396d", // Your unique reference
  "channel": "Web",
  "amount": {
    "currency": "USD",
    "value": 24999 // 249.99 USD in minor units
  },
  "returnUrl": "https://your-company.com/api/handleRedirect?orderRef=7a5d8be7-cceb-4442-b17f-3a10a8fa396d", // We redirect to our domain
  "countryCode": "NL",
  "paymentMethod": { 
     "type": "scheme",
      "number":"4111111111111111",
      "cvc":"737",
      "expiryMonth":"03",
      "expiryYear":"2023",
      "holderName":"John Smith"
  },
  "additionalData": {
    "allow3DS2": "true",
    "authorisationType": "PreAuth"
  }
}
```

A successful response contains the “Authorised” result code.


**Pre-authorization response:**
```json
{
   "additionalData" : {
      // …
   },
   "pspReference" : "TJ5MXF5SK3RZNN82",
   "resultCode" : "Authorised",
   "amount" : {
      "currency" : "USD",
      "value" : 24999 // 249.99 USD in minor units
   },
   "merchantReference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
   "paymentMethod" : {
      "brand" : "visa",
      "type" : "scheme"
   }
}
```

Adyen will send a webhook asynchronously, check the notification success-flag to see whether the authorization has succeeded.


![Image of Adyen sending the AUTHORISATION webhook to your endpoint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g9iexvzivoztu2m7vpc3.png)

**"AUTHORISATION" webhook:**
```json
{
   "live" : "false",
   "notificationItems" : [
      {
         "NotificationRequestItem" : {
            "additionalData" : {
	  // …
               "hmacSignature" : ""**********************",",
             // …
            },
            "amount" : {
               "currency" : "USD",
               "value" : 24999 // 249.99 USD in minor units
            },
            "eventCode" : "AUTHORISATION",
            "eventDate" : "2023-07-06T15:07:38+02:00",
            "merchantAccountCode" : "YOUR_MERCHANT_ACCOUNT",
            "merchantReference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
            "operations" : [
               "CANCEL",
               "CAPTURE",
               "REFUND"
            ],
            "paymentMethod" : "visa",
            "pspReference" : "TJ5MXF5SK3RZNN82",
            "reason" : "052031:1111:03\/2030",
            "success" : "true"
         }
      }
   ]
}
```

The webhook contains a _PspReference_ that can be used in the subsequent authorization adjustment call.


## 2. Authorization Adjustment


To adjust the amount asynchronously, we create a request object to the /payments/**TJ5MXF5SK3RZNN82**/amountUpdate endpoint. The

**Authorization adjustment request:**
```json
{
  "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
  "amount": {
    "Currency": "USD",
    "Value": 50000 // 500 USD in minor units
  },
  "Reason": "DelayedCharge",
  "reference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d"
}
```

**Authorization adjustment response:**
```json
{
    "industryUsage": "delayedCharge",
    "status": "received",
    "amount": {
        "currency": "USD",
        "value": 50000
    },
    "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
    "paymentPspReference": "TJ5MXF5SK3RZNN82",
    "pspReference": "WBG6F4K25HXXGN82",
    "reference": "7a5d8be7-cceb-4442-b17f-3a10a8fa396d"
}
```


The call is received by Adyen when the response status matches the expected "received" status.


Later on, Adyen sends a webhook with an “**AUTHORISATION_ADJUSTMENT**” event code that contains the result of the authorization adjustment. Check the success-flag to see whether the adjustment has been successful and save this accordingly in your backend.


![Image of Adyen sending the AUTHORISATION_ADJUSTMENT webhook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/btf9qguwm4kgq6qorv2d.png)

**"AUTHORISATION_ADJUSTMENT" webhook:**
```json
{
   "live" : "false",
   "notificationItems" : [
      {
         "NotificationRequestItem" : {
            "additionalData" : {
               "hmacSignature" : "********************",
               "bookingDate" : "********************" // This is a DateTime
            },
            "amount" : {
               "currency" : "USD",
               "value" : 50000
            },
            "eventCode" : "AUTHORISATION_ADJUSTMENT",
            "eventDate" : "2023-07-06T16:01:28+02:00",
            "merchantAccountCode" : "YOUR_MERCHANT_ACCOUNT",
            "merchantReference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
            "originalReference" : "TJ5MXF5SK3RZNN82",
            "paymentMethod" : "visa",
            "pspReference" : "WBG6F4K25HXXGN82",
            "reason" : "",
            "success" : "true"
         }
      }
   ]
}
```


## Validity and authorization expiry dates

Card schemes set specific rules around which businesses (f.e. travel, restaurants, public transportation) are able to adjust an authorization. Your merchant category code (MCC) determines the eligibility, together with the card scheme. You can find an extensive table on availability [here](https://docs.adyen.com/online-payments/adjust-authorisation/?tab=asynchronous_authorisation_adjustment_1#availability).

Adyen expires authorization requests automatically after 28 days from the day the payment is authorized. Note: Please refer to the [documentation](https://docs.adyen.com/online-payments/adjust-authorisation/?tab=asynchronous_authorisation_adjustment_1#validity) to see a table as these vary per card scheme. The default expiry period can be adjusted and ensures that Adyen does not automatically expire the authorization after the default 28 days. Our support team can configure this for your merchant account. 

If you try to capture a transaction after the allowed time, it's more likely to fail. However, you can often capture a payment successfully after an authorization has expired. Depending on the card scheme, there can be a fee for late captures, and an increase in interchange and/or scheme fees charged for the transaction. There's also a higher risk of chargebacks from card holders.


To manually **extend** the expiry date of an authorization, make a request to the same endpoint but leave the amount unchanged.

**Authorization adjustment extend request:**
```json
{
  "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
  "amount": {
    "Currency": "USD",
    "Value": 24999 // 249.99 USD in minor units
  },
  "Reason": "DelayedCharge",
  "reference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d"
}
```


**Authorization adjustment extend response:**
```json
{
  "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
  "amount": {
    "Currency": "USD",
    "Value": 24999 // 249.99 USD in minor units
  },
  "Reason": "DelayedCharge",
  "reference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d"
}
```

**“AUTHORIZATION_ADJUSTMENT” extend webhook:**
```json
{
   "live" : "false",
   "notificationItems" : [
      {
         "NotificationRequestItem" : {
            "additionalData" : {
               "hmacSignature" : "********************",
               "bookingDate" : "********************" // This is a DateTime
            },
            "amount" : {
               "currency" : "USD",
               "value" : 24999
            },
            "eventCode" : "AUTHORISATION_ADJUSTMENT",
            "eventDate" : "2023-07-06T16:21:28+02:00",
            "merchantAccountCode" : "YOUR_MERCHANT_ACCOUNT",
            "merchantReference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
            "originalReference" : "TJ5MXF5SK3RZNN82",
            "paymentMethod" : "visa",
            "pspReference" : "WBG6F4K25HXXGN82",
            "reason" : "",
            "success" : "true"
         }
      }
   ]
}
```

## 3. Capture


To finalize the payment, make sure you’ve received the webhook for each authorization adjustment that you’ve made. Make a request to the endpoint /payments/**TJ5MXF5SK3RZNN82**/captures with the final amount of $500 that you wish to capture. Notice that we're using the _PspReference_ of the initial pre-authorization.


**Capture request:**
```json
{
  "merchantAccount":"YOUR_MERCHANT_ACCOUNT",
       "amount":{
          "Currency": "USD",
          "Value": 50000 // 500 USD in minor units
       },
   "reference":"7a5d8be7-cceb-4442-b17f-3a10a8fa396d"
}
```

**Capture response:**
```json
{
   "merchantAccount" : "YOUR_MERCHANT_ACCOUNT",
   "paymentPspReference" : "TJ5MXF5SK3RZNN82",
   "pspReference" : "FVNHBFGDFVTFWR82",
   "reference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
   "status" : "received",
   "amount" : {
      "currency" : "USD",
      "value" : 50000 // 500 USD in minor units
   }
}
```

Adyen sends a webhook with the event code “CAPTURE” when successful or unsuccessful. In some rare cases a "[CAPTURE_FAILED](https://docs.adyen.com/online-payments/capture/#failed-capture)" event code (with a success-flag) can occur as well. This can happen because it was either rejected by a card scheme, technical issue, or when capture expires. For a full list of failed capture reasons, refer to [this documentation page](https://docs.adyen.com/online-payments/capture/failure-reasons/) on what to do next.

![Image of Adyen sending the CAPTURE webhook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/phzmvz6vu32nkgz249g3.png)

**Successful “CAPTURE” webhook:**
```json
{
   "live" : "false",
   "notificationItems" : [
      {
         "NotificationRequestItem" : {
            "additionalData" : {
               "hmacSignature" : ""********************"",
               "bookingDate" : "********************"
            },
            "amount" : {
               "currency" : "USD",
               "value" : 50000 // 500 USD in minor units
            },
            "eventCode" : "CAPTURE",
            "eventDate" : "2023-07-06T16:50:16+02:00",
            "merchantAccountCode" : "YOUR_MERCHANT_ACCOUNT",
            "merchantReference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
            "originalReference" : "TJ5MXF5SK3RZNN82",
            "paymentMethod" : "visa",
            "pspReference" : "FVNHBFGDFVTFWR82",
            "reason" : "",
            "success" : "true"
         }
      }
   ]
}
```

If you use an invalid _PspReference_ (f.e. when you use the _PspReference_ from an authorization adjustment response), you’ll receive a webhook containing a "transaction not found" message. Likewise, if you attempt to recapture a payment that has already been captured, you will receive an unsuccessful webhook notification with the reason field indicating "Insufficient balance on payment."


**Unsuccessful “CAPTURE” webhook:**
```json
{
   "live" : "false",
   "notificationItems" : [
      {
         "NotificationRequestItem" : {
            "additionalData" : {
               "hmacSignature" : ""********************"",
               "bookingDate" : "********************"
            },
            "amount" : {
               "currency" : "USD",
               "value" : 50000
            },
            "eventCode" : "CAPTURE",
            "eventDate" : "2023-07-06T16:45:55+02:00",
            "merchantAccountCode" : "YOUR_MERCHANT_ACCOUNT",
            "merchantReference" : "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
            "originalReference" : "WBG6F4K25HXXGN82",
            "pspReference" : "N99H9LX8NV5X8N82",
            "reason" : "Transaction not found",
            "success" : "false"
         }
      }
   ]
}
```



**Reversals**
To cancel or refund a payment, send a request to the /payments/**TJ5MXF5SK3RZNN82**/reversals endpoint. Notice that we're still using the _PspReference_ **TJ5MXF5SK3RZNN82** from the initial pre-authorization. This request is useful when you want to return the funds to your guest, but are not certain whether the payment has been captured or not.

This will either: 

- Cancel the payment – in case it has not yet been captured. 
- Refund the payment – in case it has already been captured.


**Reversal request:**
```json
{
    "reference": "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
    "merchantAccount": "YOUR_MERCHANT_ACCOUNT"
}
```



**Reversal response:**
```json
{
    "merchantAccount": "YOUR_MERCHANT_ACCOUNT",
    "paymentPspReference": "TJ5MXF5SK3RZNN82", // The original pre-authorization pspReference
    "pspReference" : "GF445R8G6L2GWR82",
    "reference": "7a5d8be7-cceb-4442-b17f-3a10a8fa396d",
    "status" : "received"
}
```


![Image of Adyen sending the CANCEL_OR_REFUND webhook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wg0fg7prcr0j182m1lh3.png)

**“CANCEL_OR_REFUND” webhook**
```json
{
   "live":"false",
   "notificationItems":[
      {
         "NotificationRequestItem":{
            "additionalData":{
               "modification.action": "refund"
            },
            "amount":{
               "currency": "USD",
               "value": 50000
            },
            "eventCode":"CANCEL_OR_REFUND",
            "eventDate":"2023-07-06T17:25:23+02:00",
            "merchantAccountCode":"YOUR_MERCHANT_ACCOUNT",
            "originalReference":"TJ5MXF5SK3RZNN82", // The original pre-authorization pspreference
            "paymentMethod":"mc",
            "pspReference":"GF795R5G6L2GWR82",
            "reason":"",
            "success":"true"
         }
      }
   ]
}
```

Now that we’ve seen the flow, here’s a diagram containing the success scenarios.


![Image of the success scenario flow when doing a pre-authorization request](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oarcfhp6bcu0ospw6i8b.png)

1. You send a pre-authorization request to Adyen.
2. After some time, Adyen sends an **AUTHORISATION** webhook.
3. A successful **AUTHORISATION** webhook can be adjusted.
 - (3A) A successful **AUTHORISATION** webhook can be captured.
 - (3B) successful **AUTHORISATION** webhook can be canceled or. refunded
4. A successful **AUTHORISATION_ADJUSTMENT** webhook can be captured.
 - (4A) A successful **AUTHORISATION_ADJUSTMENT** webhook can be canceled or refunded.
5. A successful **CAPTURE** webhook can be canceled or refunded.
6. After receiving a successful **CANCEL_OR_REFUND** webhook, the refund can still be rejected by the card scheme. There are two webhooks that may be sent afterwards.
 - **REFUND_FAILED** webhook.
 - **REFUNDED_REVERSED** webhook.

**"[REFUND_FAILED](https://docs.adyen.com/online-payments/refund/#refund-failed)" webhook**
When Adyen sends a successful REFUND webhook, it means that our validations were successful and we sent the refund request to the card scheme. However, the card scheme can still reject the refund. This can happen even a few days after you submitted the refund request. To handle these [failure reasons](https://docs.adyen.com/online-payments/capture/failure-reasons/), refer to our documentation on what to do next. 

To test failed refunds, you can make a pre-authorization request and enter the holder name “refund failed”, to test this scenario.

**"[REFUNDED_REVERSED](https://docs.adyen.com/online-payments/refund/#refunded-reversed)" webhook**
For some payment methods, for example bank transfers, iDEAL, or Bancontact, the status of the payment can change from “**REFUND**” to “**REFUNDED_REVERSED**”. This means that the funds have been returned to Adyen, and are back in your account. This can happen, for example, if the bank account is no longer valid. 

Below you can find a full chart of the webhooks with the different event codes. Red indicates that the “success”-flag is set to false, while green indicates that the webhook was successful. 


![Flowchart image of the webhooks with event codes that Adyen sends to your application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lijuwqcb91877nrp5yvc.png)

You can find a fully working integration-example on our [Github page](https://github.com/adyen-examples/adyen-dotnet-online-payments/tree/main/authorisation-adjustment-example).


## Summary

We’ve seen how you can use Adyen [pre-authorizations and authorization adjustments](https://docs.adyen.com/online-payments/adjust-authorisation/) to implement a hotel booking use case. We’ve gone over the API responses and webhooks that a developer can encounter. The following steps were described in-depth:

1. Perform the pre-authorization request
2. Increase or decrease the amount using authorization adjustments; optionally extend the expiry date of the authorization
3. Capture the final amount
4. Perform payment reversals (cancel or refund) 


We’re always looking for ways to improve our existing [integration examples](https://www.github.com/adyen-examples) or build new integrations for our developers. 

Have a look at [developers.adyen.com](https://developers.adyen.com) today or let us know on [Twitter](https://twitter.com/adyendevs) what you’d like to see next!