Revenue attribution
Razorpay
Connect Razorpay with a key pair and a webhook secret so ProductLense records captured payments, refunds and the fee Razorpay charged, GST included.
ProductLense reads your Razorpay customers, subscriptions, payments and refunds, with the fee on each payment. ProductLense only reads: it never writes to your Razorpay account, never refunds, cancels, captures or changes anything.
What you need
| Field | Secret | Where to find it |
|---|---|---|
| Key ID | No | rzp_live_... from Razorpay Dashboard → Account & Settings → API Keys. |
| Key secret | Yes | The secret paired with the key id. |
| Webhook secret | Yes | The secret you set when creating the webhook in Razorpay Dashboard → Webhooks. |
Every plan includes one billing connection per site, Free too; Growth and Scale allow any number. See plans and limits.
Permissions
Razorpay API keys are not scoped; ProductLense only reads with yours. It calls GET /v1/customers, /v1/subscriptions, /v1/plans/{id} (each plan once, cached), /v1/payments and /v1/refunds.
Set up
- In Razorpay Dashboard, open Account & Settings → API Keys and generate a live key pair.
- In ProductLense, open your site's Settings → Billing connections → Razorpay, paste the key id and secret, and click Connect and import history.
- Copy the webhook URL from the connection card.
- In Razorpay Dashboard → Webhooks, add a webhook with that URL, set a secret and tick the events below.
- Paste the same secret into the connection in ProductLense.
Webhook
URL: https://api.productlense.app/api/webhooks/razorpay/<connection-id> (ProductLense shows the exact URL after you save).
Events ProductLense uses:
payment.captured,payment.authorized,payment.failedrefund.processed,refund.created,refund.failed- every
subscription.*event
Verification: the X-Razorpay-Signature header, an HMAC-SHA256 of the raw body with your webhook secret. Razorpay signatures carry no timestamp; replays are rejected by event id.
What ProductLense reads
- Customers: email, name and notes. Payments made without a Razorpay customer are keyed by the payer's email.
- Subscriptions: status, with the amount and interval from the plan.
- Payments: captured payments count as revenue. Failed payments are kept with status failed and add nothing to revenue.
- Refunds: processed refunds.
- History: the last 12 months on first connect, then a nightly reconcile at 03:00 UTC from the last sync minus 48 hours.
INR amounts stay in INR and are also converted to USD at the European Central Bank rate for the payment's day.
How fees are derived
The fee is the fee field on each payment, which Razorpay reports including GST. It is exact, not estimated.
Match payments to visitors
ProductLense reads the user id from the notes on the customer or on the payment: pl_user_id, user_id, userId or uid. Use the same id you pass to identify. A ProductLense visitor id in pl_visitor_id or visitor_id is also accepted. Without either, ProductLense falls back to the customer email, matched to the email trait sent with identify, or to a user id that is that email.
const order = await razorpay.orders.create({
amount: 99900,
currency: 'INR',
notes: { pl_user_id: user.id },
});