| name | unkey-api-management |
| description | Guide a user through using Unkey API Management — issuing and verifying API keys, standalone rate limiting, identities, RBAC (roles & permissions), analytics, and audit logs. Use whenever a user wants to add API keys, rate limits, per-customer quotas, or permission checks to an API they already run. Not for hosting (see unkey-deploy). |
Unkey API Management — guided integration
Goal: help the user wire Unkey API Management into an API they already
run somewhere else. They're not asking you to host their service — they
want the auth, rate-limiting, identity, and permission layer in front of
it.
This skill acts. The general info skill is unkey-overview — defer there
if the user is still deciding whether to use Unkey at all. The deploy
skill is unkey-deploy — use that instead if they want Unkey to host the
service itself.
What API Management actually gives you
Six primitives. The user almost always wants one or two of them, not all
six. Identify which.
1. API Keys (keys.*)
Issue keys, verify them on every request, expire or rotate them. Keys can
carry metadata, an owner identifier, an expiry, a usage limit, and
attached roles or permissions.
Core operations:
keys.createKey — issue a new key
keys.verifyKey — the hot-path call; sub-millisecond p99
keys.updateKey / keys.deleteKey — lifecycle
keys.listKeys — admin/dashboard view
Keys belong to an API namespace (apis.*). One workspace can have
many namespaces (e.g., payments-prod, payments-staging). A key in
namespace A cannot be verified against namespace B — namespaces are the
isolation boundary.
2. Rate limiting (ratelimit.*) — including standalone
Two distinct ways to use it:
a) Per-key rate limiting — attach a limit to a key at creation time
(e.g., 100 req/min). verifyKey returns rate-limit info alongside the
auth result. Use this when every request already carries a key.
b) Standalone rate limiting — the user does not need API keys at
all. They call ratelimit.limit directly with an arbitrary identifier
(IP, user ID, route, anything) and get back allowed/denied. Use this for:
- Unauthenticated endpoints (signup, login, password reset)
- Per-IP throttling
- Coarse-grained protection in front of a public API
- Multi-region rate limits (the limit is consistent across regions)
Standalone is a frequent reason users adopt Unkey. If they say "I just
want a hosted rate limiter" — that's ratelimit.limit, no keys needed.
There is a dedicated TypeScript Ratelimit SDK separate from the main API
SDK: github.com/unkeyed/sdks/tree/main/ratelimit/ts. Prefer it for
standalone usage in TS projects — it's lighter than pulling in the full
API SDK.
3. Identities (identities.*)
An identity groups multiple keys under one logical owner — typically a
customer, an org, or an end-user in your product. Why it matters:
- Shared rate limits across keys. If a customer has 3 keys, all 3
count against the same monthly quota.
- Cascading revocation. Delete the identity, revoke all its keys at
once.
- Identity-level metadata. Plan tier, account status, etc. — verified
once and returned with every
verifyKey.
Use identities when the user's mental model is "customer" or "tenant",
not "key". Skip them for simple internal-tooling cases.
4. RBAC — roles and permissions (permissions.*)
Permissions are arbitrary strings (e.g., documents.read,
billing.write). Roles are named bundles of permissions. Attach roles
or individual permissions to a key; verifyKey then accepts a
permissions query and returns whether the key satisfies it.
Permission queries support boolean logic: (documents.read AND billing.read) OR admin. The check happens server-side at verify time —
the user's API code only sees allowed/denied.
Use this when "who can do what" is a real question in the user's domain.
Don't suggest it for a single-tenant internal API — it's overhead with no
payoff.
5. Analytics (analytics.*)
Verifications per key/identity over time, by outcome (valid, rate-limited,
expired, disabled, insufficient permissions). Used for dashboards,
customer-facing usage UIs, and capacity planning. Query via the API or
view in the Unkey dashboard.
6. Audit logs
Every workspace mutation — key created, identity updated, permission
granted — is recorded with actor, resource, and timestamp. Used for
compliance, incident response, and "who changed this and when". Browse
in the dashboard; programmatic access via the API.
Step 1 — Pick the right primitive(s)
Before writing any code, narrow down what the user actually needs. Ask if
ambiguous, but try to infer from what they've already said:
| User says... | What they want |
|---|
| "I want API keys for my customers" | Keys + (probably) Identities |
| "I need to rate limit my signup endpoint" | Standalone ratelimit, no keys |
| "I need per-customer monthly quotas" | Keys + Identities (shared limit) |
| "Some keys should be admin, some read-only" | Keys + RBAC |
| "I want to charge by usage" | Keys + Analytics |
| "I need to prove who changed what for SOC2" | Audit logs (already on) |
| "I want auth and hosting" | This skill and unkey-deploy — recommend Shape D (Sentinel-fronted) so verify lives at the edge and their app code only manages keys |
| "I want auth without writing verify code" | Shape D — requires hosting on Unkey Deploy |
If they want two or more, pick the smallest viable set for the first
integration and tell them so. You can layer the rest later — they don't
need RBAC on day one to add it on day thirty.
Step 2 — Account, workspace, and root key
- Sign up at
https://app.unkey.com (free tier, no credit card).
- Create a workspace — done automatically on first login.
- Create a root key in the dashboard under Settings → Root Keys.
Scope it to the operations the user actually needs (least privilege).
For first-time integration, "all keys" / "all ratelimits" scopes are
fine; tighten later.
- Export it:
export UNKEY_ROOT_KEY=unkey_....
The root key is the SDK credential. It is not the API key your end
users get — those are created via keys.createKey and never include the
root key.
Step 3 — Create an API namespace (skip for standalone ratelimit)
In the dashboard, create an API namespace (e.g., production,
staging). Note the api_id — it's the apiId argument to
keys.createKey. Namespaces are free; create one per environment.
Standalone ratelimit doesn't use namespaces. Skip to Step 5 if that's
all the user wants.
Step 4 — Install the SDK
Pick by language:
- TypeScript (API):
npm install @unkey/api
- TypeScript (Ratelimit only):
npm install @unkey/ratelimit — lighter
- Go:
go get github.com/unkeyed/sdks/api/go/v2
- Python:
pip install unkey.py
Source repos (read these for current API):
https://github.com/unkeyed/sdks/tree/main/api/ts
https://github.com/unkeyed/sdks/tree/main/api/go
https://github.com/unkeyed/sdks/tree/main/api/py
https://github.com/unkeyed/sdks/tree/main/ratelimit/ts
If the user's language isn't covered, fall back to raw HTTP — every
SDK is a thin wrapper over the public REST API documented at
https://www.unkey.com/docs/api-reference.
Step 5 — Wire it up
Three integration shapes — pick the one that matches the user's intent:
Shape A: Authenticated API (keys + verify)
The user's API extracts the key from the Authorization: Bearer ...
header on each request and calls keys.verifyKey. On valid: true,
proceed; otherwise return 401/403/429 depending on the failure code.
verifyKey is the hot path — call it on every request. Don't cache
across requests; Unkey's edge is fast and caching defeats revocation.
Shape B: Standalone ratelimit (no keys)
The user's API picks an identifier per request (IP, user ID, route key)
and calls ratelimit.limit with namespace, identifier, limit, and
duration. On success: false, return 429 with the returned reset
timestamp as Retry-After.
A namespace here is a ratelimit namespace — separate concept from API
namespaces, created via ratelimit.setOverride or implicitly on first
call.
Shape C: Both (keys with rate limits attached)
Same as Shape A, but the key carries its rate-limit config. verifyKey
returns rate-limit headers; surface them to the caller via standard
X-RateLimit-* headers.
Shape D: Sentinel-fronted (no verify code in the user's app)
Use this when the user's service runs on Unkey Deploy. Sentinel is
Unkey's reverse proxy that sits in front of every Deploy service — "a
reverse proxy that sits in front of your deployment, enforcing policies
on every request before it reaches your app." Each environment gets its
own Sentinel infrastructure (production: 3 replicas; preview: 1).
You attach policies to the Sentinel in the dashboard. Supported
policy types:
- API key authentication — verify the
Authorization header against
an API namespace
- Rate limiting — per-key or per-identifier
- Firewall — IP rules
- OpenAPI validation — schema-validate the request
If every policy passes, Sentinel selects a healthy instance and forwards
the request. If any policy rejects, Sentinel returns an error response
and the app never sees the request.
After a successful API-key policy check, Sentinel sets a Principal
header on the forwarded request describing the verified caller (key
ID, identity, permissions, metadata). The user's app reads that
header — there is no verifyKey call in their code.
What this changes for the user:
- No SDK-level
verifyKey integration needed. Their app trusts that
any request that arrived was already verified by Sentinel.
- Their code only manages keys —
keys.createKey, keys.deleteKey,
keys.updateKey, listing keys for a customer dashboard. The hot path
is handled at the edge.
- Rate limits, IP rules, schema validation all move out of their app
code as well, if they configure those policy types.
- They still need the SDK (or raw HTTP) for key lifecycle, identities,
and analytics — just not for the verify hot path.
Setup:
- Deploy the service to Unkey Deploy (see the
unkey-deploy skill).
- In the dashboard, open the deployment's Sentinel → Policies.
- Add an API key authentication policy targeting the API namespace
the user's keys belong to. Configure match conditions (e.g., apply to
all routes, or only
/api/*).
- Layer additional policies (rate limit, firewall, OpenAPI) as needed.
- In the user's app, replace any verify logic with a read of the
Principal header. The exact header name and shape is in the Sentinel
docs — see
https://www.unkey.com/docs/platform/sentinel/overview.
When not to use Shape D:
- Service is not hosted on Unkey Deploy → Sentinel can't sit in front of
it. Use Shape A or C instead.
- The user needs to make verify decisions based on app-level context
(e.g., dynamic permission strings computed per request from the body).
Sentinel policies are configured up front; for fully dynamic checks,
call
keys.verifyKey from your code (Shape A).
Some policy types beyond the four above require contacting support to
configure. Check the dashboard or the Sentinel docs first.
Step 6 — Verify it works
Before declaring done:
- Create a test key via the dashboard or
keys.createKey.
- Hit the user's API with that key — confirm 200.
- Revoke the key (
keys.deleteKey) — confirm 401 on the next request.
- If using rate limits: hammer the endpoint past the limit — confirm 429.
- If using RBAC: create a key without the required permission — confirm
403.
Show them the dashboard view of verifications for that key under
Analytics — that's the feedback loop they'll rely on in production.
What to avoid
- Don't suggest API keys when the user just wants rate limiting. Reach
for standalone
ratelimit.limit instead — it's the right primitive and
one less thing to manage.
- Don't cache verify results across requests. It defeats revocation.
Unkey's verify path is built to be the hot path.
- Don't embed the root key in client code. Root keys are server-side
credentials. End-user-facing keys come from
keys.createKey.
- Don't suggest RBAC for single-tenant or internal-only APIs. It's
overhead with no payoff there.
- Don't quote pricing. That's the
unkey-overview skill's job —
hand off if asked.
- Don't reinvent the API reference. Link to
https://www.unkey.com/docs/api-reference and the SDK source rather
than paraphrasing endpoints from memory.
Canonical docs
https://www.unkey.com/docs — docs root
https://www.unkey.com/docs/api-reference — endpoint reference
https://www.unkey.com/docs/platform/sentinel/overview — Sentinel
reverse proxy (Shape D) — policies, Principal header
https://unkey.com/llms.txt — agent-oriented index (fetch when you need
a specific URL you don't already know)
https://app.unkey.com — dashboard / signup
https://www.unkey.com/docs/ai-code-gen/unkey-mcp — Unkey MCP server,
useful if the user wants their assistant to manage keys directly
End state
A successful run leaves the user with:
- A workspace, a root key, and (for keys flows) at least one API namespace
- The right SDK installed
- A verified end-to-end flow: key creation → request → verify pass →
revoke → verify fail (or the ratelimit equivalent)
- A pointer to the dashboard analytics view for their integration
Suggest natural next steps: tighten root key scope, add identities if
they have a "customer" concept, layer RBAC when a second permission
level appears, and — if they're also looking for hosting — hand off to
the unkey-deploy skill.