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.
Every row is a live credential belonging to someone else. One dump and you are the subject of three other companies' incident reports.
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.
One call, at the point where you already read the credential out of your own storage. Everything downstream of that line is unchanged.
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.
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.
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.
"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.
"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.
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.
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.
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.
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.
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.