Revvly
Docs
Guide

Configure an integration API key.

Issue the least-privileged credentials your worker needs, store them once, and rotate without interrupting ingestion or payment callbacks.

Give this prompt to an integration agent

You are helping an operator configure a Revvly integration API key with the least privilege their worker needs.

Working agreement before you implement:
- Do not write production code until you have enough concrete context from the operator.
- Ask clarifying questions first — prefer one short round of questions over guessing.
- Confirm at least: source system / trigger, field mapping, where the API key and any signing secret will be stored, the target environment (local, staging, or production), and the Revvly tenantId when it is not already provided below.
- Once those answers are in place, implement the full integration against the contract below end-to-end.
- Open or fetch the Full guide URL if you need examples or edge-case detail beyond this prompt.
- Never invent API keys, signing secrets, region ids, subscription ids, or other tenant data.
- Never put secrets in browser code, logs, client bundles, or source control.

Tenant context
- The operator has not supplied a tenantId in this prompt. Ask for the Revvly tenant id before making tenant-scoped assumptions.

Platform rules that apply to every Revvly API call:
- Auth is a Bearer API key issued in the dashboard under Settings → API Keys. Tokens are prefixed `rvly_sk_live_`.
- Rate limits are per API key and default to 10 requests/second and 100 requests/minute. Overage is HTTP 429 with a `Retry-After` header in seconds (public GraphQL reports `errors[].extensions.code = RATE_LIMITED`). Honour Retry-After and back off — never retry a 429 in a tight loop.
- A key can be scoped to specific subscriptions and meters. List reads are filtered to that scope; reading or writing a single out-of-scope resource is 403 (`FORBIDDEN`), not an empty result.
- Every call is tenant-scoped by the key itself. There is no tenant parameter to switch — a different tenant means a different key.
- The token and the signing secret are server-side credentials: no browser code, no client bundles, no logs, no source control.

Full guide: https://www.revvly.ai/docs/guides/api-keys

Goal
Issue or rotate credentials correctly, store them once in a server-side secret manager, and choose the right auth model for each Revvly endpoint family.

Where keys are managed
- Dashboard: Settings → API Keys
- The issue dialog sets: a name, an Access level (Read, or Read & write), and optional subscription / meter scope.
- On issue and on rotation, the Bearer token and the signing secret plaintext are shown only once — store them immediately.
- Never return either secret to browsers, logs, CI output, or source control.

Auth models by endpoint family
- Public GraphQL (POST https://api.revvly.ai/api/v1/graphql): Bearer token. Mutations such as createClient, createSubscription, and createProspect need WRITE.
- Usage REST (https://api.revvly.ai/api/v1/usage*): Bearer token + Idempotency-Key on mutations. No request HMAC.
- Discovery REST (GET https://api.revvly.ai/api/v1/subscriptions, /variables, /regions, and the usage GETs): Bearer token only.
- Event ingestion (POST https://api.revvly.ai/api/v1/events): Bearer token AND HMAC-SHA256 of the raw body with the signing secret. The eventId is the idempotency key; there is no Idempotency-Key header.
- Invoice payment webhook (POST https://api.revvly.ai/api/v1/webhooks/invoice-payment): Bearer token, raw-body HMAC with the signing secret, and a stable Idempotency-Key.

Capabilities and scope (current product behavior)
- Capabilities are deliberately coarse: READ is always present, WRITE is the opt-in that public GraphQL mutations require. Choose "Read & write" at issue time when the worker mutates; there are no per-resource capabilities.
- WRITE is enforced on any mutation at the endpoint level, so a read-only key fails every mutation with FORBIDDEN regardless of which one it calls.
- Subscription and meter (variable) scope can be narrowed at issue time; leave both empty for tenant-wide access. Scope filters list reads and blocks single-resource reads/writes outside it — including the GraphQL client's subscriptions / invoices / paymentSummary, so a scoped key reports partial receivables.
- Endpoint scope exists on the key but is NOT exposed in the dashboard issue dialog: a key issued there is unrestricted by endpoint. Narrowing it means issuing through the internal issueApiKey mutation with scope.endpoints (paths with the /api/v1 prefix stripped, e.g. ["/usage", "/usage/*"]).
- Rate limits default to 10 requests/second and 100/minute per key (support secret keys: 50/second and 3,000/minute). A tenant admin can change them, up to 500/second and 30,000/minute, through the internal updateApiKeyRateLimits mutation or, for support secret keys, Settings → Support → Secret keys → Limits. Plan for 429 + Retry-After in the worker regardless.

Rotation
1. Rotate in the dashboard. This mints a NEW token and a NEW signing secret, and the old pair keeps working for a 30-day grace window.
2. Store both new values, then deploy them to the worker.
3. Retire the old values once the worker is fully on the new pair — you do not have to swap atomically, the grace window is the overlap.
4. Revocation is immediate and ignores the grace window — revoke only after the worker is off the key.
5. A key issued before signing secrets existed has none; the HMAC endpoints answer 401 "API key has no signing secret. Rotate to provision one." Rotation is the fix.

Implementation checklist
1. Confirm which endpoint family the worker calls (GraphQL, usage, discovery, events, payment webhook, or a mix).
2. Confirm whether WRITE is required — if it is, the key must be issued as "Read & write".
3. Confirm whether subscription/meter scope should be narrowed, and that narrowing will not starve a reporting read the same key performs.
4. Confirm the secret manager and rotation runbook the operator uses.
5. Document which secret is used for Bearer vs HMAC so they are not swapped.

Choose the correct authentication model

Public GraphQL
POST https://api.revvly.ai/api/v1/graphql
Bearer key. Queries need READ. Mutations need WRITE, except createEndUserToken and upsertSupportUsers (SUPPORT_TOKEN_MINT), submitForm (FORM_SUBMIT) and the knowledge mutations (KNOWLEDGE_WRITE), where WRITE is neither needed nor sufficient.
Usage REST
https://api.revvly.ai/api/v1/usage*
Bearer key plus Idempotency-Key for mutations; no request HMAC. READ and WRITE are not checked here; the key, its endpoint scope and its subscription and meter scope are.
Event ingestion
POST https://api.revvly.ai/api/v1/events
Bearer key and HMAC-SHA256 of the raw body with the signing secret.
Invoice payment webhook
POST https://api.revvly.ai/api/v1/webhooks/invoice-payment
Bearer key, raw-body HMAC, and a stable Idempotency-Key.

Scope and rotate safely

Restrict a key to the subscriptions, meters, and endpoints its worker actually needs. During rotation, deploy the new token and signing secret to the worker before removing the old values. Keep credentials in a server-side secret manager and redact them from observability output.

Every key is limited per key to 10 requests per second and 100 per minute unless the issuer sets other values. A refused request returns 429 with a Retry-After header. Capabilities, limits and the 429 body are listed in the API key reference.

Related