Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/paramveer-cyber/Deployaar/llms.txt

Use this file to discover all available pages before exploring further.

The Razorpay webhook endpoint receives payment lifecycle events from Razorpay and keeps your organization’s billing state in sync with actual payment outcomes. When a payment is captured, fails, or a subscription is cancelled, Razorpay delivers a signed POST to POST /api/razorpay/webhook. Deployaar verifies the payload signature using RAZORPAY_WEBHOOK_SECRET, extracts the organizationId from the payment notes, and updates the organization’s billing plan and status in the database accordingly.

Endpoint

POST /api/razorpay/webhook

Required Headers

HeaderDescription
x-razorpay-signatureHMAC-SHA256 signature of the raw request body. Computed by Razorpay using your RAZORPAY_WEBHOOK_SECRET.
Content-TypeMust be application/json.
If the x-razorpay-signature header is absent, the request is rejected immediately with a 401.

Signature Verification

Deployaar computes the expected signature as:
HMAC-SHA256(key=RAZORPAY_WEBHOOK_SECRET, message=<raw request body>)
The resulting hex digest is compared to the value in the x-razorpay-signature header using a strict string equality check. If the signatures do not match, handleWebhook throws "Invalid Razorpay webhook signature" and the server returns 401 {"error": "Invalid signature"}. No billing state is changed when verification fails.
This route uses express.raw({ type: 'application/json' }) specifically so the raw request bytes are available for signature verification. Do not add a JSON body-parsing middleware (e.g. express.json()) before this route — doing so consumes the raw buffer and replaces req.body with a parsed object, which breaks the HMAC check and causes all webhook deliveries to fail signature verification.

Handled Events

Deployaar reads the event field from the parsed webhook payload and routes it to the appropriate billing update. The organizationId is resolved from payload.payment.entity.notes.organizationId or payload.subscription.entity.notes.organizationId — these notes are embedded in the Razorpay order at creation time by Deployaar’s own createOrder function.
EventBilling Effect
payment.capturedUpdates the organization’s billing plan to the targetPlan stored in the payment notes (e.g. pro or pro_max). Sets billing status to active.
payment.failedSets the organization’s billing status to past_due. The plan tier is not downgraded immediately.
subscription.cancelledSets the organization’s billing status to inactive.
Any other eventLogged at debug level. No database changes are made.
If the webhook payload is missing an organizationId in the payment or subscription notes, the event is logged as a warning and dropped — no billing changes occur. This prevents orphaned webhook deliveries from corrupting billing state.
The billing plan values written to the database map to Deployaar’s three tiers:
Plan valueDisplay namePrice (INR)
freeDeployaar Free
proDeployaar Pro₹1,499
pro_maxDeployaar Pro Max₹2,999

Response Codes

StatusBodyMeaning
200{"received": true}Event processed successfully (or event type not handled — acknowledged with no action).
401{"error": "Missing x-razorpay-signature header"}The x-razorpay-signature header was not present in the request.
401{"error": "Invalid signature"}HMAC-SHA256 verification failed. The payload may have been tampered with, or RAZORPAY_WEBHOOK_SECRET is misconfigured.
Errors that occur after a successful signature check (e.g. a transient database failure) are swallowed and still return 200 {"received": true}. This prevents Razorpay from continuously retrying deliveries for non-recoverable server-side errors.

Setting Up

1

Open the Razorpay Dashboard

Log in to the Razorpay Dashboard. Navigate to Settings → Webhooks and click Add New Webhook.
2

Set the Webhook URL

Enter your deployed API URL as the webhook destination:
https://{api-url}/api/razorpay/webhook
Make sure the URL is publicly reachable and uses HTTPS. Razorpay does not deliver to plain HTTP endpoints in production.
3

Select webhook events

Enable at minimum the following events:
  • payment.captured — fires when a one-time payment is successfully captured. This is the primary event that upgrades a plan.
  • payment.failed — fires when a payment attempt fails. Deployaar sets the org to past_due.
  • subscription.cancelled — fires when a Razorpay subscription is cancelled. Deployaar sets the org to inactive.
4

Copy the webhook secret

After saving, Razorpay generates a webhook secret. Copy it and set it as the RAZORPAY_WEBHOOK_SECRET environment variable in your API deployment.
RAZORPAY_WEBHOOK_SECRET=whsec_your_razorpay_webhook_secret_here
5

Set your Razorpay API keys

In the Razorpay Dashboard under Settings → API Keys, generate a key pair. Set both values in your API environment:
RAZORPAY_KEY_ID=rzp_live_xxxxxxxxxxxx
RAZORPAY_KEY_SECRET=your_razorpay_key_secret
RAZORPAY_KEY_ID is also returned to the frontend during checkout so Razorpay.js can open the payment modal. RAZORPAY_KEY_SECRET is used server-side to create orders and verify inline payment signatures.

Testing with a Mock Delivery

You can simulate a payment.captured event locally using curl. Replace <secret> with your RAZORPAY_WEBHOOK_SECRET:
# 1. Build the payload — include the organizationId in notes
PAYLOAD='{
  "event": "payment.captured",
  "payload": {
    "payment": {
      "entity": {
        "order_id": "order_test123",
        "notes": {
          "organizationId": "your-org-uuid-here",
          "targetPlan": "pro"
        }
      }
    }
  }
}'

# 2. Compute the HMAC-SHA256 signature
SECRET="your-razorpay-webhook-secret"
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')

# 3. Send the mock webhook
curl -X POST http://localhost:8000/api/razorpay/webhook \
  -H "Content-Type: application/json" \
  -H "x-razorpay-signature: $SIGNATURE" \
  -d "$PAYLOAD"
A correctly signed request returns 200 {"received":true} and the organization’s billing plan is updated in the database.
For a full explanation of plan tiers, usage limits, and the checkout flow, see the Billing Plans reference.

Build docs developers (and LLMs) love