API keys & scopes

Creating a key, narrowing what it can do, and the two rules that decide whether a request is allowed.

5 min read

On this page

Settings → API Keys. Keys are prefixed evnt_ and are shown once, at creation. There is no way to recover one afterwards — store it wherever you keep secrets, then close the dialog.

What a key is bound to

A key belongs to one organization and is bound to it. It is not a user credential and does not inherit anything from the person who created it.

Two independent things decide whether a request goes through:

  1. The key’s role — what its organization permits it to do at all. See Roles & permissions; keys can also take the Viewer role, which people cannot.
  2. The key’s scopes — what this particular key is narrowed to.

Both must allow the call. Narrowing scopes does not widen a role, and a permissive role does not bypass scopes.

Scopes

A key with no scopes is unrestricted, which is the default and is deliberate. Existing production keys were minted before scopes were enforced, and defaulting them to deny would have broken working integrations overnight.

That means narrowing is opt-in. If you want a restricted key, say so at creation: the Access field in the Create key dialog offers read-only, or per-resource read or read & write. Scopes cannot be changed after a key is created, so to narrow an existing key, create a scoped replacement and revoke the old one.

Scope strings take two forms:

  • read or write — that action across everything.
  • <resource>:read or <resource>:write — that action on one resource.

write implies read on the same resource. GET, HEAD and OPTIONS count as reads; everything else is a write.

The resources are the API’s top-level paths: reviews, products, orders, loyalty, faqs, galleries, customers, imports, analytics, evidence, events, email, email-sequences, email-branding, email-suppressions, sending-domain, review-incentives, outbound-webhooks, webhooks, placements, web-pages, categories, connectors, features, uploads, storefront, account, orgs, billing, api-keys, backups, affiliates, partner, support.

Examples

GoalScopes
A read-only reporting keyread
Push catalogue and orders from a headless storefrontproducts:write, orders:write
Let a tool moderate reviews and nothing elsereviews:write
Read reviews and loyalty for a dashboardreviews:read, loyalty:read

One exemption

GET /account/stores is always allowed, regardless of scopes. Without it a narrowly scoped key could not discover the store environment it is scoped for, and would be locked out of everything including the resources it does hold.

Naming the store

Every request needs the store environment it applies to:

Authorization: Bearer evnt_...
x-store-env-id: YOUR_STORE_ENV_ID

x-api-key: evnt_... is accepted in place of the Authorization header, for tools that can only set a custom header. Prefer Authorization: Bearer where you have the choice; both are supported and neither is deprecated.

Evident refuses queries that do not name a tenant. A missing x-store-env-id is a failure, not a wildcard — there is no “all stores” mode.

Rate limits

Limits are applied per caller, on three windows at once:

WindowGlobal
1 second10 requests
10 seconds50 requests
1 minute200 requests

Each key gets its own budget once it has authenticated at least once. Storefront write endpoints — review submission, gallery uploads, helpful votes — have much tighter per-visitor limits; see API conventions. Batch endpoints exist precisely so you do not have to fight these — PUT /products and PUT /orders take up to 250 items per call. Use them rather than looping.

Rotating and revoking

Revocation is immediate. There is no grace period and no soft-delete, so rotate by creating the new key, deploying it, then revoking the old one.

A key can also carry an expiry date, set when you create it. After that moment it stops authenticating — requests get a 401, exactly as if it had been revoked, with no grace period. The key list shows it as Expired. Nothing warns you beforehand, so put the date in your own calendar. An expiry a year out is a good default for anything long-lived; a day or a week is right for a one-off script.

Key creation, revocation and first use are all recorded in the security audit log. A key created months ago and used for the first time today is worth a question.

Keeping keys safe

  • Never put an evnt_ key in browser code. It carries organization-wide authority. Storefront widgets deliberately do not use one — they authenticate by origin instead.
  • One key per integration, so you can revoke one without taking down the others, and so the audit log tells you which system did what.
  • Scope it, and give it an expiry. Those two, plus one key per integration, are what limit the damage if a key leaks.
  • Scope every new key. The unrestricted default exists for backwards compatibility, not as a recommendation.

Something missing or out of date? Email support@evidentugc.com — docs corrections go straight to the team that builds the feature.