whk_-prefixed API key you create in your dashboard. Send it in the Authorization header on every request; there is no other auth scheme, no cookies, and no session.
whoami is the fastest way to confirm a deployed key is the one you think it is — it echoes the key’s org and scopes without touching any resource.
Key format
A key iswhk_ followed by 43 random characters and a 6-character checksum — 53 characters in total. The checksum is a CRC32 over the random part: it’s error detection, not security, so a key mistyped or truncated in transit fails fast with a 401 instead of being probed against your data. The secret’s strength is the 43 random characters; treat the whole string as sensitive and never log it. At rest, keys are stored as a peppered HMAC, never in the clear — which is also why a lost key can’t be recovered, only rotated.
Construct an SDK client
The SDKs take the key at construction and attach theAuthorization header for you. They redact it from errors, debug output, and any logging, so a stack trace can’t leak your credential.
Scopes
Every key carries an explicit set of scopes, and a key should be granted only the scopes its job needs. Choosing scopes is choosing blast radius: a key scopedevents:read that leaks can read events and nothing else — it can’t create an endpoint, register a secret, or replay to a destination.
There’s one more scope you won’t find in this table:
profile. It isn’t a capability or a blast-radius scope, and you can’t mint an API key with it — it’s an identity scope granted only through OAuth consent, and it lets the MCP whoami tool return your name and email. See how authorization works.
Least privilege in practice: mint one key per consumer, scoped to what that consumer does. A CI job that only lists events gets events:read; a provisioning script that creates endpoints gets endpoints:write; a metering dashboard gets billing:read. Don’t over-provision one key and hand every service the keys to the kingdom — the point of narrow scopes is that a leak from one consumer doesn’t compromise the others.
When a scope is missing
A request whose key lacks the required scope gets403 FORBIDDEN — the key is valid, but not allowed to do this. The fix is to mint a new key with the right scope, not to widen an existing one:
403 is the API telling you the auth worked and the authorization didn’t. Contrast it with a 401 (below), which means the bearer itself is missing, invalid, or for the wrong audience. Check a key’s actual scopes any time with whoami:
wbhk whoami.
Managing keys
Create, rotate, and revoke API keys from Settings → Credentials in the dashboard. Keys are managed from the authenticated dashboard rather than minted over the API, precisely because they’re credentials — the API surface never hands out a key that could act as your org.- Shown once. A key’s secret is displayed a single time, at creation. Copy it into your secret manager then; there’s no way to reveal it again — if you lose it, rotate.
- Rotate without downtime. Create the replacement first, roll it out to your consumers, and revoke the old key once traffic has moved. Both keys are live during the overlap, so nothing drops. The full playbook, including how to shrink the blast radius before a leak, is in recovering a leaked key.
- Revocation is immediate. A revoked key stops working on the very next request — it’s the only remedy for a leak, and it takes effect at once.
Signing in from the CLI
You don’t have to paste a key into the CLI.wbhk login runs a browser-based OAuth flow (PKCE) and stores a short-lived, scoped key in your OS keychain; it refreshes silently in the background, and wbhk logout revokes it server-side.
Auth across surfaces
The samewhk_ bearer authenticates every surface — it’s one credential model, not four:
- API — the
Authorization: Bearerheader on every request toapi.webhook.co. - CLI —
wbhk loginmints and stores a short-lived scoped key for you; or setWEBHOOK_API_KEYfor a key you manage yourself. - SDKs — pass the key at construction; the client attaches it and redacts it.
- MCP —
mcp.webhook.co/mcpaccepts a bearer token in theAuthorizationheader, and there are two ways to get one: paste awhk_key, or run the interactive OAuth flow (a browser sign-in and consent at auth.webhook.co) that your client offers. Either way the same shared handler enforces scopes, just like the API. See connect from a client and how authorization works.
Environments and base URL
The default base URL ishttps://api.webhook.co. Point the SDKs at a self-host or development origin with the base-URL option — but it must be https. The one exception is a loopback address (localhost / 127.0.0.1) over http, allowed for local development only. This is a deliberate guard: a plaintext base URL would put your bearer key on the wire where a proxy could read it, so the client refuses to construct against one — you’ll get a WebhookConfigError before any request leaves the process.
Errors
Two auth failures, and they mean different things:
A
401 means fix the credential; a 403 means fix the scope. Every error also carries a requestId (also returned as the x-request-id response header) — include it in any support report. See errors and status codes for the full taxonomy and the SDKs’ typed errors.
Security best practices
- Server-side only. Never expose a
whk_key to a browser, mobile app, or anything a user can read. - One key per consumer. Separate keys per service or environment so you can revoke one without disrupting the rest.
- Narrow scopes. Grant only what the consumer needs; a
readjob never needs awritekey. - Out of source. Load keys from environment variables or a secret manager — never commit them.
- Rotate on a schedule, revoke on a leak. Rotation is zero-downtime; revocation is immediate. When in doubt, revoke — see recovering a leaked key.