Ship the token.Keep the key.

KeyVault Edge swaps your real API key for a token bound to the origins, endpoints, rate and spend you allow. The token is what lands in your bundle, your repo and your .env. The real key is injected at the edge, on requests that pass every check.

A stolen token still has to clear every check: origin, expiry, rate, spend. We say no.

Try to get a stolen token past the edge

Same checks, same order, same responses as the live worker.

Edge inspectorclick any underlined value
Request from your app
Origin:
X-KV-Token: kvt_7f3a…c21
Token policy (encrypted in the token)
allowed_hosts: [app.acme.com]
allowed_endpoints: [POST /v1/chat/completions]
expires_at:
rate window: req/min
month spend:

The policy block is what an attacker cannot see or change: it is sealed inside the encrypted payload. It is shown here so you can watch which rule refuses the request.

Edge checks, in order
  1. Upstream target

    X-KV-Target must be a public https origin (SSRF guard)

  2. Token signature

    HMAC-SHA-256 verify over the token body, before any decrypt

  3. Envelope decrypt

    AES-256-GCM unwraps the per-key DEK, DEK decrypts the payload

  4. Host binding

    Request origin matched against allowed_hosts (wildcards supported)

  5. Expiry

    expires_at compared against request time

  6. Endpoint scope

    Method + path matched against allowed_endpoints

  7. Rate limit

    Sliding minute/hour/day windows in a Durable Object

  8. Spend cap

    Month-to-date estimated cost against monthly_cost_cap_micros

200Forwarded to upstream

The real key was injected into the provider's auth header inside the worker. X-KV-* and CF-* headers are stripped before the request leaves.

X-KV-Edge: JNB
X-RateLimit-Remaining: 19
real key injected at the edge · never returned to the client

Rotation is a fire drill you run after the damage.

A key pushed to a public repo gets found by automated scanners. Secret scanning catches it too, and the alert is accurate. It can still be too late: by the time you rotate, the key may already have been used.

Detection tells you a secret escaped. It can't do anything about the secret itself. That gap is the whole reason this product exists, and the only thing it tries to close.

So we stopped trying to keep keys out of the places they leak, and made the thing that leaks limited and revocable instead.

The longer version, including what we got wrong →

Six places a key gets out

Client bundles
A key inlined at build time ships to every visitor who opens devtools.
Git history
Removed from HEAD, still sitting in an earlier commit, and in every fork.
CI logs
One set -x, one verbose curl, and the key is in a build log with broad read access.
Error trackers
Request headers attached to an exception and forwarded to a third party.
AI assistants
Whole files pasted into a prompt, keys included, to debug something unrelated.
Screenshots
A terminal or .env on screen during a demo, a PR review, or a support ticket.

None of these are exotic. Every one of them is a normal Tuesday on a team that is shipping, which is why “be more careful” has never worked as a control.

One boundary, and the secret only exists on one side of it.

Nothing ever hands a decrypted key back to your application, and this isn't a vault you query. Your app holds a token, the edge holds the ability to use it, and those two facts never swap places.

Your app

Holds a restricted token

kvt_7f3a…c21

This is what your app sends in X-KV-Token: a signed, encrypted envelope only the edge can open, carrying the key plus the policy that decides when it may be used.

KeyVault Edgeplaintext boundary
  1. 01

    Verify signature

    HMAC-SHA-256, before any decrypt

  2. 02

    Unwrap envelope

    AES-256-GCM: master key → DEK → payload

  3. 03

    Match origin

    allowed_hosts, wildcards supported

  4. 04

    Check expiry + scope

    expires_at, allowed_endpoints

  5. 05

    Meter budget

    rate window, then monthly spend cap

  6. 06

    Inject real key

    provider auth header, in worker memory

The real key is decrypted into worker memory for the life of one request. Any stage can refuse, and a refusal never reaches your provider, so it never costs you anything.

Upstream API

Receives an ordinary request

Authorization: Bearer sk-proj-…

OpenAI, Stripe, GitHub: whoever it is, they see the real key in their own header format. Nothing about your provider relationship changes.

Return path

The response streams straight back with X-KV-Edge and X-KV-Latency attached. Usage and cost are metered after the response is already on its way, never in front of it.

The policy travels inside the token, encrypted.

Whoever holds the token cannot read its policy or widen it. The restrictions are sealed into the payload, so the only thing an attacker learns from a stolen token is that it did not work.

ControlToken fieldBehaviour
Originallowed_hostsExact hosts, or a leading wildcard for subdomains. Checked against the request origin.
Endpointallowed_endpointsMethod + path patterns. An empty list means unrestricted.
Lifetimeexpires_atAbsolute expiry, compared at request time.
Throughputrate_limitSeparate per-minute, per-hour and per-day windows.
Spendmonthly_cost_cap_microsHard month-to-date ceiling in USD micros.

Scope is checked before the rate limit, so a request to an endpoint the token does not cover is refused without spending any of its budget.

Change the URL. Add two headers.

There is no KeyVault SDK to adopt and no wrapper around your provider's client. You send the request to the proxy with the provider's usual path, put your token in X-KV-Token and the provider's base URL in X-KV-Target.

