# From sandbox to production

> What differs between the sandbox and production, area by area, and the order in which you go live: platform client, addresses, live in the portal, key, webhook endpoint, CLI, patients, payment methods and clinics.

Your integration works in the sandbox and the checklist holds. Production is an environment of its own, not the same client in another mode: its own addresses, its own auth, its own clients, keys and webhook endpoints, and real patients and money. Nothing from the sandbox comes along. The steps go through what differs in the order you go live, once live is open for your organisation: prove everything in the sandbox, get a platform client for production, change the addresses, open live, create a key and an endpoint, and connect a pilot clinic whose first orders you and Rivr follow up together. If live isn't open for your organisation yet, talk to your contact at Rivr.

- Market: Sweden (`se`). Norway differs in currency, payment methods and what happens when nobody pays: https://developers.rivr.io/guides/sandbox-to-production.md?market=no
- Language: English (`en`). Svenska: https://developers.rivr.io/guides/sandbox-to-production.md?lang=sv
- 7 min read · 10 steps
- Page in the portal: https://developers.rivr.io/guides/sandbox-to-production

Every example targets the sandbox (`https://api.test.rivr.io`) and needs test credentials. A platform client's tokens come from `https://auth.test.rivr.io`, an organisation key's from `https://auth.test.rivr.tech`.

## 1. Prove everything in the sandbox first

*Journal system → Rivr*

Before anything is switched, the checklist should hold in the sandbox, with your own code at both ends. The guide The checklist before the first clinic says what must be proven, and the guide Test in the sandbox how it is tried.

Two CLI commands probe your receiver without anything going to Rivr. `rivr verify` sends signed test deliveries to the address in `--url` and checks the answers, among them to a duplicate, a wrong signature, a timestamp that is too old, a delivery without a signature and events in the wrong order. `rivr verify --sequence` instead sends one order's events in a row (`invoice-paid`, `refund`, `cancel`, `out-of-order`, `late-duplicate` or `same-status`) and says at the end which status the order should have in your journal. Both sign with your own secret in `RIVR_WEBHOOK_SECRET` and exit with an error code when something fails, so they can run in your CI against the same receiver code that will take production's deliveries.

**Why:** Production has no test orders and no replay in the portal. What isn't proven in the sandbox is otherwise tried for the first time with a real patient.

**What your system does:** Write down what you have proven and how, and what can't be tried in the sandbox and is therefore left for the pilot clinic (see the step on payment methods).

