Authentication

Authentication

Every request requires a ppk_live_… API key in one of two headers:

X-API-Key: ppk_live_…

or

Authorization: Bearer ppk_live_…

X-API-Key is the preferred form — it’s what onboarding instructs users to copy and what Cowork’s config snippet emits. Authorization: Bearer is supported for backwards compatibility with older integrations.

How it’s enforced

All ProPresence edge functions share a single auth helper (_shared/bearer-api-key-auth.ts) that:

  1. Looks for X-API-Key first (case-insensitive).
  2. Falls back to Authorization: Bearer … if absent.
  3. Looks the key up in user_api_keys where is_active = true.
  4. Rejects if the key is missing, revoked, or past expires_at.
  5. Updates last_used_at (fire-and-forget).
  6. Returns the resolved userId to the calling function.

Scope enforcement happens after authentication, per endpoint.

CORS

The functions return the standard preflight headers and accept authorization, x-api-key, x-client-info, apikey, content-type.

Errors

Status Meaning
401 Missing, malformed, revoked, or expired key
403 Key authenticated but lacks the scope the endpoint requires

Example

curl https://<project>.supabase.co/functions/v1/articles-api \
  -H "X-API-Key: ppk_live_..." \
  -H "Content-Type: application/json"
await fetch(`${baseUrl}/articles-api`, {
  headers: { 'X-API-Key': process.env.PROPRESENCE_KEY }
});

Related: API keys, Error codes