Skip to main content
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.
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. Other payment modes are not supported in this sandbox preauthorisation path.

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 and the Preauthorisation API. The Order 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 request. If this value is missing or incorrect, Cashfree may not recognise the order as a sandbox preauthorisation transaction.
CURL
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.
order_tags, order_meta, and customer fields follow the usual Create Order API rules. Use a valid notify_url if you rely on Payment Webhooks for payment status.

Initiate payment with Order Pay API

Send the Order Pay API request (POST /orders/sessions) with the payment_session_id from the Create Order API. Set channel to link so the response returns a redirect URL for the customer. Use the following request to initiate a card preauthorisation payment. Replace the placeholder card details with values from the Data to Test Integration page.
CURL
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. For UPI preauthorisation, set authorize_only to true and pass an authorization object with the following fields:
FieldDescription
approve_byThe deadline by which the customer must approve the request (ISO 8601 with offset, for example 2025-12-20T19:20:12+05:30).
start_timeThe time at which the hold or mandate window starts (ISO 8601, UTC Z allowed).
end_timeThe time until which the hold applies (ISO 8601). You can capture or void using the Preauthorisation API while the authorisation is valid, subject to Preauthorisation product rules.
CURL
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 page.

Capture or void the payment

Once you simulate the payment as successfully authorised in sandbox, call the Preauthorisation 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:
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
  }'
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.

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 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 and wait for the authorisation-success event via Payment 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 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 for the full set of timing rules.