Give each customer their own key, check and count every call with one request, and cut off anyone instantly. This works for any HTTP API, including remote MCP servers. Every endpoint below is live in test mode; the full list is in the OpenAPI spec.
Before you start, honestly: Stevens Keys is in preview. Keys, validation, metering and revocation work today. Charging customers and payouts (via Stripe Connect) are planned, not live, so for now you collect payment yourself, or just meter a free tier. New accounts are verified manually during early access (verification emails aren't sent yet).
Create an account in the dashboard, then click "Request early access verification". We approve real creators by hand. Until then you can create products but not issue keys. Meanwhile, try the whole flow with a sandbox key in the demo.
In the dashboard, create an API secret (sk_creator_test_…, shown once). Then create a product, which holds your quota and cache settings:
curl -s -X POST https://stevens-keys.pages.dev/v1/products \
-H "authorization: Bearer sk_creator_test_..." \
-H "content-type: application/json" \
-d '{"name":"My API","monthly_quota":3000,"price_cents":900}'
# → 201 { "id": "prod_...", "name": "My API", ... }
curl -s -X POST https://stevens-keys.pages.dev/v1/keys \
-H "authorization: Bearer sk_creator_test_..." \
-H "content-type: application/json" \
-d '{"product_id":"prod_...","label":"customer@example.com"}'
# → 201 { "id": "key_...", "key": "sk_mcp_test_...", ... } (plaintext shown once)
Keys are stored only as SHA-256 hashes, so you can't look the plaintext up later. Give it to your customer; they send it as Authorization: Bearer ….
Add one validate call in front of your handler. Get code for your stack from the snippet generator; the core is:
async function requireLicense(req) {
const auth = req.headers.get("authorization") || "";
if (!auth.startsWith("Bearer ")) return { allow: false, status: "missing_key" };
const res = await fetch("https://stevens-keys.pages.dev/v1/validate", {
method: "POST",
headers: { authorization: auth, "content-type": "application/json" },
body: JSON.stringify({ product_id: "prod_...", units: 1 }),
});
return res.json(); // 200 allow · 403 deny · 401 missing key
}
Each allowed call is counted against the key's monthly quota (send "meter": false for checks that shouldn't count; "units" up to 1000 for heavier calls). Over quota returns 403 over_quota.
The dashboard shows daily usage and top keys (GET /v1/usage). To cut someone off:
curl -s -X POST https://stevens-keys.pages.dev/v1/keys/key_.../revoke \
-H "authorization: Bearer sk_creator_test_..."
The next validation anywhere is denied. If you cache allows using the cache_ttl hint (30s default), it takes up to that long.
Per-call or subscription? Model it in the revenue calculator (85/15 is our planned rate; no fees are charged in preview). Background in the monetization FAQ.
Docs · Snippet generator · Calculator · OpenAPI · llms.txt