For product teams that receive customer credentials

Your customers' API keys are a liability you didn't ask for.

Every integration that asks a customer to paste an API key makes your database a place other companies' credentials live. You inherit the blast radius, the rotation support burden, and the questionnaire. SecRefs lets you accept a sec:// reference instead, and resolve it at the moment you use it.

Your integrations table today
SELECT * FROM customer_integrations
customer_id | credential
------------+----------------------------
acme_corp | sk_live_51NxAb9Kq2mZ...
globex | ghp_8Kd0sLpQm4vX1nR...
initech | xoxb-4471-9920-jHqL...

Every row is a live credential belonging to someone else. One dump and you are the subject of three other companies' incident reports.

Your integrations table with SecRefs
SELECT * FROM customer_integrations
customer_id | credential
------------+----------------------------
acme_corp | sec://acme/stripe#key
globex | sec://globex/github#token
initech | sec://initech/slack#bot

Every row is a pointer. Resolving one requires an authorization the attacker doesn't have, and the customer can revoke yours without touching anyone else's.

What you actually change

One call, at the point where you already read the credential out of your own storage. Everything downstream of that line is unchanged.

before.ts
// the key you stored at connect time
const key = integration.credential;
await stripe(key).charges.create(...);
// you are holding a live credential
// for as long as the row exists
after.ts
// the reference you stored at connect time
const key = await secRefs.expandString(
integration.credential
);
await stripe(key).charges.create(...);
// the value exists in memory, for this call

A plain value passed to expandString comes back unchanged, so you can accept both and migrate customers gradually rather than flag-day your whole integration surface.

Enrolling also means registering a public key. Responses are sealed to it with HPKE, bound to the specific reference being resolved, so a response cannot be replayed as the answer to a different one. The SDK unseals it; your code sees a string.

What it buys you

A breach leaks pointers

A dump of your integrations table is a list of references. Without the customer's authorization, a reference resolves to nothing. It is not a credential, and it cannot be replayed.

Rotation stops breaking you

Today, a customer rotating a key silently breaks their integration and opens a support ticket blaming you. A reference survives rotation - the name is stable, the value underneath it moves.

Offboarding is theirs, not yours

"Please confirm you have deleted our API key" becomes a question they answer themselves by revoking the grant. You stop being the custodian of something you never wanted to hold.

The questionnaire answer changes

"How do you store customer credentials?" is the question that stalls enterprise deals. Answering "we don't" - and being able to show it - is worth more than any control you could describe.

What it costs you

Three real tradeoffs. If we only listed the upside, your security team would find these in the first review anyway, and rightly trust the rest of the page less.

A round trip before use

Resolving at use time puts a network call in front of the customer's API call. Cacheable within a bounded window if you accept the staleness, but it is not free, and we will hold ourselves to a published latency budget rather than hand-wave it.

A dependency in your critical path

If the control plane is unreachable, resolution fails and so does your integration. That is a real operational coupling and it belongs in a contract, not a footnote.

The value passes through us

Responses are encrypted to a public key you enrol, so the plaintext never reaches a log, a load balancer, or anything else that terminates TLS. But resolving still means fetching from your customer's vault into our memory - so the honest claim is a smaller exposure window, not zero. Code execution on our resolve path would still see it.

In design - not yet shipped

We are looking for the first vendor to build this with.

The client libraries are shipped and in production use. Pass-through resolution - the part described on this page - is specified in full and deliberately unbuilt. Speculative security surface is the worst kind, so we are not writing the endpoint until a real integration is driving its shape.

If your product asks customers for API keys and you would rather it didn't, we want to design the interface against your use case: your auth model, your latency budget, your revocation story. The specification is public and unflattering about its own tradeoffs - read it before you talk to us.