How to give each end user their own API key?
Make a key for each user, check it on every call, and let your customers create, rotate and revoke their own keys on your developer page. Then you always know who made a call, and one leaked key never takes everyone down.
Making a key is one line of code. Everything around it is what takes weeks. Here’s why, and the easy way to solve it.
Skip to the one-command wayManaging API keys isn’t just one line of code
Making the key is the easy bit. Around every key, you need all of this, built and kept running:
Making the key: one line
sk_live_9fQ2…
And around every key, all of this:
Unguessable, stored as a hash
So a copy of your database doesn’t hand out working keys.
Checked on every call, fast
From wherever your API runs, without slowing every request down.
Tied to a customer and a person
Otherwise you can’t tell who made a call, or whose usage it was.
Allowed only what it needs
A read-only key for dashboards, a fuller one for partners, checked on every route.
Rotated without downtime
The old key keeps working for a while, so nobody’s integration breaks mid-swap.
Switched off everywhere, fast
When a key leaks, it has to stop working on every server within minutes.
A page to manage them
Create, copy, rotate and revoke, or every new key becomes a support ticket.
A record of what it did
So after a leak you can see exactly which calls it made.
So most teams start with one shared key, until it leaks
One key for everyone is quick to set up. But when it leaks, every customer breaks at once, and you can’t tell who used the key or what they did with it.
3am, one shared key in your code
One leak. Every customer down.
- The key everyone shares is out in public
- Replacing it breaks every customer at once
- You can’t tell who used the leaked key
- Or what they did with it overnight
And no way to switch off just the leaked key.
- 03:02A key shows up in a public GitHub repo.leaked
- 03:15It’s the one key every customer shares.shared
- 03:40You replace it in your config and redeploy.redeploy
- 03:41Every customer’s integration breaks at once.outage
- 09:00Who used it, and what did they do overnight? There’s no way to tell.no record
Put keys in front of your API with one command
APIblaze runs everything around the key. Point it at your API:
Put API keys in front of your API
$ npx apiblaze@latest create --target https://ninopizzas.com/openapi.yamlPaste it in a terminal. No sign-up, no servers. The link is a sample restaurant API; swap in your own API’s address. Keys are on from the start: every call then needs one in an X-API-Key header. Your code doesn’t change.
And give your customers their own key page
One React component on your developer page, in your colours. Your signed-in customers create, see, rotate and revoke their own keys there, so a new key is never a support ticket or an email.
Developer
API access
Create a key to call the Acme API from your app or CI.
Your API keys
▲ the drop-in <ApiKeyWidget/>, white-labelled to your brand
Create a key
Named for what it’s for, of a type you allow them.
See it again
Reveal a key when they need to copy it into a new place.
Rotate it
A fresh key, with the old one working for a grace period.
Revoke it
One key off, everything else untouched.
<ApiKeyWidget />Set up in minutes: one component and one small server route. See the codeAPIblaze is an API proxy: every request passes through it first
It sits between the people using your API and your API itself. Every call shows its key to APIblaze, and only the ones with a valid key that’s allowed to do what it asks reach your code.
Callers
- Nino’s reservation appasks to view reservations
- Someone with a revoked keyasks to list reservations
- A dashboard’s read-only keyasks to cancel a reservation
APIblaze
The API proxy
Checks every call’s key: whose it is, whether it’s still active, and what its type may do.
Your API
Only sees the calls APIblaze lets through.
Never reached your code.
That’s why it’s the right place for keys. Every call has to pass it, so it can check, limit, record and switch off any single key, and your code never handles a key at all.
The same leak, a key per customer on APIblaze
One leak. One key off.
- Only the leaked key was switched off
- Its own limit capped the damage
- The log shows whose key it was and what it did
- Nino’s made a fresh key by itself
Every other customer carried on.
- 03:02A key shows up in a public GitHub repo.leaked
- 03:03You freeze that one key from your dashboard. Nothing else changes.frozen
- 03:05Its own rate limit had already capped how much it could do.capped
- 03:10The log shows whose key it was and every call made with it.on record
- 03:12You revoke it, and Nino’s Pizza makes a fresh key on your site.replaced
A key for every user, step by step
- 1
Give each customer, or each person, their own key
A key for one customer, or a key issued to one person so every call it makes counts as them. Keys can expire on their own.
$ npx apiblaze@latest apikeys mint --tenant ninos --expires-days 30$ npx apiblaze@latest apikeys mint --tenant ninos --for chiara@ninopizzas.com - 2
Decide what each kind of key may do
Define key types in your dashboard, like read-only, partner and internal, and write one rule for what each type may do. Pick a key to see which doors it opens.
View reservations
GET /reservations
Opens
Make a reservation
POST /reservations
Opens
Cancel any reservation
DELETE /reservations/{id}
Stays locked
Export reports
GET /reports
Stays locked
The rule behind it, in plain English: “read-only keys can view reservations; partner keys can also make them; internal keys can do everything.” Each key’s scopes also reach your code, signed, for any finer checks you want there.
- 3
Put the key page on your site
Create a widget key in your APIblaze dashboard (Developers → Widget key) and save it as
APIBLAZE_CP_KEY. Then add the component to your developer page, and one small route that tells it who is signed in. The browser only ever talks to your own site.app/keys/page.tsximport { ApiKeyWidget } from 'apiblaze/react'; export default function Page() { return <ApiKeyWidget theme={{ accent: '#7C3AED' }} />; } - 4
Rotate, freeze or revoke any one key
Try it on one key below and watch what a call made with it gets back.
activesk_prod_8f2Kq0LmTx_••••••••••••
Customer
Nino’s Pizza
Issued to
Chiara
Type
read-only
Environment
prod
Expires
in 87 days
Rate limit
10 a second
A read-only key for Nino’s Pizza
Issued to Chiara, so every call it makes counts as her. It can view reservations and nothing else, and it has its own rate limit.
GET /reservations · X-API-Key: sk_prod_8f2Kq0LmTx_••••
Allowed · Nino’s reservations
- 5
Call your API with a key
The key goes in an X-API-Key header. Without a valid key, APIblaze refuses the call before your code runs.
$ curl https://ninopizzas.abz.run/1.0.0/prod/reservations -H "X-API-Key: sk_prod_…"
Common questions
Put APIblaze in front of it. It gives your API a gateway that requires an API key on every call, sent in an X-API-Key header, with keys for each of your customers. Your code doesn’t change.
Prices are on the pricing page.
Give every user their own API key today
One command, no sign-up. Your code doesn’t change.
$ npx apiblaze@latest create --target https://ninopizzas.com/openapi.yaml