// npm install openai  (no KeyVault SDK needed)import OpenAI from "openai"; const openai = new OpenAI({  // Placeholder: the proxy replaces the auth header with your real key.  apiKey: "via-keyvault-edge",  baseURL: "https://proxy.keyvaultedge.com/v1",  defaultHeaders: {    "X-KV-Token": process.env.KVE_TOKEN!,   // kvt_...    "X-KV-Target": "https://api.openai.com",    // Server-side only: browsers set Origin themselves.    Origin: "https://app.yourdomain.com",  },}); const res = await openai.chat.completions.create({  model: "gpt-4o-mini",  messages: [{ role: "user", content: "Hello from the edge" }],}); console.log(res.choices[0].message.content);

Compatible with your stack

Anything reachable over HTTPS with a header-based credential works, including OpenAI, Anthropic, Stripe, GitHub, AWS, Twilio, SendGrid, Supabase and Pinecone. These are APIs we proxy, not customers, partners or endorsements. Per-provider setup →

Claims worth making are claims worth checking.

A security product that asks to sit in your request path should show its work. Here is what we assert, who it comes from, and where to verify it, including the parts that are not finished.

Runs on Cloudflare's edge network

Cloudflare's footprint, not ours

The proxy is a Cloudflare Worker, so it executes in Cloudflare's points of presence. The scale of that network is Cloudflare's claim to make; ours is only that we deploy to it.

How we deploy →

Latency overhead, per region

Measured, not modelled, and not live yet

We publish p50/p95/p99 overhead per region from probes every five minutes, measured as proxy time minus a direct upstream call. The methodology is pinned. The probes are not running yet, and the table says so.

Benchmark + method →

Uptime and incidents

Our record, published either way

We sit in your request path, which makes our availability your problem too. The status page and incident history are public, including the incidents that were our fault.

Status and history →

Where we actually are

KeyVault Edge is early. We are working with a small number of engineering teams to prove the model in production, and we would rather tell you that than dress up a logo wall. There is no customer list on this page because we are not going to imply relationships we do not have.

What we can offer instead is inspectability: the architecture, the threat model, the benchmark methodology, the incident log, and a disclosure process for when you find something we missed.

The questions a security reviewer asks.

Where does the real key live, and is it encrypted at rest?

It is encrypted with AES-256-GCM under a per-token data encryption key, and that DEK is wrapped with a master key held as a Worker secret, not in our database. The encrypted key travels inside your kvt_ token and is decrypted in Worker memory when a request arrives. A database compromise alone yields ciphertext.

Who controls the encryption keys?

We hold the master key that wraps every DEK, as an encrypted Cloudflare Worker secret. Customer-managed keys (your own AWS KMS, GCP Cloud KMS or Azure Key Vault key) are on the Enterprise roadmap and not live yet. If you need to hold the keys yourself today, the self-hosted proxy runs with your own master key.

Can the edge ever hand the original secret back to my client?

No. The key is written into the upstream request's own auth header inside the worker and the response is streamed back untouched. There is no API that returns a decrypted key, and the proxy strips its own X-KV-* headers plus Cloudflare's CF-* headers before forwarding.

What happens when a check fails?

The request is refused at the edge and never reaches your provider, so a rejected request costs you nothing upstream. Signature and origin failures return 403, expiry 401, a throughput breach 429 with Retry-After, and a spend-cap hit 402. Everything except the spend cap is written to your breach log with the attempted origin, IP and geography.

Does it fail open if something breaks?

It fails closed: an unverified token simply never gets forwarded. Nothing in the code sends a request upstream without validating it first. The trade-off is honest: the proxy sits in your request path, so our availability becomes part of yours. That is the right question to ask us, and /status is where we answer it.

What are the limits of the spend cap?

Cost is metered after the response is already streaming, so the counter is eventually consistent. A burst of concurrent requests can overshoot the cap slightly before requests start failing. Streaming responses are metered from the final usage figures the provider sends (for OpenAI-compatible APIs the proxy asks for them). Treat the cap as a tight guard rail, not an accounting ledger.

Question not here? The vendor checklist covers procurement detail, and security@keyvaultedge.com reaches an engineer.

When a key leaks anyway.

Prevention fails sometimes. These help you contain the damage and recover the money afterwards.

Revoke in one click

Kill a leaked token from the dashboard and the edge refuses it on the next request. The provider key was never exposed, so there is nothing to rotate.

Incident evidence report

Download every request and blocked attempt in the abuse window, with times, IPs, origins, endpoints and estimated cost, for your provider billing dispute.

Auto-quarantine (opt-in)

When the daily anomaly scan finds a critical spike in requests or cost, or calls from a new region, the token is paused and you are alerted.

Just leaked a key? Follow the first-hour checklist.

Priced on tokens and requests.

No setup fee, and the limits below are the actual enforced numbers rather than marketing rounding. Full pricing →

Developer

$9/mo

One developer, shipping to production.

  • 10 tokens
  • 5M requests / month
  • Host allowlist per token
  • Breach log + email alerts

Starter

Most teams
$39/mo

A team with something in production.

  • 50 tokens
  • 50M requests / month
  • Host allowlist per token
  • Anomaly alerts + Slack
  • Up to 5 seats

Enterprise

Talk to us

Compliance requirements and your own KMS.

  • Unlimited tokens + requests
  • Customer-managed keys (roadmap)
  • Private deployment (BYOP) on request
  • SSO on request
  • Custom MSA + DPA

Put a key in and try to steal it back.

Protecting your first key takes about a minute: create a token, bind it to an origin, change one base URL. Then leak it to yourself on purpose and watch the breach log fill up while nothing happens upstream.