Payments and payouts · from our own builds
Several apps on one Razorpay account: keeping each app's money apart
One Razorpay account can serve several apps, but every app's webhook endpoint receives the other apps' events, so each app has to tag what it creates with its own name, check that tag on the way in, and confirm ownership by finding the payment in its own database. countrydevs.com and Storafleet share one account in production; our fixes were tagging the plans, subscriptions and orders each app creates, dropping foreign events before they become records, stopping a sibling app's chargebacks from paging the wrong team, and labelling settlements as the whole account's.
- countrydevs.com tool tiers
- Storafleet
Updated 20 October 2026 · checked against our code and the vendors' documentation
Where have we built this?
- countrydevs.com tool tiersThe Subscriptions app on the shared account: notes.app on six create calls, record-scoped handlers and five isolation tests.
- StorafleetThe second app on the account: a webhook controller that drops other apps' events by notes.app, and alerts only about its own disputes and settlements.
What are the numbers and limits to know?
- notes on Razorpay entities
- Up to 15 key-value pairs, 256 characters eachsource, checked 20 October 2026
- Order receipt
- Up to 40 characters, and must be uniquesource, checked 20 October 2026
- Webhook URLs
- Set up separately for live mode and test modesource, checked 20 October 2026
- x-razorpay-event-id
- Unique per event; Razorpay suggests it for spotting duplicate deliveriessource, checked 20 October 2026
- Webhook endpoints on our shared account (Sept 2026)
- Two, one per app, each with its own signing secret; Storafleet's subscribes to 33 events, countrydevs.com's to 23
- Plans visible to one app (July 2026)
- plans.all() returned 14 plans: 8 Storafleet's and 6 from a sibling app
How do you integrate One Razorpay account for several apps, step by step?
- 1
Give each app its own webhook endpoint and secret
API keys belong to the account, so the apps share one test key pair and one live key pair. Webhook signing secrets belong to each endpoint, so each app verifies only its own deliveries. On our account the two apps' test secrets are different, and each app registers its own live endpoint at its own host.
- 2
Stamp notes.app on everything you create
countrydevs.com sets notes.app to its name on six create calls: both plan currencies, checkout subscriptions, prorated upgrade orders, and the subscriptions created by upgrades and by the downgrade job; its customer records and admin refunds do not carry it yet, an open fix. Storafleet stamps its plans, subscriptions and refunds from one constant, so the string that decides whose money it is lives in one place.
- 3
Check the tag on the way in, and decide what a missing tag means
Storafleet's webhook controller drops any entity whose notes.app names another app before it becomes a database row. An entity with no notes at all passes through on purpose, because some, like disputes, never carry notes; the next step has to catch those.
- 4
Prove ownership with your own records
Every handler looks the entity up by its order, subscription or payment ID in its own database and ignores it when nothing matches. countrydevs.com's failed-payment handler returns before writing a ledger row when neither the subscription in notes nor the order is ours; Storafleet's subscription handlers check notes.app and then their own subscription ID.
- 5
Guard alerts, not only writes
A ledger write behind an ownership check can still sit next to an alert that is not. Dispute events need the same check before they notify anyone. Settlements cover the whole account, including the other apps' takings, so Storafleet now sends them as an account-wide notice, not as an error or as its own revenue.
- 6
Reconcile from your own records
countrydevs.com's per-user reconcile starts from the subscriptions in its own database and fetches each by ID, so another app's subscriptions never enter it. The dashboard's active-subscription counter and account-wide lists include every app on the account, so they cannot be used to check one app's numbers. countrydevs.com's daily ledger check still compares against every payment on the account, so Storafleet's takings show up there as a discrepancy; scoping it is an open fix.
- 7
Test with the other app's events
countrydevs.com's isolation suite feeds its handlers a foreign order.paid, a foreign payment.captured with empty notes and with notes.app set to the other app, a foreign payment.failed, and a subscription.charged that is not ours, and asserts that nobody is notified and, where the handler could write, that nothing is written.
What went wrong, and how was it fixed?
The tag was set but never read
Storafleet stamped notes.app on its orders from the start, but no code read it, so once its webhook worked, the other app's validly signed events would have been processed like its own. Setting a tag without checking it protects nothing.
Fix: The controller now drops entities that name another app, using the same constant the create calls use to stamp them.
A sibling app's chargeback raised an urgent alert
Disputes carry no notes, so Storafleet's filter let them through by design. Its dispute handler checked ownership before writing the ledger but not before alerting, so every chargeback on a countrydevs.com payment raised an urgent 'waiting on evidence from us' alert about a payment Storafleet never took.
Fix: The dispute handler returns ignored when no order of ours matches the payment, before any alert.
Settlement alerts for the whole account
Storafleet's settlement handler raised a system-error alert for every settlement, and settlements include the other apps' money. It reported another product's takings, and labelled money reaching the bank as an error.
Fix: The error alert is gone: a settlement now sends a plain notice saying it covers the whole shared account and should be reconciled against the bank statement, not against Storafleet's revenue.
A capture handler that was safe only by luck
On countrydevs.com the one-off capture path read notes.user_id to find the customer. A foreign payment with empty notes did nothing only because looking up an undefined user returns nothing, and the failed-payment handler could write a ledger row for a payment that was not ours.
Fix: An explicit skip for payments whose notes.app names another app, and a short-circuit in the failed-payment handler when neither the subscription nor the order is ours, both pinned by the isolation tests.
An assumption about the other app went out of date
When the account was first shared, countrydevs.com's isolation plan assumed Storafleet would never send subscription events, because it billed with one-off orders. A month later Storafleet moved to Razorpay Subscriptions.
Fix: Test against event shapes, not against what the other app says it uses: the isolation suite already included a subscription.charged that was not ours, and the handlers were safe because they look subscriptions up in their own database.
What should you check before going live?
- notes.app set on every order, subscription, plan and refund you create
- Inbound filter on notes.app, plus a look-up in your own database
- Dispute alerts check ownership first; settlement notices say they cover the whole account
- Reports and reconciliation filtered to your own IDs
- Isolation tests with foreign events for each event family
- Each app's webhook endpoint has its own secret
- A key-rotation plan that switches every app on the account at once
Questions about One Razorpay account for several apps
Does every webhook endpoint on a Razorpay account receive every app's events?
On our shared account, yes: each app's endpoint receives the other app's payment, order and refund events, validly signed for that endpoint, so the signature check passes. Only the tag in notes and a look-up in your own database tell you whether an event is yours.
What should an app put in Razorpay notes?
Its own name and its own IDs: the app, the user and whatever record the payment belongs to. Razorpay allows up to 15 key-value pairs of up to 256 characters each. Do not rely on notes alone, because some entities, such as disputes, arrive without them.
How do you tell which app a Razorpay dispute belongs to?
Look the disputed payment up in each app's own records. A dispute carries no notes, so the app that finds its own order for that payment handles it, and every other app ignores it before alerting anyone.
Do apps on one Razorpay account share API keys?
Yes. The account has one test key pair and one live key pair, so every app uses the same keys, while webhook signing secrets are set per endpoint. Rotating the API keys therefore has to switch every app on the account in the same window.
Can each app still report its own revenue?
Yes, from its own records. Account-wide numbers, such as the dashboard's active-subscription counter, the full plans list or a payments list for a date range, include every app on the account. Count from your own payment and subscription IDs, or filter account lists by notes.app.
What changes when a third app joins the account?
Its events start reaching every existing endpoint the day it goes live. Before then, each existing app should already drop entities tagged for another app and check ownership before any alert, and the new app should tag everything it creates from its first API call.
Need One Razorpay account for several apps in your app?
We have built it in production code, including the parts that went wrong. Tell us what your app needs and we'll say what it takes.
Ask about this integrationRelated guides: Razorpay Subscriptions.