**In the portal:** [The guide The checklist before the first clinic](https://developers.rivr.io/guides/go-live)

## 2. A platform client for production

*Rivr → Journal system*

The sandbox and production are two separate environments, each with its own auth, monolith and rivr-webhook. The platform client from the sandbox therefore doesn't exist in production. Rivr creates a new client for your platform in production and hands over `client_id` and `client_secret`, as in the sandbox. Ask your contact at Rivr for it.

What Rivr switches on per platform applies in the environment where it was switched on. The onboarding links are one example: until Rivr has switched them on for your platform in production, `POST /api/public/onboarding-links` answers `403` with `onboarding_not_enabled` there.

**Why:** No client, key or secret is valid in both environments, so a call with the sandbox's credentials can never reach a real clinic.

**What your system does:** Keep one set of credentials per environment in your configuration, and put production's secret only where production's code runs.

> **Rule.** Test keys only work in the sandbox, and production's keys only in production.

## 3. Change the addresses

*Journal system → Rivr*

Production's addresses are the sandbox's without `.test`:

- **The API**, `/api/public`: `api.rivr.io`.
- **The platform token** for `/api/public`: `auth.rivr.io`, on the path `/connect/token` and with a JSON body, as in the sandbox.
- **An organisation key's token**: `auth.rivr.tech`, on the path `/connect/token` and form-encoded, as in the sandbox.

`resource=https://api.rivr.io` in the key's token request doesn't change. It is the token's audience, not an address, and the same in both environments.

Without a sign-in and in the sandbox, the guides and their code samples show the sandbox's addresses. In a session in live, the portal shows the same guides with production's addresses.

**Why:** Each environment has its own auth, so a token from the sandbox isn't accepted in production, and the other way round.

**What your system does:** Read the three addresses from configuration, one set per environment, and switch them together with the credentials.

## 4. Live in the portal

*Journal system → Rivr*

The portal has two environments, the sandbox and live, and once live is open for your organisation the switch in the portal moves between them. Switching needs an active membership in production for your email address, a sign-in that proved the address and a passkey you have confirmed within the last 15 minutes. Add the passkey under Passkeys for live on the Account page. A session in live is moved back to the sandbox 12 hours after the passkey was confirmed.

In live the portal reads production's orders, settlements, devices, API log and the deliveries to your endpoints, but without customer data: orders show without reference, metadata and OCR, the API log without bodies and headers, and orders are searched by order number only. The Workbench reads but doesn't write. Keys, webhook endpoints and the team, on the other hand, you manage in live, with a passkey: the next two steps cover the key and the endpoint. What writes to the clinics' orders and money or exists only for testing answers `403` with `sandbox_only`: creating test orders, sending an order to a device, refunding, replaying deliveries, the virtual device and the relay.

**Why:** A test order in live would be a real order, and a refund moves real money. So only your own code writes to production's orders.

**What your system does:** Build everything the staff need to do with an order, such as cancelling and refunding, into your own system against the API. The portal in live is for following up.

## 5. The organisation key is created in live

*Journal system → Rivr*

Keys from the sandbox don't exist in production. If your integration uses an organisation key, you create production's key under API keys in live. As in the sandbox, an admin of the organisation creates, changes and revokes keys, and in live they must also have confirmed with their passkey within the last 15 minutes. The secret is shown only once, and an organisation can have at most 10 active keys.

A key can't be rotated. Switch like this instead: create a new key, switch your configuration to it and then revoke the old one. Both work in the meantime, and a revoked key stops working within about a minute, including for tokens it already has.

**Why:** A key reaches the whole organisation and everything under it, so creating and revoking one is the admin's job.

> **Rule.** Rivr stores only a hash of the secret, so it can't be shown again. Put it straight into production's secret store.

**In the portal:** [The guide Which key do I need?](https://developers.rivr.io/guides/which-key)

## 6. A webhook endpoint of your own in live

*Rivr → Journal system*

Endpoints from the sandbox don't exist in production either. Set up production's receiver under Webhooks in live. An admin does that, in live with a passkey confirmed within the last 15 minutes. The endpoint gets a new signing secret, which is shown once. "Send test" then sends a signed test delivery with made-up data, so you see that the receiver answers `2xx` and verifies the signature before real events arrive.

The endpoint gets the events of the orders your organisation's own keys create. An order created with the platform client's token takes the clinic path: to the order's `callbackUrl`, or to the address Rivr has configured when the order has none. The guide The webhook didn't arrive sorts out the paths. Rivr switches deliveries to organisations' endpoints on per environment. While they are switched off in production no deliveries are created. Check with your contact at Rivr that they are on before the pilot clinic is connected.

The address must be https, and the retry schedule is the same as in the sandbox: 14 attempts over about seven days. A delivered delivery stays in the log for 30 days. What differs is that the portal replays deliveries only in the sandbox. If Rivr has given up on a delivery in production, fetch the order with `GET /api/public/orders/{orderId}` and act on that.

**What your system does:** Put production's secret into the receiver's verification and run "Send test" before the pilot clinic is connected.

**In the portal:** [The guide The webhook didn't arrive](https://developers.rivr.io/guides/webhook-troubleshooting)

## 7. The CLI belongs to the sandbox

*Journal system → Rivr*

The CLI's sign-in is the sandbox's and isn't approved in live. Everything that runs through the portal therefore exists only in the sandbox: `rivr listen` and the relay URL, `rivr trigger`, `rivr journey`, and `rivr api` and `rivr orders` with your sign-in. Production's deliveries should go to your own public https receiver, never to a relay URL.

`rivr verify` and `rivr send` never contact Rivr. They sign test deliveries with your own secret and send them where you say. With an organisation key in `RIVR_CLIENT_ID` and `RIVR_CLIENT_SECRET`, `rivr api`, `rivr orders` and `rivr whoami` call the sandbox, unless `RIVR_TOKEN_URL` and `RIVR_API_BASE` point elsewhere.

## 8. Real patients

*Rivr → Patient*

A sandbox clinic that Rivr sets up for you accepts only test identities and sends neither texts nor emails to the patient. A clinic in production doesn't have those settings: the personal numbers are real people's, and texts and emails go to the phone number and email address on the order according to the clinic's settings.

Protected identity and people the register can't identify you first meet in production, since the portal has no test number that gives them. How your system should show them is in the guide Patients who can't be identified, and what Rivr echoes in calls and webhooks in the guide Patient data in your calls and webhooks.

**Why:** In the standard flow a text with a payment link goes to the number on the order as soon as the order is created.

**What your system does:** Create no test orders in production: every order there is real. Send the personal number, phone and email that belong to the payer.

## 9. Payment methods you first see in production

*Patient → Rivr*

In the sandbox you pay yourselves: with the simulated card reader on the virtual device, with Rivr's own Swish against Swish's simulator and by invoice up to `Pending`. In production the patient pays on the clinic's real payment device or through the payment link, with the payment methods the clinic's settings and market give.

Some paths can't be completed in the sandbox, or aren't documented as completable there: an invoice being paid, from `Pending` to `Completed`, an approved credit check for Avarda invoice and instalments, and Swish through Adyen. Trustly, Apple Pay, Google Pay and Medical Finance aren't shown on the virtual device at all. You first see these with the pilot clinic, and the full list is in the step What does not work yet in the guide Test in the sandbox. Your receiver can still be proven for the invoice: `rivr verify --sequence invoice-paid` sends one order's events from `Created` through `Pending` to `Completed` by invoice.

**What your system does:** Follow the first payments with each payment method closely in the pilot, and compare your journal with the order's status at Rivr.

**In the portal:** [The guide Test in the sandbox](https://developers.rivr.io/guides/testing)

## 10. The pilot clinic and the first orders

*Rivr → Clinic*

You and Rivr pick the first real clinic together. With an onboarding link from your platform, the person with signatory rights signs the agreement with BankID, as in the guide Connect a clinic from your system, but only once Rivr has switched the onboarding links on for your platform in production.

For an organisation key to reach the clinic, the clinic has to be connected to your organisation, and Rivr makes that connection today. Until the clinic is active and connected, a call for it answers `403` with `organization_not_accessible`.

**What your system does:** Follow up the first real orders together with Rivr. Compare your journal with the orders under Orders in live, searched by order number, and with the deliveries under Webhooks.

**In the portal:** [The guide Connect a clinic from your system](https://developers.rivr.io/guides/onboarding-links)

## Common pitfalls

- Taking the sandbox's client, keys, secrets or endpoints to production. None of them exist there: Rivr creates the platform client, and you create the key and the endpoint in live.
- Fetching the platform token from the key's address, or the key's token from the platform's. The platform token comes from `auth.rivr.io` with a JSON body, the key's token from `auth.rivr.tech` form-encoded.
- Counting on the portal's replay in production. It exists only in the sandbox: fetch the order with `GET /api/public/orders/{orderId}` and act on that.
- Creating test orders in production to see that everything works. Every order there is real, and in the standard flow a text with a payment link goes to the number on the order at once.
- Letting production's deliveries go to a relay URL from `rivr listen`. The relay belongs to the sandbox.

## Next guide

- [Test in the sandbox](https://developers.rivr.io/guides/testing.md): What you can try in the sandbox today, how to do it, which test values exist and what does not work yet.
- [The webhook didn't arrive](https://developers.rivr.io/guides/webhook-troubleshooting.md): A decision tree for a missing webhook: which path it should take, whether it was sent at all, why the delivery fails and what to do once Rivr has given up.
- [Patients who can't be identified](https://developers.rivr.io/guides/unidentified-patients.md): Protected identity, personal numbers the register can't find, orders without a personal number and children whose guardian pays: when Rivr requires an identified payer, what happens when it can't, and what your system should show.
- [Which key do I need?](https://developers.rivr.io/guides/which-key.md): The platform client and the organisation key open different doors. How to tell which one you need for which call, and which capabilities control what.
