Skip to main content
Outcome: each plan is a small object in your code, a key carries its plan’s limits, credits, permissions, and a meta.plan label, and upgrading a customer is one keys.updateKey call that takes effect within about ten seconds.
You need a root key with the permissions listed on this page. Create one in the dashboard under Settings > Root Keys, and pass it as Authorization: Bearer <root key>. See Permission reference for every permission.

Define the tiers

Define each plan once and build every key from it. Rate limits cap how often, credits cap how much, permissions unlock features, and meta returns the plan name on every verification so your handlers don’t need a database lookup.
src/plans.ts
You don’t have to create these permissions first. keys.createKey creates any that don’t exist. keys.setPermissions does too, but only if the root key has rbac.*.create_permission; otherwise it returns 403. Don’t use * in slugs, because it isn’t a wildcard.

Create a key for a plan

src/keys.ts

Read the plan during verification

Gate features with a permissions query so Unkey makes the decision. Use meta.plan only for softer choices, such as page size.
src/handler.ts

Change a customer’s plan

keys.updateKey changes a key in place. Fields you leave out keep their value, ratelimits replaces the whole list, and credits: null removes the cap and any refill. Use keys.setPermissions for permissions. It replaces the key’s permissions, so a downgrade removes what the higher plan granted.
Changes take about 10 seconds to reach verification. Credit changes apply right away. If a customer has several keys, put the plan’s rate limits on their identity so all keys share one limit, as shown in Per-user rate limits.
Last modified on September 29, 2026