> ## 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.

# Webhooks

> Webhooks are server callbacks to your server from Cashfree Payments. Webhooks are event-based and are sent when specific events related to that transaction happen.

## Configure webhook

* You can now configure webhooks from the [Merchant Dashboard](https://merchant.cashfree.com/auth/login). See [Configure webhooks](/payments/online/webhooks/configure) to know how to add a new webhook.
* Ensure you do not process duplicate events.

Webhooks will be sent to your configured endpoint as a POST request with the body containing the various parameters specifying the details of each event. Each request contains an event parameter that identifies its type.

Below are the various events that can be sent to your webhook endpoint.

* SUBSCRIPTION\_STATUS\_CHANGE
* SUBSCRIPTION\_NEW\_PAYMENT
* SUBSCRIPTION\_PAYMENT\_CANCELLED
* SUBSCRIPTION\_PAYMENT\_DECLINED
* SUBSCRIPTION\_AUTH\_STATUS
* REFUND\_STATUS

## SUBSCRIPTION\_STATUS\_CHANGE

<Note> The parameters "cf\_subscriptionId" will be available from 31st July 2023 onwards. </Note>

| Parameter          | Type                                   | Description                                                                                                                                                      |
| :----------------- | :------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf\_event          | String                                 | This event is triggered whenever the subscription status changes. The value for this event is SUBSCRIPTION\_STATUS\_CHANGE.                                      |
| cf\_subReferenceId | Integer                                | A unique Id which was generated when the subscription was created.                                                                                               |
| cf\_status         | String                                 | The new status of the subscription. See [Subscription lifecycle](/payments/subscription/create#subscription-lifecycle) for information on subscription statuses. |
| cf\_lastStatus     | String                                 | The old status of the subscription. See [Subscription lifecycle](/payments/subscription/create#subscription-lifecycle) for information on subscription statuses. |
| cf\_eventTime      | String \[format - yyyy-MM-dd HH:mm:ss] | The time when the event was dispatched.                                                                                                                          |
| cf\_subscriptionId | String                                 | The subscription Id  passed by the merchant while creating the subscription                                                                                      |
| signature          | String                                 | A unique string which helps distinguish that the request is genuine and initiated by Cashfree. See [Verify signature](#verify-signature) for more information.   |

***

## SUBSCRIPTION\_NEW\_PAYMENT

<Note> The parameters "cf\_subscriptionId" and "cf\_merchantTxnId" will be available from 31st July 2023 onwards. </Note>

| Parameter          | Type                                   | Description                                                                                                                                                    |
| :----------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf\_event          | String                                 | This event is triggered whenever there is a successful new payment for an authorized subscription. The value for this event is SUBSCRIPTION\_NEW\_PAYMENT.     |
| cf\_subReferenceId | Integer                                | A unique Id which was generated when the subscription was created.                                                                                             |
| cf\_eventTime      | String \[format - yyyy-MM-dd HH:mm:ss] | The time when the event was dispatched.                                                                                                                        |
| cf\_orderId        | String                                 | The unique order ID against which the payment is made.                                                                                                         |
| cf\_paymentId      | Integer                                | The unique paymentId for the payment.                                                                                                                          |
| cf\_amount         | Float                                  | The amount charged for payment.                                                                                                                                |
| cf\_subscriptionId | String                                 | The subscription Id  passed by the merchant while creating the subscription                                                                                    |
| cf\_merchantTxnId  | String                                 | An id unique to the transaction that merchant passed while raising a transaction for a subscription.                                                           |
| cf\_referenceId    | Integer                                | The unique txnId for the payment.                                                                                                                              |
| cf\_retryAttempts  | Integer                                | The number of payment retries. This is applicable for failed payments.                                                                                         |
| signature          | String                                 | A unique string which helps distinguish that the request is genuine and initiated by Cashfree. See [Verify signature](#verify-signature) for more information. |

***

## SUBSCRIPTION\_PAYMENT\_CANCELLED

<Note> The parameters "cf\_subscriptionId" and "cf\_merchantTxnId" will be available from 31st July 2023 onwards.</Note>

| Parameter          | Type                                   | Description                                                                                                                                                    |
| :----------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf\_event          | String                                 | This webhook is triggered when the charge is cancelled. The value for this event is PAYMENT\_CANCELLED\_WEBHOOK.                                               |
| cf\_subReferenceId | Integer                                | A unique ID which was generated when the subscription was created.                                                                                             |
| cf\_eventTime      | String \[format - yyyy-MM-dd HH:mm:ss] | The time when the event was dispatched.                                                                                                                        |
| orderId            | String                                 | The unique order ID against which the payment is made.                                                                                                         |
| paymentId          | Integer                                | The unique paymentId for the payment.                                                                                                                          |
| amount             | Float                                  | The amount charged for payment.                                                                                                                                |
| subscriptionId     | String                                 | The subscription Id passed by the merchant while creating the subscription                                                                                     |
| merchantTxnId      | String                                 | An id unique to the transaction that the merchant passed while raising a transaction for a subscription.                                                       |
| referenceId        | Integer                                | The unique txnId for the payment.                                                                                                                              |
| retryAttempts      | Integer                                | The number of payment retries. This is applicable for failed payments.                                                                                         |
| reasons            | String                                 | Failure reason                                                                                                                                                 |
| signature          | String                                 | A unique string which helps distinguish that the request is genuine and initiated by Cashfree. See [Verify signature](#verify-signature) for more information. |

***

## SUBSCRIPTION\_PAYMENT\_DECLINED

<Note> The parameters "cf\_subscriptionId" and "cf\_merchantTxnId" will be available from 31st July 2023 onwards.</Note>

| Parameter          | Type                                   | Description                                                                                                                                                    |
| :----------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf\_event          | String                                 | This event is triggered whenever a payment fails for an authorized subscription. The value for this event is SUBSCRIPTION\_PAYMENT\_DECLINED.                  |
| cf\_subReferenceId | Integer                                | A unique Id which was generated when the subscription was created.                                                                                             |
| cf\_eventTime      | String \[format - yyyy-MM-dd HH:mm:ss] | The time when the event was dispatched.                                                                                                                        |
| cf\_paymentId      | Integer                                | The unique paymentId for the payment.                                                                                                                          |
| cf\_amount         | Float                                  | The amount charged for payment.                                                                                                                                |
| cf\_subscriptionId | String                                 | The subscription Id  passed by the merchant while creating the subscription                                                                                    |
| cf\_merchantTxnId  | String                                 | An id unique to the transaction that merchant passed while raising a transaction for a subscription.                                                           |
| cf\_referenceId    | Integer                                | The unique txnId for the payment.                                                                                                                              |
| cf\_retryAttempts  | Integer                                | The number of payment retries. This is applicable for failed payments.                                                                                         |
| cf\_reasons        | String                                 | A possible reason for failure.                                                                                                                                 |
| signature          | String                                 | A unique string which helps distinguish that the request is genuine and initiated by Cashfree. See [Verify signature](#verify-signature) for more information. |

***

## SUBSCRIPTION\_AUTH\_STATUS

<Note> The parameters "cf\_subscriptionId" and "cf\_merchantTxnId" will be available from 31st July 2023 onwards.</Note>

The event is triggered when the checkout is completed by the customer for success and failed cases.

| Parameter              | Type                                   | Description                                                                                                                                                    |
| :--------------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cf\_event              | String                                 | The event is triggered when the checkout fails The value for this event is SUBSCRIPTION\_AUTH\_STATUS.                                                         |
| cf\_subReferenceId     | Integer                                | A unique Id which was generated when the subscription was created.                                                                                             |
| cf\_eventTime          | String \[format - yyyy-MM-dd HH:mm:ss] | The time when the event was dispatched.                                                                                                                        |
| cf\_subscriptionStatus | String                                 | The status of the subscription. See [Subscription lifecycle](/payments/subscription/create#subscription-lifecycle) for information on subscription statuses.   |
| cf\_authStatus         | String                                 | Checkout status. Allowed value: FAILED                                                                                                                         |
| cf\_subscriptionId     | String                                 | The subscription Id  passed by the merchant while creating the subscription                                                                                    |
| cf\_merchantTxnId      | String                                 | An id unique to the transaction that merchant passed while raising a transaction for a subscription.                                                           |
| cf\_authTimestamp      | String \[format - yyyy-MM-dd HH:mm:ss] | Checkout initiated timestamp.                                                                                                                                  |
| cf\_authFailureReason  | String                                 | Possible checkout failure. It will be empty for successFul authStatus change.                                                                                  |
| signature              | String                                 | A unique string which helps distinguish that the request is genuine and initiated by Cashfree. See [Verify signature](#verify-signature) for more information. |

***

## REFUND\_STATUS

| Parameter                | Type                                   | Description                                                                                                                                                   |
| :----------------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| cf\_event                | String                                 | This event is triggered whenever a refundStatus of a transaction will be success or failed or cancelled. The value for this event is REFUND\_STATUS\_WEBHOOK. |
| cf\_subReferenceId       | Integer                                | A unique Id that was generated when the subscription was created.                                                                                             |
| cf\_eventTime            | String \[format - yyyy-MM-dd HH:mm:ss] | The time when the event was dispatched.                                                                                                                       |
| cf\_sub\_refund\_id      | String                                 | A unique ID that is generated for every refund at the initialisation of refund state.                                                                         |
| cf\_payment\_id          | Integer                                | The unique payment ID for the payment.                                                                                                                        |
| cf\_refund\_amount       | BigDecimal                             | The amount that is to be refunded                                                                                                                             |
| cf\_refund\_id           | Integer                                | The refund ID is a unique ID generated when processing a refund.                                                                                              |
| cf\_merchant\_refund\_id | String                                 | A unique ID for the transaction that merchant passed while raising a refund.                                                                                  |
| cf\_refund\_status       | String                                 | Refund status of the transaction.                                                                                                                             |
| signature                | String                                 | A unique string which helps distinguish that the request is genuine and initiated by Cashfree. See [Verify signature](#verify-signature) for more information |

***

## Verify signature

Verifying the signature (passed along with the POST parameters) is mandatory before you process any response. We also recommend whitelisting only our IP address on your webhook endpoint.

Follow the steps below to calculate & verify the signature on the webhook payload:

1. Please sort the webhook payload in alphabetical order based on fields which are starting with field cf\_.
2. Append the key-value pair w/o using any delimiter and create a string.
3. Hash the string using the secret key which will be provided to you.
4. Encode the hashed string using base64 and generate the signature.

**Example** :

1. Sample web hook payload -
   ```
   {
      "cf_retryAttempts":0,
      "cf_amount":1,
      "cf_event":"SUBSCRIPTION_NEW_PAYMENT",
      "cf_eventTime":"2022-01-10 10:03:50",
      "cf_paymentId":1,
      "cf_referenceId":2,
      "cf_subReferenceId":3,
      "signature":"tT9pXZkT2LuDzXacYDUaur7EX3dJgNKcITHQng44tns="
   }
   ```

2. Sorted web hook payload - <pre><code>cf\_amount1cf\_eventSUBSCRIPTION\_NEW\_PAYMENTcf\_eventTime2022-01-10 10:51:02cf\_paymentId1cf\_referenceId2cf\_retryAttempts0cf\_subReferenceId3</code></pre>

3. Signature generated using encoding with secret key - <pre><code>tT9pXZkT2LuDzXacYDUaur7EX3dJgNKcITHQng44tns=</code></pre>

4. Generated signature should match the signature present in the webhook payload.

Following code snippets show you how to generate and verify the signature. This should not be assumed production-ready, kindly consider adding necessary validation before processing.

<CodeGroup>
  ```java Java theme={"dark"}
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import java.util.*;
  public class SignatureVerification {
      private static final String MAC_SHA256_ALGO = "HmacSHA256";
      private static final String SECRET_KEY = "ac7960e7995536f0177fd210f3b3937fc2d974a4"; // Merchant secret key
      public boolean verifySignature(Map<String, Object> payload) {
          String signature = String.valueOf(payload.get("signature"));
          String computedSignature = generateSignature(payload);
          return signature != null && signature.equals(computedSignature);
      }
      public String generateSignature(Map<String, Object> payload) {
          try {
              StringBuilder data = new StringBuilder();
              SortedSet<String> keys = new TreeSet<>(payload.keySet());
              for (String key : keys) {
                  if (key.startsWith("cf_")) {
                      data.append(key).append(String.valueOf(payload.get(key)));
                  }
              }
              Mac mac = Mac.getInstance(MAC_SHA256_ALGO);
              SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(), MAC_SHA256_ALGO);
              mac.init(secretKeySpec);
              byte[] encrypted = mac.doFinal(data.toString().getBytes());
              return Base64.getEncoder().encodeToString(encrypted);
          } catch (Exception ex) {
              // handle
          }
      }

  }
  ```

  ```php PHP theme={"dark"}
  <?php
  class SignatureVerification {
      private const MAC_SHA256_ALGO = 'sha256';
      private const SECRET_KEY = 'ac7960e7995536f0177fd210f3b3937fc2d974a4'; // Merchant secret key
      public function verifySignature(array $payload): bool {
          $signature = $payload['signature'] ?? '';
          $computedSignature = $this->generateSignature($payload);   
          return !empty($signature) && $signature === $computedSignature;
      }
      public function generateSignature(array $payload): string {
          try {
              $data = '';
              ksort($payload);

              foreach ($payload as $key => $value) {
                  if (strpos($key, 'cf_') === 0) {
                      $data .= $key . strval($value);
                  }
              }
              $hmac = hash_hmac(self::MAC_SHA256_ALGO, $data, self::SECRET_KEY, true);
              return base64_encode($hmac);
          } catch (Exception $ex) {
              // Handle exception (log it, throw error, etc.)
              return '';
          }
      }
  }
  ?>
  ```

  ```python Python theme={"dark"}
  import hmac
  import hashlib
  import base64
  from collections import OrderedDict
  class SignatureVerification:
      MAC_SHA256_ALGO = "sha256"
      SECRET_KEY = "ac7960e7995536f0177fd210f3b3937fc2d974a4"  # Merchant secret key
      def verify_signature(self, payload: dict) -> bool:
          signature = str(payload.get("signature", ""))
          computed_signature = self.generate_signature(payload)
          return signature == computed_signature
      def generate_signature(self, payload: dict) -> str:
          try:
              data = "".join(f"{key}{payload[key]}" for key in sorted(payload.keys()) if key.startswith("cf_"))  
              mac = hmac.new(self.SECRET_KEY.encode(), data.encode(), hashlib.sha256)
              return base64.b64encode(mac.digest()).decode()
          except Exception as ex:
              print(f"Error generating signature: {ex}")
              return ""
  ```
</CodeGroup>

**Failure Reasons**

| Code | Reason                                                                   |
| :--- | :----------------------------------------------------------------------- |
| AP01 | Account Blocked                                                          |
| AP02 | Account Closed                                                           |
| AP03 | Account Frozen                                                           |
| AP04 | Account Inoperative                                                      |
| AP05 | No Such Account                                                          |
| AP06 | Not a SBS account number or old account number represent with CBS number |
| AP07 | Refer to the branch KYC not completed                                    |
| AP11 | Authentication Failed                                                    |
| AP14 | Invalid user credentials                                                 |
| AP15 | Mandate not registered\_ not maintaining required balance                |
| AP16 | Mandate not registered\_ minor account                                   |
| AP17 | Mandate not registered\_ NRE Account                                     |
| AP18 | Mandate registration not allowed for CC account                          |
| AP19 | Mandate registration not allowed for PF account                          |
| AP20 | Mandate registration not allowed for PPF account                         |
| AP23 | Transaction rejected or cancelled by customer                            |
| AP24 | Account not in regular Status                                            |
| AP25 | Withdrawal stopped due to insolvency of account                          |
| AP28 | Mandate registration failed. Please contact your home branch             |
| AP29 | Technical errors or connectivity issues as bank                          |
| AP30 | Browser closed by customer in mid-transaction                            |
| AP31 | Mandate registration not allowed for joint account                       |
| AP32 | Mandate registration not allowed for wallet account                      |
| AP33 | User rejected the transaction on pre-login page                          |
| AP34 | Account number not registered with net-banking facility                  |
| AP35 | Debit card validation failed due to\_ Invalid card number                |
| AP36 | Debit card validation failed due to\_ Invalid expiry date                |
| AP37 | Debit card validation failed due to\_ Invalid PIN                        |
| AP38 | Debit card validation failed due to\_ Invalid CVV                        |
| AP39 | OTP invalid                                                              |
| AP40 | Maximum retries exceeded for OTP                                         |
| AP41 | Time expired for OTP                                                     |
| AP42 | Debit card not activated                                                 |
| AP43 | Debit card blocked                                                       |
| AP44 | Debit card hot listed                                                    |
| AP45 | Debit card expired                                                       |
| AP46 | No response received from customer while performing transaction          |
| AP47 | Account number registered for only view rights in net banking facility.  |

<Note> We send the webhook response in a form data format.</Note>
