Going to production¶
The path from sandbox to a real customer event.
Production credentials request¶
Once your integration is built and tested in sandbox, email your account contact with:
- Sandbox
client_id(so we can review what you've registered). - Production redirect URIs — exact-match list of the URLs you'll use.
- Production webhook URL.
- A short demo or screenshots of your integration in action.
- For public-catalog integrations: marketing copy, screenshots, terms link, support contact.
We review the submission, confirm the manifest matches what you've registered, and issue production client_id + client_secret + production webhook signing secret. Production credentials are separate from sandbox — same integration name, separate authentication.
Pre-launch checklist¶
Before flipping a real customer to your integration, confirm:
Auth and tokens¶
- [ ] Webhook signature verification works AND fails closed if the signature is missing (a missing signature should be treated as failure, not as "unsigned but otherwise valid").
- [ ] Token storage uses encryption at rest (database-level, KMS envelope, secrets manager — pick one).
- [ ] Refresh-token rotation is implemented: the new refresh token is persisted before any use of the new access token.
- [ ] Refresh-token concurrent races are handled: in-process mutex, distributed lock, or single-flight worker.
- [ ] You catch
400 invalid_granton refresh attempts as a permanent revocation, NOT a transient error. - [ ] You catch
401 token_revokedand401 token_expiredas distinct errors with distinct handlers.
Webhook handling¶
- [ ] You verify HMAC signatures using constant-time comparison (
hmac.compare_digestin Python,crypto.timingSafeEqualin Node, etc.). - [ ] You reject webhook deliveries with stale timestamps (>5 minutes from now).
- [ ] You respond within 10 seconds. Real work that takes longer is queued asynchronously on your side.
- [ ] You deduplicate retries using
X-Revento-Delivery-Id. - [ ] You honor
data.deletion_required— schedule deletion of cached data within 30 days. - [ ] You honor
user.revoked_accessif you store per-user data. - [ ] You're subscribed to the event types you actually need — and ONLY those. Subscribing to event types you don't process adds unnecessary load.
Rate-limit awareness¶
- [ ] You don't hammer the API on schedule when webhooks would tell you the same thing.
- [ ] You back off on 429 with
Retry-After-respecting exponential backoff + jitter. - [ ] You handle
concurrent_limit_exceededby queuing/throttling.
UX and operations¶
- [ ] The OAuth flow has a clear error UX for declined consent.
- [ ] Your dashboard surfaces the disconnect cascade (revoked, archived, suspended) to operators.
- [ ] You have monitoring for: refresh failures, webhook deliveries failing repeatedly, token-revoked errors spiking.
- [ ] You can identify a single (event, organization) connection and trace its API calls + webhook deliveries by
X-Revento-Request-Id. - [ ] You've previewed the consent screen text in both PL and EN — confirm scope descriptions are accurate.
Security¶
- [ ] OAuth state parameter validated on every callback to prevent CSRF.
- [ ] PKCE verifier never leaves your backend (it's not a client-side secret, but careless handling can leak via logs).
- [ ]
client_secretin your environment-variable / secrets-manager only — never in code, never in logs, never in screenshots. - [ ] Webhook signing secret same — secrets manager only.
- [ ] Tokens never logged (or logged as
last 4 chars + lengthonly).
What to expect at production launch¶
For your first production connection:
- The first organizer connects. You receive your first installation token.
- They probably do a small test — maybe approve one application, see it sync, archive a test event, see deletion fire.
- Then they connect their real event.
Don't assume the first connection is going to be a real-event production load. It's typically a sanity test.
Suspension behavior¶
If we need to suspend your integration (security review, compliance concern, terms violation):
- We email you and the organizer.
- All your tokens — installation and user — are invalidated immediately. API calls return
401 token_revoked. Refresh attempts return400 invalid_grant. - An
integration.suspendedwebhook fires once (best-effort — we send it but you might already be in a state where it can't reach you). - The integration is hidden from the catalog (organizers see it greyed out as "Suspended").
- You and the organizers see a banner with a contact link.
Suspension is reversible. Once we resolve the underlying concern with you, we lift it and the integration becomes connectable again. Existing connections do NOT auto-reconnect — organizers see a "Reconnect" CTA.
Versioning your integration¶
Three kinds of changes:
Code-only changes (no scope or URL changes)¶
Just deploy. Doesn't affect customers, doesn't change the contract.
Manifest changes — adding a new scope¶
Per scopes versioning:
- Update your manifest to declare the new scope.
- Update your code to request the new scope on new authorizations.
- Existing connections enter "re-consent required" state. The new scope is unavailable until each organizer re-consents.
- Roll out the new feature gradually as customers re-consent. Don't break existing customers — your code path that uses the new scope must be guarded behind "did this connection grant the scope" checks until everyone has re-consented.
For renaming or splitting scopes, same process — treated as net-new scopes.
Manifest changes — adding webhook event types¶
Update your integration manifest to add the new event types to declared_webhook_event_types. New event types start delivering immediately. No re-consent needed (webhook event types aren't part of organizer consent).
Marketing changes (description, screenshots, etc.)¶
Email us. We update the catalog listing. No code change on your side.
What if you need to deprecate?¶
If you're sunsetting your integration:
- Tell us 30+ days ahead so we can warn affected organizers.
- We mark your integration deprecated in the catalog — existing connections continue to work, but no new connections can be made.
- You communicate the timeline to your customers.
- On end-of-life, you unpublish — every customer's tokens invalidate,
data.deletion_requiredfires per (event, organization). - You delete cached data per the 30-day deadline.
Don't unpublish abruptly without warning. The cascade is fine technically; it's just bad customer experience.
Production-only behaviors¶
Things that work in production but not (or not the same way) in sandbox:
- Real webhook deliveries to real third-party endpoints. Sandbox is the same; production hits real customer-controlled URLs that we don't control.
- Real network behavior. Production has real internet conditions; sandbox traffic is between test environments and is faster.
- Real customer data. Treat it accordingly — encryption at rest, audit logs, access controls on your side.
That's the lot. Same contract, real users.