Source: https://www.revvly.ai/docs/reference/api-keys

Reference

# API key *capabilities* and limits.

What each capability on a key unlocks, which endpoints a key can reach, the default rate limits and the 429 response, and how rotation, revocation and tenant binding behave. The step-by-step setup is in [Configure an integration API key](https://www.revvly.ai/docs/guides/api-keys).

## Capabilities

A key carries a list of capabilities. Every key holds READ. The others are opt-in, and none of them stands in for another: a key with WRITE cannot mint support tokens, and a key with SUPPORT_TOKEN_MINT cannot create clients. Asking for a capability that does not exist is rejected when the key is issued.

- **READ**: Always present. Lets the key call the public GraphQL API (queries) and connect to the [MCP server](https://www.revvly.ai/docs/api/mcp) with read tools.

- **WRITE**: Public GraphQL mutations that create data: createClient, createProspect and createSubscription. Every mutation that is not named under another capability below requires WRITE, so a new mutation is write-gated by default. Over MCP, WRITE lets the key propose changes, which a person still approves in Revvly.

- **SUPPORT_TOKEN_MINT**: Revvly Support sign-in. Gates createEndUserToken and upsertSupportUsers only. It is a server-side secret: the browser only ever holds the short-lived token it mints. See [Sign users in to the support chat](https://www.revvly.ai/docs/guides/support-tokens).

- **FORM_SUBMIT**: Gates submitForm, which sends answers to a published Revvly Form from your backend. It grants no other mutation. See the [Forms API](https://www.revvly.ai/docs/api/forms).

- **KNOWLEDGE_WRITE**: Gates upsertKnowledgeArticles, deleteKnowledgeArticles and finishKnowledgeSync, which push help articles into the Support knowledge base. It grants no other mutation. See [the knowledge API guide](https://www.revvly.ai/docs/guides/support-knowledge-api).

- **PRODUCT_EVENT_WRITE**: Send product usage events (POST /api/v1/product-events) and erase one user’s events (DELETE /api/v1/product-events/users/:userId). No existing key has it. See [the Product Events API](https://www.revvly.ai/docs/api/product-events).

- **USAGE_WRITE**: Report, set, commission and correct metered usage over REST (POST /api/v1/usage, /usage/set, /usage/commission, /usage/batch) and send events (POST /api/v1/events). Reading usage only needs READ. See [Usage reporting](https://www.revvly.ai/docs/guides/usage-reporting).

- **PAYMENT_WRITE**: Record payments against invoices through the [invoice payment webhook](https://www.revvly.ai/docs/api/invoice-payments). Give it only to the key your payment processor or bank feed holds. Keys that were live on 15 October 2026 were given it so existing payment integrations keep working.

A mutation request is checked before anything runs. If it names several mutations, the key needs every capability they require. A key that lacks one is refused with FORBIDDEN (HTTP 403) and the message API key lacks required capability: <names>.

## What each surface checks

Capabilities apply to GraphQL and MCP. Over REST, writes to usage and events need USAGE_WRITE and the payment webhook needs PAYMENT_WRITE; every REST endpoint also checks the key itself, its endpoint scope and its subscription and meter scope (section 03). WRITE grants nothing over REST.

- **Public GraphQL
POST /api/v1/graphql**: Queries need READ. Mutations need the capability in section 01. Per-key rate limit applies.

- **Usage REST
/api/v1/usage***: Report and read metered usage. Authenticated by the key; endpoint scope and subscription and meter scope apply. See [Usage reporting](https://www.revvly.ai/docs/guides/usage-reporting).

- **Event ingestion
POST /api/v1/events**: Key plus an HMAC signature made with the key’s signing secret. See [Event ingestion](https://www.revvly.ai/docs/api/events).

- **Catalog read
GET /api/v1/subscriptions, /variables, /regions**: Discover subscriptions, meters and regions. See [External references](https://www.revvly.ai/docs/api/external-references).

- **Invoice payment webhook
POST /api/v1/webhooks/invoice-payment**: Push payment status into Revvly. Needs PAYMENT_WRITE and an HMAC signature. See [Invoice payment webhook](https://www.revvly.ai/docs/api/invoice-payments).

- **MCP
POST /mcp**: READ gives the read tools, WRITE adds the proposal tools. The key’s endpoint scope must be empty, or include /mcp or *. See [the tool catalogue](https://www.revvly.ai/docs/reference/mcp-tools).

The support chat endpoint (/api/v1/support/graphql) does not take API keys at all. It takes the end-user token that a SUPPORT_TOKEN_MINT key mints.

What happens to an API call

1. Key sentBearer key in the Authorization header.
2. Key checkedUnknown, revoked or expired: 401.
3. GraphQL: capabilityThe key must hold what the operation needs, else 403.orREST: scopeEndpoint, subscription and meter scope must allow it, else 403.
4. Rate limitOver the per-second or per-minute limit: 429.
5. Tenant from the keyA conflicting x-tenant-id is refused with 403.

The key decides the tenant, the checks depend on the surface, and a call over its limit is refused with 429.

## Scope

Scope narrows a key below the whole workspace. An empty list means all. The issue form in the dashboard sets the first two; endpoint scope is set through the issueApiKey mutation.

- **Subscriptions**: The subscription ids the key may act on. A request for any other subscription is refused with 403.

- **Meters**: The meter (variable) ids the key may report usage for. The issue form calls this picker Variables.

- **Endpoints**: Path rules such as /usage or /usage/set, compared without the /api/v1 prefix. * allows everything, and a trailing wildcard such as /usage/* allows everything under that path.

i

With no scope selected, the dashboard warns that the key has tenant-wide access to all subscriptions and meters. Give each integration the narrowest scope it needs.

## Rate limits

Every key has two fixed windows, counted per key: requests per second and requests per minute. The check runs after authentication, so unauthenticated traffic never uses a key’s budget.

- **Ordinary key**: 10 per second and 100 per minute, unless the issuer sets other values.

- **Key with SUPPORT_TOKEN_MINT**: 50 per second and 3,000 per minute. One such key signs in every user of your product, so a login rush has more room.

- **Ceiling on any key**: 500 per second and 30,000 per minute. Both values must be whole numbers of at least 1, and the per-minute value cannot be lower than the per-second value.

- **Changing a limit**: A tenant admin can change a live key’s limits with the updateApiKeyRateLimits mutation. The new limits apply from the key’s next request, with no rotation. Support secret keys have a limits editor in Support settings. The apiKeyUsage query reports a key’s requests and refusals over the last 24 hours.

### The 429 response

Over a limit, the request is refused before it runs. The Retry-After header carries the seconds to wait. retryAfterSeconds says the same in the body. The message names the window that was exceeded, second or minute.

REST endpoints

```
HTTP/1.1 429 Too Many Requests
Retry-After: 1

{
  "statusCode": 429,
  "message": "Rate limit exceeded (second window)",
  "retryAfterSeconds": 1
}
```

Public GraphQL

```
HTTP/1.1 429 Too Many Requests
Retry-After: 1

{
  "errors": [
    {
      "message": "Rate limit exceeded (second window)",
      "extensions": { "code": "RATE_LIMITED" }
    }
  ]
}
```

## Tenant binding

A key names its workspace. The tenant of a request is the key’s tenant, never a value you send. Do not add an x-tenant-id header to API key calls. If you do and it names a different workspace, the request is refused with 403 and the message x-tenant-id does not match the authenticated API key. A matching header is ignored. This is why a key issued for one workspace can never be aimed at another.

## Issue, rotate and revoke

Only tenant admins and owners can issue, rotate or revoke keys, or change rate limits. Go to **Settings → API Keys**.

- **Issue**: Pick a name and an access level: **Read** (the READ capability only) or **Read and write** (READ and WRITE). A **Can submit forms** checkbox adds FORM_SUBMIT and appears when Forms is on for the workspace. A **Can add knowledge articles** checkbox adds KNOWLEDGE_WRITE and appears when Support is on. Neither needs write access. Support secret keys with SUPPORT_TOKEN_MINT are issued from Support settings.

- **One-time reveal**: The key (it starts rvly_sk_live_) and its signing secret are shown once. Only a hash of the key is stored, so neither can be shown again. Lost values mean rotating the key.

- **Rotate**: Issues a successor with a new key and a new signing secret. The successor keeps the name (with "(rotated)" added), scope, capabilities and rate limits. The old key moves to Rotating and keeps working for a 30-day grace window, then stops with 401 and the message "API key rotation grace period has expired". A revoked key cannot be rotated.

- **Revoke**: Takes effect immediately. The key is refused with 401 and the message "API key has been revoked". A revoked key cannot be restored; issue a new one.

- **Status**: Active, Rotating or Revoked. The key list also shows access, scope and when the key was last used.

## Errors

- **401**: No Authorization header, not the Bearer scheme, an unknown key, a revoked key, or a rotating key past its grace window. Unknown and wrong keys get the same generic message on purpose.

- **403**: The key is outside its endpoint, subscription or meter scope, lacks a capability the operation needs, or sent a conflicting x-tenant-id.

- **429**: Over the per-second or per-minute limit. Wait the Retry-After seconds.

## Related

- [Configure an integration API key ›](https://www.revvly.ai/docs/guides/api-keys)
- [API Key ›](https://www.revvly.ai/docs/concepts/apiKey)
- [Public GraphQL API ›](https://www.revvly.ai/docs/api/graphql-public)

