Docs

API keys, members, webhooks & usage

AdminUpdated Sep 15, 2026

API keys, members, webhooks & usage

Org-administration endpoints: invite/manage members, issue/list API keys, subscribe to webhooks, and read usage. All require an API key (see authentication); the org is always derived from the key you authenticate with — no route in this section accepts an orgId parameter, so a key can only ever act on its own org.

Note: these are admin-only surfaces. A scoped API key (one issued with an explicit scopes list) can never call /v1/members, /v1/keys, or /v1/webhooks — every request gets 403 { "error": "insufficient_scope", "message": "this key may not use admin endpoints; manage them in the dashboard" } regardless of which scopes it holds. Only a legacy, unscoped key (scopes: null — the default for keys issued before scoped keys existed, and for keys issued via POST /v1/keys itself) can reach this section. Manage scoped keys' permissions from the dashboard instead.

Members

List members

GET /v1/members
curl -H "Authorization: Bearer $COOKIEMUNCH_API_KEY" \
  https://api.cookiemunch.net/v1/members
[
  { "userId": "usr_1", "email": "owner@example.com", "role": "owner" },
  { "userId": "usr_2", "email": "teammate@example.com", "role": "admin" }
]

Invite a member

POST /v1/members

Field

Type

Required

Description

email

string

yes

Email of the person to invite.

role

admin | member | viewer

yes

Role to assign. owner cannot be granted via the API.

curl -X POST https://api.cookiemunch.net/v1/members \
  -H "Authorization: Bearer $COOKIEMUNCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "teammate@example.com", "role": "admin" }'

Response 201: { "member": { "userId": "usr_2", "email": "teammate@example.com", "role": "admin" } }. 409 if the email is already a member.

Note: inviting a member grants durable human access — that person keeps access to the dashboard independently of the API key that invited them. Treat members:write-capable keys with the same care as an admin password.

Change a member's role

PATCH /v1/members/{userId}

Field

Type

Required

Description

role

admin | member | viewer

yes

New role.

curl -X PATCH https://api.cookiemunch.net/v1/members/usr_2 \
  -H "Authorization: Bearer $COOKIEMUNCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "role": "viewer" }'

400 { "error": "the owner's role cannot be changed" } if userId is the org owner.

Remove a member

DELETE /v1/members/{userId}
curl -X DELETE https://api.cookiemunch.net/v1/members/usr_2 \
  -H "Authorization: Bearer $COOKIEMUNCH_API_KEY"

400 if userId is the owner, or if they're the org's last remaining member. Otherwise 200 { "ok": true }.

SDK equivalent

await client.members.list();
await client.members.invite('teammate@example.com', 'admin');
await client.members.setRole('usr_2', 'viewer');
await client.members.remove('usr_2');

API keys

List key prefixes

GET /v1/keys

Returns display metadata only — the secret is never retrievable after issuance.

curl -H "Authorization: Bearer $COOKIEMUNCH_API_KEY" \
  https://api.cookiemunch.net/v1/keys
[{ "prefix": "fck_a1b2c3d4", "createdAt": 1730332800000 }]

501 { "error": "key listing not configured" } on a self-host without key metadata storage wired.

Issue a new key

POST /v1/keys

Takes no body. The key is returned once — store it immediately; it can't be recovered later, only revoked and replaced.

curl -X POST https://api.cookiemunch.net/v1/keys \
  -H "Authorization: Bearer $COOKIEMUNCH_API_KEY"
{ "key": "fck_9e8d7c6b5a4f3e2d1c0b", "prefix": "fck_9e8d7c6b" }

Note: keys issued this way are unscoped (full access), because this route is itself admin-only and reachable only by unscoped keys. Create scoped, least-privilege keys from the dashboard's API Keys settings page.

SDK equivalent

await client.keys.list();
const { key, prefix } = await client.keys.issue();

Usage

GET /v1/usage

Current resource usage / quota summary for the org (plan-relative).

curl -H "Authorization: Bearer $COOKIEMUNCH_API_KEY" \
  https://api.cookiemunch.net/v1/usage
{ "domains": 4, "seats": 3, "monthlyEvents": 128430 }

501 { "error": "usage reporting not configured" } on a self-host without usage tracking wired. Unlike members/keys/webhooks, usage needs no scope — any valid key (scoped or not) can read it.

SDK equivalent

const usage = await client.usage();

Webhooks

Full event catalogue, payload shape, and signature verification are covered in Webhooks & events. This section is the CRUD reference.

List subscriptions

GET /v1/webhooks

The signing secret is omitted from list responses.

curl -H "Authorization: Bearer $COOKIEMUNCH_API_KEY" \
  https://api.cookiemunch.net/v1/webhooks
[
  {
    "id": "whk_1",
    "orgId": "org_9f01",
    "url": "https://example.com/hooks/cookiemunch",
    "events": ["consent.recorded", "dsar.created"],
    "cbid": null,
    "active": true,
    "createdAt": 1730332800000
  }
]

Create a subscription

POST /v1/webhooks

Field

Type

Required

Description

url

string

yes

HTTPS endpoint to deliver events to.

events

string[]

yes

Non-empty list from the event catalogue.

cbid

string

no

Scope delivery to a single site. Omit for all sites in the org.

curl -X POST https://api.cookiemunch.net/v1/webhooks \
  -H "Authorization: Bearer $COOKIEMUNCH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/hooks/cookiemunch", "events": ["consent.recorded", "dsar.created"] }'

Response 201 includes the signing secret once:

{
  "id": "whk_1",
  "orgId": "org_9f01",
  "url": "https://example.com/hooks/cookiemunch",
  "secret": "whsec_3f9a...",
  "events": ["consent.recorded", "dsar.created"],
  "cbid": null,
  "active": true,
  "createdAt": 1730332800000
}

Delete a subscription

DELETE /v1/webhooks/{id}
curl -X DELETE https://api.cookiemunch.net/v1/webhooks/whk_1 \
  -H "Authorization: Bearer $COOKIEMUNCH_API_KEY"

204 No Content on success.

SDK equivalent

await client.webhooks.list();
await client.webhooks.create({ url, events, cbid });
await client.webhooks.delete('whk_1');
Was this page helpful?
API keys, members, webhooks & usage