Skip to main content
Going live is a configuration cutover, not a rewrite. Your queries, mutations, and flows are identical in both environments. What changes is which hosts you call and which credentials you call them with — and those change completely.
Nothing carries over from staging. Applications, API keys, client secrets, redirect URIs, and webhook subscriptions all exist separately in each environment. A staging credential will never work against a production host, and vice versa. That’s deliberate — it’s what makes it impossible to accidentally move real money from a test harness.

Endpoint map

The GraphQL host and the OAuth host are different services with different domains. Swapping one and not the other is the single most common cutover mistake — and it fails in a confusing way, because authorization succeeds and then every API call is rejected.

Reaching each portal

The live portal is at https://fluz.app/for-developers. From there, the developer tab has an ‘Open Staging’ link into the staging portal — your login credentials are the same in both. Each portal shows only that environment’s applications and API keys.

Make the environment a variable

If any host, key, or redirect URI is a string literal in your codebase, fix that before cutting over. Everything environment-specific belongs in configuration.
Default to staging, never to production. If a deployment loses its environment variable, you want it hitting the test environment, not moving real money.

Rebuild your app in the live portal

Work through Create an OAuth App again against https://fluz.app/for-developers. Then check every one of these — each is something people forget:
1

Reissue every credential

Production client_id, client_secret, apiKey, and apiSecret are all new values. Put them in your production secret store. Confirm no staging value survives in a production config.
2

Re-register redirect URIs against production hosts

Your production callback URL, in its exact canonical form. Then remove any localhost or staging URIs — a production app should not accept a redirect to a developer’s laptop.
3

Re-point webhook URLs

At production endpoints that are publicly reachable, monitored, and alerting. Re-do the per-event subscriptions; they don’t copy across. If you used a catch-all URL in staging, decide whether you actually want that in production.
4

Set Origin to your production domain

For embedded widgets, this must match the domain actually serving the page, or the widget won’t load.
5

Re-select your scopes

Scope selections don’t transfer. Walk your integration’s API calls and confirm each one’s scope is checked on the production app’s Permissions tab. A missing scope is silently dropped, not rejected.
6

Finish the Overview tab

Name, subtitle, description, avatar, and logomark are what real users now see on a real consent screen deciding whether to give you access to their money. Placeholder text ships to production if you let it.
7

Confirm your app's status

Applications carry a status in the dashboard — an app sitting in review is not yet an app your customers can use. Confirm your production app is active before you announce anything.

What behaves differently in production

Staging mirrors production’s capabilities and transaction flows without real money. That’s most of the surface, but not all of it. Three consequences worth planning for:
  • Idempotency stops being optional. Every money-moving call needs a unique idempotencyKey, and widget tokens need a unique jti. In staging a duplicate is a nuisance; in production it’s a double payment. See Idempotency.
  • Your error handling gets exercised. Test users don’t get declined for insufficient funds or fail KYC in ways you didn’t script. Every failure path needs a defined user-facing outcome before launch, not after.
  • Reconciliation matters. Verify balances on both sides of a transfer rather than assuming success from a 200 response.

Data hygiene, both directions

Never put production data in staging. No real customer details, no real financial information, no PII. Staging is for data created explicitly for testing. The reverse also holds: don’t carry test users, test funding sources, or test webhook payloads into production. Test artifacts in a live ledger are hard to unpick later, and some of them can’t be deleted.

Widget cutover

If you’re shipping an embedded widget, the same rules apply plus these:
  • Regenerate the embed code from the production app’s Installation tab. The apiKey baked into the snippet is environment-specific.
  • Sign patTokens with your production apiSecret, server-side. Confirm the secret is loaded from your production secret store and that the token generator is not still pointing at a staging value.
  • Confirm Origin matches your production domain exactly.
  • Re-check the transaction type. Pay-In and Payout move money in opposite directions; verify the direction against a real transfer before you open it to users.

Pre-launch checklist

  • Production app created, configured, and active
  • All four credentials reissued and stored in the production secret store
  • No staging or localhost redirect URIs remain on the production app
  • Webhook URLs point at production endpoints, with event subscriptions re-selected
  • Scopes re-selected and matched against your actual API calls
  • Overview tab complete — name, subtitle, description, avatar, logomark
  • No hard-coded hosts, keys, or redirect URIs anywhere in the codebase
  • Environment resolution defaults to staging
  • Both the OAuth host and the GraphQL host swapped
  • Idempotency keys generated per operation, not per session
  • Callback route is idempotent and validates state
  • Token refresh runs before expiry rather than reacting to a failure
  • Webhook endpoint monitored, with alerting on failure to deliver or process
  • Logging captures request identifiers and idempotency keys, and never captures secrets, PANs, or PII
  • Someone owns the “user can’t connect” and “transfer stuck” runbooks
  • You’ve run one real end-to-end transaction at the smallest possible amount, in both directions, and reconciled both ledgers
  • Internal users first, then a small cohort, then general availability
  • You can disable the integration without a code deploy — a feature flag, not a rollback
  • Re-authorization path built and tested, for when refresh tokens expire or users revoke

Common cutover failures


Next steps

Create an OAuth app

Re-run every tab against your production app.

Grant flow

Verify the consent screen on production hosts.

Refresh an access token

Keep production connections alive without re-prompting.

API features

Everything now running against real money.