What you'll build#
An Express server with a protected /secret route that requires a valid API key. Requests without a valid key get rejected with a 401.
Time to complete: ~5 minutes
Prerequisites#
- Unkey account (free)
- Keyspace created in your Unkey dashboard
- Node.js 18+
Want to skip ahead?
Clone the complete example and run it locally.
Create your Express app#
Add your root key#
Get a root key from Settings → Root Keys and create a .env file:
.env
Warning
Never commit your
.env file. Add it to .gitignore.Create your server#
Create index.js with a protected route:
index.js
Start your server#
Test it#
First, create a test key in your Unkey dashboard, then:
Test with valid key
You should see:
Now try without a key:
Test without key
You'll get:
What's in data?#
After successful verification, data contains:
| Field | Type | Description |
|---|---|---|
valid | boolean | Whether the key passed all checks |
code | string | Status code (VALID, NOT_FOUND, RATE_LIMITED, etc.) |
keyId | string | The key's unique identifier |
name | string? | Human-readable name of the key |
meta | object? | Custom metadata associated with the key |
expires | number? | Unix timestamp (in milliseconds) when the key will expire. (if set) |
credits | number? | Remaining uses (if usage limits set) |
enabled | boolean | Whether the key is enabled |
roles | string[]? | Permissions attached to the key |
permissions | string[]? | Permissions attached to the key |
identity | object? | Identity info if externalId was set when creating the key |
ratelimits | object[]? | Rate limit states (if rate limiting configured) |
Using as middleware#
For cleaner code, extract verification into middleware:
middleware/auth.js
Then use it on any route:
Next steps#
Troubleshooting#
Getting 401 even with a valid key?
- Ensure the key hasn't expired or been revoked - Verify the
Authorizationheader format:Bearer YOUR_KEY(note the space) - Check that your root key has theverify_keypermission
Getting 500 errors?
- Check that
UNKEY_ROOT_KEYis set correctly in your.env- Make sure you're callingrequire("dotenv").config()before using env vars - Check the Unkey dashboard for any service issues
TypeScript version?
The code above uses CommonJS. For TypeScript, install types and use imports: