Sandbox to production: the go-live list
On go-live day you change exactly one thing: the key. The rest just has to be ready.
The sandbox opens immediately. Production is enabled on your account once your company is verified. Between the two, there is only a key to change — URLs, payloads and error codes are identical.
It is precisely because the switch is that simple that it deserves a list. Here is the one we walk through with integrators.
What must be true beforehand
Your webhook handler verifies the signature. On the raw body, before any parsing. If you have not tested it with a test event, you have not tested it.
Your webhook handler is idempotent. The same notification can arrive twice. If your code ships an order on every delivery, it will eventually show.
Your creates send an idempotency key. Derived from your own order reference, never from a random value.
You log the `correlationId`. It is returned on every response, successes included. It is what support will ask for, and it is what turns a day-long investigation into a thirty-second lookup.
Your keys are in a vault. Not in the repository, not in a versioned config file, not in a team-channel message.
You have tested something other than the happy path. At minimum: a declined payment, a refund, a partial refund, and a webhook your server answers with an error — to see what happens when we retry.
What the sandbox allows and production forbids
One endpoint forces a subscription's next due date. It exists only in the sandbox, and it is what lets you run a year of subscription in a minute: create the subscription, force three charges, check that your billing follows, that your dunning works, and that cancellation is recorded.
Do it. It is the only way to find a recurring-billing bug before it reaches a real customer.
Switch-over day
You change the key. That is all.
If production is not yet enabled on your account, the production key gets an explicit 403 with code PRODUCTION_ACCESS_NOT_ENABLED — that is not an integration bug, it is an administrative step.
Keep the test key active: you will need it for your staging environments, and it is far healthier to test a change in the sandbox than "carefully" in production.
The three classic oversights
The webhook secret. Sandbox and production sign with different secrets. The integration that switches the API key but keeps the old secret silently rejects every production notification — payments go through, orders don't ship, and the incident looks like anything but its cause.
Test amounts in the code. An amount: 100 left over from a test, a demo discount, an artificial cap: re-read everything that touches an amount with the question "where does this number come from?". In production, every number must come from your database, never from a file.
Development emails and URLs. The notification address still pointing at the developer's inbox, the return URL at localhost: sandbox forgives, production exposes. Searching your configuration for localhost, test@ and .dev takes two minutes.
Keeping environments separate, durably
Going live is not a migration, it is a separation: the sandbox keeps existing, and it is your best tool for what comes next.
Keep one environment of your application permanently wired to the sandbox. That is where the next feature, the version upgrade, the new webhook get tested — with test data and payments that carry no consequences. Teams that delete their sandbox integration on launch day find themselves three months later testing a change to their payment funnel... in production, on real cards.
Concretely: two sets of environment variables, never mixed in one file; keys named by environment in your secrets manager; and a technical — not merely cultural — ban on calling the production API from a development machine.
The following week
Look at three things every day for a week:
- the webhook delivery log — an endpoint that piles up failures ends up suspended;
- the daily reconciliation — if your totals do not tie out in the first week, they will not tie out better after a month;
- pending payments that expire — a high rate signals a journey problem, not a bank problem.
A payment flow that works is recognisable by one sign: nobody talks about it any more.
Written by ChariPay team.