> ## Documentation Index
> Fetch the complete documentation index at: https://www.cashfree.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Preauthorisation

> Run the Cashfree preauthorisation flow in sandbox: create an order, hold funds on cards or UPI, and capture or void the authorised amount.

You can run through the full preauthorisation lifecycle in the **sandbox** environment using the same APIs as in production. For product behaviour, supported instruments, and capture or void rules, refer to [Preauthorisation](/payments/features/pre-authorisation).

<Warning>
  In the **sandbox** environment, preauthorisation for API-driven flows works only for **card** and **UPI** when you use the seamless **link** channel on the [Order Pay](/api-reference/payments/latest/payments/pay) API. Other payment modes are not supported in this sandbox preauthorisation path.
</Warning>

## Prerequisites

Ensure the following are in place before you start the sandbox flow:

* Use the sandbox base URL: `https://sandbox.cashfree.com/pg`.
* Send a supported API version in `x-api-version` (for example, `2025-01-01`), consistent with your integration.
* Use `x-client-id` and `x-client-secret` to authenticate calls to the [Create Order](/api-reference/payments/latest/orders/create) API and the [Preauthorisation](/api-reference/payments/latest/payments/authorize) API. The [Order Pay](/api-reference/payments/latest/payments/pay) API does not require these headers. You can call it directly from the client.

## Preauthorisation flow

Complete a preauthorisation transaction in the sandbox by following the three stages below.

### Create an order

For sandbox preauthorisation testing, set `order_note` to **`preauth_transaction`** in your [Create Order](/api-reference/payments/latest/orders/create) API request. If this value is missing or incorrect, Cashfree may not recognise the order as a sandbox preauthorisation transaction.

```bash CURL highlight={16} theme={"dark"}
curl --request POST 'https://sandbox.cashfree.com/pg/orders' \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-01-01' \
  --header 'x-client-id: <your_client_id>' \
  --header 'x-client-secret: <your_client_secret>' \
  --data-raw '{
    "customer_details": {
      "customer_email": "customer@example.com",
      "customer_phone": "9999999999",
      "customer_name": "Test Customer",
      "customer_id": "customer_001"
    },
    "order_amount": 100,
    "order_currency": "INR",
    "order_note": "preauth_transaction",
    "order_meta": {
      "return_url": "https://example.com/return",
      "notify_url": "https://example.com/webhooks/cashfree"
    }
  }'
```

Save the **`order_id`** and **`payment_session_id`** from the response. You will need both values for the [Order Pay](/api-reference/payments/latest/payments/pay) API.

<Note>
  `order_tags`, `order_meta`, and customer fields follow the usual [Create Order](/api-reference/payments/latest/orders/create) API rules. Use a valid `notify_url` if you rely on [Payment Webhooks](/api-reference/payments/latest/payments/webhooks) for payment status.
</Note>

### Initiate payment with Order Pay API

Send the [Order Pay](/api-reference/payments/latest/payments/pay) API request (**`POST /orders/sessions`**) with the `payment_session_id` from the [Create Order](/api-reference/payments/latest/orders/create) API. Set **`channel`** to **`link`** so the response returns a redirect URL for the customer.

#### Card payments (link channel)

Use the following request to initiate a card preauthorisation payment. Replace the placeholder card details with values from the [Data to Test Integration](/api-reference/payments/data-to-test-integration) page.

```bash CURL theme={"dark"}
curl --request POST 'https://sandbox.cashfree.com/pg/orders/sessions' \
  --header 'Content-Type: application/json' \
  --header 'x-api-version: 2025-01-01' \
  --data '{
    "payment_session_id": "<payment_session_id_from_create_order>",
    "payment_method": {
      "card": {
        "channel": "link",
        "card_number": "4111111111111111",
        "card_expiry_mm": "06",
        "card_expiry_yy": "27",
        "card_cvv": "900",
        "card_holder_name": "Test User"
      }
    },
    "save_instrument": true
  }'
```

Open the URL returned under `data.url` (when `action` is `link`) to complete the payment in the browser.

#### UPI payments (link channel)

For UPI preauthorisation, set **`authorize_only`** to **`true`** and pass an **`authorization`** object with the following fields:

