X-Unkey-Principal request header, as JSON. Your code reads this one header instead of calling Unkey. If the header is missing, no key was verified for that request.
What’s in the header
string
required
Format version, currently
v1. It only changes if a field is removed, renamed, or changes type. New optional fields can appear without a version change, so ignore fields you don’t know.string
required
Who’s calling. For a key linked to an identity, it’s the identity’s
externalId, so all keys of one identity share it. Otherwise it’s the key ID.string
required
How the caller authenticated. Always
API_KEY today. Treat any other value as unknown.object
The identity the key is linked to. Left out when the key has none.
externalId is the ID you assigned, and meta is the identity’s metadata ({} when empty).object
required
The verified key.
keyIdandkeySpaceId: always present.name: left out when the key has no name.expiresAt: Unix milliseconds, left out when the key doesn’t expire. Always in the future, because expired keys are rejected.credits: credits left after this request. Left out for unlimited keys, so0means this request used the last one.meta: the key’s metadata ({}when empty).rolesandpermissions: the key’s roles and permissions, left out when empty. The policy’s permission query has already passed, so use these for finer checks in your app.
Read it in your app
Parse the header as JSON, and expect optional fields to be missing.Why you can trust it
The header isn’t signed, but callers can’t fake it. The gateway removes anyX-Unkey-* header a client sends, and only then sets X-Unkey-Principal. Compute deployments can only be reached through the gateway, so inside your app the header is always real. If you run the same code somewhere else, for example during local development, anyone who can reach it can send a fake header.
If several API key policies match a request, the first one that succeeds sets the principal.
You can rate limit by the principal: authenticatedSubject counts by subject, and principalField counts by a field such as source.key.meta.org_id. Only string values work. See Rate limit policy.
Next steps
Local development with the gateway
Send the header yourself while developing.
API key authentication policy
The policy that produces the principal.