Skip to main content
Identities let you connect multiple API keys to a single entity — a user, an organization, a service account, or anything else in your system. Once connected, keys can share configuration, metadata, and rate limits.

Why use identities?

Without identities, each API key is standalone. If a user has 3 keys, you need to update each one individually. With identities:
Without IdentitiesWith Identities
Update rate limits on each key separatelyUpdate once on the identity, applies to all keys
Metadata stored per-keyShared metadata across all keys
Analytics scattered across keysAggregated analytics per identity
No concept of “this user’s total usage”Shared rate limit pool across all keys

Real-world example

Imagine you’re building a developer platform like Stripe. Each customer might have:
  • A test key for development
  • A production key for live traffic
  • Multiple restricted keys for different services
All these keys belong to the same customer. With identities:
// Create an identity for the customer
try {
  const { meta, data, error } = await unkey.identities.create({
    externalId: "customer_acme_123",  // Your internal customer ID
    meta: {
      plan: "pro",
      company: "Acme Corp"
    }
  });

  if (error) throw error;

  // All keys for this customer share the identity
  await unkey.keys.create({
    apiId: "api_xxx",
    identityId: data.id,
    name: "Production Key"
  });

  await unkey.keys.create({
    apiId: "api_xxx", 
    identityId: data.id,
    name: "Test Key"
  });
} catch (err) {
  console.error(err);
  throw err;
}
Now when you verify any of these keys, you get the identity metadata:
const { meta, data } = await unkey.keys.verify({ key: "sk_..." });

console.log(data.identity);
// { id: "id_xxx", externalId: "customer_acme_123", meta: { plan: "pro", company: "Acme Corp" } }

Use cases

Set a rate limit on the identity, and all associated keys share the same pool. If a user has 1000 requests/hour across all their keys, they can’t bypass the limit by using different keys.Learn more →
Instead of piecing together usage from individual keys, get total usage per identity. Perfect for billing dashboards and customer insights.
Store plan tier, feature flags, or custom limits on the identity. All keys inherit this configuration without needing individual updates.
Map identities to organizations in your system. When an org adds team members or creates new keys, they all share the same identity and limits.

Data model

id
string
required
Unkey’s internal identifier for this identity. Use this to reference the identity in API calls.
externalId
string
required
Your identifier for this entity. This links the Unkey identity to your system — typically a user ID, org ID, or customer ID.If you use Clerk, Auth0, WorkOS, or similar: use their user/org ID as the externalId.
// Example with Clerk
const identity = await unkey.identities.create({
  externalId: clerkUserId,  // "user_2NNEqL2nrIRdJ194ndJqAHwEfxC"
});
meta
json
Arbitrary JSON metadata. Store anything useful: plan tier, feature flags, company name, etc.
{
  "plan": "enterprise",
  "features": ["advanced-analytics", "sso"],
  "billingEmail": "[email protected]"
}

Next steps

Last modified on February 6, 2026