Skip to main content

CMS API keys

Public delivery (/v1/public/cms/...) authenticates with project-scoped API keys, not JWTs. Each key is bound to one project and grants read access to that project's published content only. Keys are minted from the Console.

Minting a key​

In the Console, open Settings → API keys → CMS and click New key.

Console Settings API keys tab with CMS API keys card, empty Keys panel, and the New API key button

You'll be prompted for:

  • Name — internal label, never shown to consumers. e.g. "marketing site", "iOS app".
  • Expiry — optional. If set, the key auto-revokes at that time. Leave blank for non-expiring (you can still revoke manually).

On creation you get a one-time view of the full key string: cmspub_a4f3b21c.... Copy it now — the Console only stores the hash, so we can't show it again. If you lose it, mint a new one and revoke the old.

Using a key​

Pass it as a bearer token:

curl https://api.sandbox.ovok.com/v1/public/cms/pages/items \
-H "Authorization: Bearer $OVOK_CMS_KEY"

See Public delivery for the full read surface.

Scope​

What a CMS API key can do:

  • Read published items via /v1/public/cms/{typeSlug}/items[/...]
  • Read media URLs / signed URLs the proxy issues for published items

What it cannot do — 401 or 403:

  • Read drafts, unpublished items, or items from other projects
  • Write, update, delete (use the Content API with a JWT)
  • Read FHIR resources or any non-CMS endpoint

Rotation​

Recommended cadence: rotate every 90 days, or immediately if you suspect compromise. The Console lets you:

  1. Mint the replacement first (overlap window).
  2. Roll out the new key to your apps.
  3. Revoke the old key from Settings → API keys → CMS.

Revocation is immediate — in-flight requests using a revoked key return 401 on the next call.

One key per surface​

We recommend a key per consumer:

ConsumerKey name
Marketing site (browser)mkt-web-prod
iOS appios-app-prod
Android appandroid-app-prod
CMS preview environmentmkt-web-preview

This keeps the blast radius of a leak small and lets you rotate one consumer without disrupting the others.

Storage​

Don't:

  • Commit keys to a public repo
  • Ship them in source maps you serve publicly
  • Log them at info / debug level

Do:

  • Use your build system's secret store (Vercel env vars, Next.js NEXT_PUBLIC_* if you intentionally expose, GitHub Actions secrets for CI)
  • Treat the key as a per-app identifier, not a high-value secret — the surface is read-only and published-only

Where they live in the API​

The CMS API key management endpoints themselves live under the internal API tag (your dashboard hits them, third parties shouldn't). The key string is created from the Console; programmatic management is not currently exposed publicly.