TL;DR
Unkey is an open-source API key management platform. Create, verify, and rate-limit API keys with sub-millisecond latency — no database setup needed. Free tier: 2,500 key verifications/month.
What Is Unkey?
Unkey provides API authentication infrastructure:
- API key management — create, revoke, rotate keys
- Rate limiting — per-key or global rate limits
- Usage tracking — track API usage per key
- Temporary keys — auto-expiring keys
- Remaining uses — keys with limited usage count
- Sub-millisecond verification — globally distributed
- Free tier — 2,500 verifications/month
Quick Start
npm install @unkey/api
Create an API Key
import { Unkey } from "@unkey/api";
const unkey = new Unkey({ rootKey: "unkey_YOUR_ROOT_KEY" });
// Create a key for a user
const { result } = await unkey.keys.create({
apiId: "api_YOUR_API_ID",
prefix: "myapp",
ownerId: "user_123",
meta: { plan: "pro", email: "user@example.com" },
ratelimit: {
type: "fast",
limit: 100,
refillRate: 10,
refillInterval: 1000, // 10 requests per second
},
remaining: 10000, // 10K total uses
expires: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days
});
console.log(`Key: ${result.key}`); // myapp_abc123...
Verify a Key
// In your API middleware
const { result } = await unkey.keys.verify({
apiId: "api_YOUR_API_ID",
key: req.headers["x-api-key"],
});
if (!result.valid) {
return new Response("Unauthorized", { status: 401 });
}
// Access key metadata
console.log(result.ownerId); // "user_123"
console.log(result.meta); // { plan: "pro", ... }
console.log(result.remaining); // 9999
console.log(result.ratelimit); // { remaining: 95, reset: ... }
Express Middleware
import { verifyKey } from "@unkey/api";
const authMiddleware = async (req, res, next) => {
const key = req.headers["x-api-key"];
if (!key) return res.status(401).json({ error: "API key required" });
const { result, error } = await verifyKey({
key,
apiId: "api_YOUR_API_ID",
});
if (error || !result.valid) {
return res.status(401).json({
error: result?.code || "Invalid API key",
});
}
req.apiKey = result;
next();
};
app.get("/api/data", authMiddleware, (req, res) => {
res.json({ data: "secret stuff", plan: req.apiKey.meta.plan });
});
Rate Limiting (Standalone)
import { Ratelimit } from "@unkey/ratelimit";
const limiter = new Ratelimit({
rootKey: "unkey_YOUR_ROOT_KEY",
namespace: "api",
limit: 100,
duration: "60s",
});
// In your handler
const { success, remaining, reset } = await limiter.limit(userId);
if (!success) {
return new Response("Rate limited", {
status: 429,
headers: {
"X-RateLimit-Remaining": remaining.toString(),
"X-RateLimit-Reset": reset.toString(),
},
});
}
Unkey vs Alternatives
| Feature | Unkey | Custom (Redis) | Clerk | Auth0 |
|---|---|---|---|---|
| API keys | Yes | Manual | No | Yes |
| Rate limiting | Built-in | Manual | No | Add-on |
| Setup time | 5 min | Hours | 30 min | 30 min |
| Latency | <1ms | ~5ms | N/A | N/A |
| Key analytics | Yes | Manual | N/A | Basic |
| Free tier | 2.5K/mo | Self-host | 10K MAU | 7.5K MAU |
| Open source | Yes | N/A | No | No |
Resources
- Unkey Documentation
- GitHub Repository — 4K+ stars
- API Reference
- Dashboard
Building an API that serves scraped data? My Apify tools extract web data — protect your data API with Unkey for key management and rate limiting. Questions? Email spinov001@gmail.com
Top comments (1)
the free tier is 150k requests per month before needing to upgrade to the next tier.
Thanks for the coverage