| Field        | Description                                                                                                                                                                                                                                                                        |
| :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `approve_by` | The deadline by which the customer must approve the request (ISO 8601 with offset, for example `2025-12-20T19:20:12+05:30`).                                                                                                                                                       |
| `start_time` | The time at which the hold or mandate window starts (ISO 8601, UTC `Z` allowed).                                                                                                                                                                                                   |
| `end_time`   | The time until which the hold applies (ISO 8601). You can capture or void using the [Preauthorisation](/api-reference/payments/latest/payments/authorize) API while the authorisation is valid, subject to [Preauthorisation](/payments/features/pre-authorisation) product rules. |

```bash CURL theme={"dark"}
curl --request POST 'https://sandbox.cashfree.com/pg/orders/sessions' \
  --header 'Content-Type: application/json' \
  --header 'x-api-version: 2025-01-01' \
  --data '{
    "payment_session_id": "<payment_session_id_from_create_order>",
    "payment_method": {
      "upi": {
        "channel": "link",
        "authorize_only": true,
        "authorization": {
          "approve_by": "2025-12-20T19:20:12+05:30",
          "start_time": "2025-12-19T12:34:34Z",
          "end_time": "2026-01-01T12:34:34Z"
        }
      }
    }
  }'
```

Complete the UPI approval flow in sandbox using the test UPI VPA values from the [Data to Test Integration](/api-reference/payments/data-to-test-integration) page.

### Capture or void the payment

Once you simulate the payment as successfully authorised in sandbox, call the [Preauthorisation](/api-reference/payments/latest/payments/authorize) API (`POST /orders/{order_id}/authorization`) with the same **`order_id`** you received when you created the order. Use either action below depending on whether you want to collect or release the funds:

<CodeGroup>
  ```bash Capture theme={"dark"}
  curl --request POST 'https://sandbox.cashfree.com/pg/orders/<order_id>/authorization' \
    --header 'Content-Type: application/json' \
    --header 'x-api-version: 2025-01-01' \
    --header 'x-client-id: <your_client_id>' \
    --header 'x-client-secret: <your_client_secret>' \
    --data '{
      "action": "CAPTURE",
      "amount": 100
    }'
  ```

  ```bash Void theme={"dark"}
  curl --request POST 'https://sandbox.cashfree.com/pg/orders/<order_id>/authorization' \
    --header 'Content-Type: application/json' \
    --header 'x-api-version: 2025-01-01' \
    --header 'x-client-id: <your_client_id>' \
    --header 'x-client-secret: <your_client_secret>' \
    --data '{
      "action": "VOID"
    }'
  ```
</CodeGroup>

You can send `amount` as a number or as a decimal string such as `"100.00"`. The amount must not exceed the authorised order amount. Cashfree supports partial capture. A void request does not require an amount.

You can capture or void each authorisation only once. For business rules such as time limits, refer to [Preauthorisation](/payments/features/pre-authorisation).

## Go live

The sandbox flow above and the production flow use the same APIs. Two things change when you go live:

* **Base URL**: Replace `https://sandbox.cashfree.com/pg` with `https://api.cashfree.com/pg`.
* **`order_note`**: The value `preauth_transaction` is a **sandbox-only** flag that tells Cashfree to treat the order as a preauth test. In production, `order_note` follows your account configuration. Check with your integration or support. Contact if you already use this field for other purposes.

Before you process live transactions, ensure preauthorisation is enabled on your account. Submit a request through the [Preauthorisation feature request](/payments/features/pre-authorisation#pre-authorisation-feature-request) form.

## Best practices

Follow these practices when integrating preauthorisation in sandbox and production:

* **Confirm authorisation before capturing or voiding:** Do not call capture or void based on a client-side redirect alone. Set `order_meta.notify_url` in the [Create Order](/api-reference/payments/latest/orders/create) API and wait for the authorisation-success event via [Payment Webhooks](/api-reference/payments/latest/payments/webhooks) on your server before you proceed.

* **Use idempotency keys for capture and void requests:** Each authorisation can be captured or voided only once. If a network error leaves the outcome uncertain, resend the same request with the **`x-idempotency-key`** header so Cashfree returns the original result instead of rejecting a duplicate. Refer to [API Best Practices](/api-reference/api-best-practices) for usage details.

* **Capture within the time limit:** If you do not capture or void an authorisation within seven days, the hold expires and the funds are released to the customer automatically. Build a reminder or scheduled job so authorised orders do not go unresolved. Refer to [Preauthorisation](/payments/features/pre-authorisation) for the full set of timing rules.
