Going to production¶
The operational readiness step before real customers start connecting your integration to real events.
There is no separate "production credentials" issuance - your existing client_id / client_secret authenticate the integration regardless of which event it's connected to. The framework's full path from registration to real customers is:
- Register your integration - receive
client_id+client_secret+ (if you declared webhook event types) webhook signing secret. Once. - Connect to one or more development events - typically draft events in your own org. Same endpoints, same credentials, same contract as production.
- When ready, real customers connect your integration to their events - for in-house integrations, the org owner connects on their own events; for public-catalog integrations, customers find you in the catalog and connect.
No second credential issuance, no separate "test" vs "production" pair. What changes when real customers join is the operational shape of what you're running - real customer data, real participants, real expectations. The checklist below is about that.
If your integration is intended for public catalog distribution, catalog-listing work runs alongside the operational readiness work.
Public catalog listing¶
visibility: public marks an integration as intended for distribution beyond the publishing organization.
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. - [ ] Confirm the consent-screen 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).
Suspension behavior¶
If an integration is suspended, existing tokens are revoked, new connections are blocked, and organizers may need to reconnect after reinstatement.
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).
What if you need to deprecate?¶
If you're sunsetting your integration:
- Notify your customers in advance.
- Stop new connections at the appropriate time.
- On end-of-life, unpublish the integration so tokens stop working and
data.deletion_requiredfires per(event, organization)tuple. - 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.
What changes when real customers join¶
The framework contract is identical regardless of which event you're connected to. What's different in practice once real customers connect:
- Real customer data. Encryption at rest, audit logs, access controls on your side - non-optional.
- Real participants on the receiving end. Notifications, payments, and customer-facing UX downstream of your integration are real. Mistakes have user impact.
- Real third-party endpoints. Your webhook URL is now hit by production traffic in real time; outages on your side translate to delivery retries and (after the retry curve exhausts) lost notifications.
The credentials, endpoints, signing recipe, scope semantics, retry math - none of these change. The contract you tested against is the contract you run against.