Skip to content
Image KB Reducer
Esc
↑↓navigate↵open⌘Jpreview
On this page

Authentication

Bearer keys, how they're issued, per-key rate limits, and why there's no CORS support.

Bearer keys

Every request to POST /v1/compress needs an Authorization header:

Authorization: Bearer ikb_live_…

GET /v1/health is the one route that needs no key — it’s a liveness check, and it’s meant to be pollable by anything (uptime monitors included) with no credential to manage.

A missing header, a malformed header, or a key that doesn’t match anything on file all come back as the same 401 unauthorized — this endpoint never distinguishes “you sent no key” from “you sent the wrong key” in its response, so a stranger probing for valid keys learns nothing from the difference.

How a key is issued

Keys are issued manually, out of band — there is no self-serve signup endpoint. Email privacy@imagekbreducer.com to ask for one. What gets stored against your key is exactly three fields: a name, a creation timestamp, and the key’s own SHA-256 hash — never the key itself in plaintext, and nothing about any request you make with it. See Privacy for the full accounting.

Treat a key like any other bearer credential: don’t commit it, don’t embed it in a browser bundle, and don’t put it anywhere a request’s Authorization header could be read by someone other than your own backend.

Per-key rate limit

Each key is limited to 10 requests per 60 seconds, counted per key — not globally, so one key being throttled never affects another. The counter for a key lives in its own Durable Object, keyed by that key’s hash, which is what makes “per key” structural rather than a convention: two keys cannot reach the same counter. A request over the limit gets 429 rate-limited with a Retry-After header carrying the seconds left in that key’s current window. Rate limiting happens before Content-Length checking or any parsing of the request body: a throttled key pays nothing for a request beyond the auth check itself.

The window is a fixed 60 seconds, not a sliding one, so a caller who spends their whole allowance at the end of one window and again at the start of the next can briefly exceed the nominal rate across that boundary.

If the limiter itself is unreachable, requests are refused, not waved through: you get 503 rate-limiter-unavailable with Retry-After: 60. Failing closed is deliberate — an outage in the only per-key cost control must not become an unmetered API.

Why there’s no CORS support

This API sends no Access-Control-* header on any response, on any route, ever — not even a permissive one on OPTIONS /v1/compress, which answers 204 Allow: POST and stops there. That OPTIONS response is not a CORS preflight response; there is no CORS support anywhere in this Worker for it to be a preflight response for. It’s the same status a browser preflight would see, but it carries none of what a preflight needs to actually authorize a cross-origin request, so a browser calling this API directly will always fail with a CORS error, on every browser.

This is deliberate, not an oversight: this is a server-to-server API, meant to be called from your own backend, where your key stays out of anything a page visitor’s browser can inspect. A page in a browser embedding a bearer key to call this API directly is exactly the failure mode this design refuses to make possible — see the Limits page’s framing of the whole endpoint as “refuse before spending,” of which this is one instance.

Was this page helpful?