A valid request URL is required to generate request examples{
"customer_id": "9b2f0f6e-1a52-4c8e-9d3a-1f2e3d4c5b6a",
"key_id": "5d1c2b3a-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"name": "Production",
"environment": "live"
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Resolve a customer-issued key
Answers which of your customers is behind a uk_ck_… string a caller presented to your surface. The key travels in the body as data, never in the Authorization header: it is a credential of your product, not of this API, and your own uk_sk_ is what authenticates the question.
The answer is scoped to your key’s environment, resolved from its stored row — a live key cannot verify a test customer’s key, and that refusal is indistinguishable from the key not existing. One 404 covers everything that does not resolve: malformed, unknown, revoked, or the other environment. Every one of them means “no customer of yours is behind this string”, and your next line is the same either way.
A revocation takes effect on the next verify, so if you cache these answers, keep the window short — or subscribe to the customer_api_key.revoked webhook, which exists for exactly that cache.
A valid request URL is required to generate request examples{
"customer_id": "9b2f0f6e-1a52-4c8e-9d3a-1f2e3d4c5b6a",
"key_id": "5d1c2b3a-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
"name": "Production",
"environment": "live"
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Authorizations
An organization API key, uk_sk_live_… or uk_sk_test_…. The environment is resolved from the stored key row on every request, never from a request parameter.
Every route behind this credential is rate limited per key — 1000 requests a minute — with a second ceiling of 3000 a minute across all the keys of one environment, so splitting your traffic across keys isolates it and minting more keys does not buy more of it. A test key can never spend a live key's allowance. Every response carries the current state in headers; see the rate-limits guide.
Headers
A key you choose — a UUID, or your own identifier for the operation — that makes this write safe to retry. Send the same key again and you get the same response back: the same status, the same body, and Idempotent-Replay: true. The handler does not run a second time.
The key is scoped to your API key and the route, so keys never collide between environments or tenants. It is remembered for 24 hours. Reusing it for a different request is refused (422), and a second request arriving while the first is still running is refused too (409) — retry that one in a moment.
A request that failed with a 5xx or was rate limited leaves the key spendable: retry it with the same key.
255Body
The uk_ck_… string a caller presented.
Response
The key names one of your customers.
The customer the key acts for.
The key row — what POST /v1/usage stamps on the ledger line when the spend arrives as customer_key.
What the customer named the key.
Your key's environment — the one the answer was resolved in.
live, test