# Shared Rate Limits

> Share rate limits across multiple API keys using Unkey identities. Enforce a single quota for all keys belonging to the same entity.

Identities let you enforce a **single rate limit** across all of a user's API keys. Without this, a user with 5 keys at 100 req/s each could make 500 req/s total, probably not what you want.

## The problem

Without shared limits, rate limits apply per-key:

```text
User has 3 API keys, each with 100 req/s limit
→ User can actually make 300 req/s (100 × 3 keys)
```

## The solution

Create an identity for the user, attach a rate limit to it, then link all their keys to that identity:

```text
Identity: user_123
  └── Rate limit: 100 req/s (shared pool)
      ├── Key A (production)
      ├── Key B (staging)
      └── Key C (mobile app)

→ User can only make 100 req/s total across ALL keys
```

## Step 1: Create an identity with rate limits

<CodeGroup>

```bash cURL
curl -X POST https://api.unkey.com/v2/identities.createIdentity \
  -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "user_123",
    "ratelimits": [
      {
        "name": "requests",
        "limit": 100,
        "duration": 1000
      }
    ]
  }'
```

```typescript TypeScript
import { Unkey } from "@unkey/api";

const unkey = new Unkey({ rootKey: process.env.UNKEY_ROOT_KEY });

const { meta, data } = await unkey.identities.createIdentity({
  externalId: "user_123",
  ratelimits: [
    {
      name: "requests",
      limit: 100,
      duration: 1000, // 100 requests per second
    },
  ],
});

console.log(data.identityId); // Save this
```

</CodeGroup>

## Step 2: Create keys linked to the identity

<CodeGroup>

```bash cURL
curl -X POST https://api.unkey.com/v2/keys.createKey \
  -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "apiId": "api_...",
    "externalId": "user_123",
    "name": "Production Key"
  }'
```

```typescript TypeScript
// All keys with the same externalId share the identity's rate limits
try {
  const { meta, data } = await unkey.keys.createKey({
    apiId: "api_...",
    externalId: "user_123", // Links to the identity
    name: "Production Key",
  });

  await unkey.keys.createKey({
    apiId: "api_...",
    externalId: "user_123", // Same identity
    name: "Staging Key",
  });
} catch (err) {
  console.error(err);
  throw err;
}
```

</CodeGroup>

## Step 3: Verify, limits are shared automatically

When you verify any key linked to the identity, the shared rate limit is enforced:

```typescript
const { data } = await unkey.keys.verifyKey({ key: "sk_prod_..." });

// If the identity is rate limited, data.valid will be false
if (!data.valid && data.code === "RATE_LIMITED") {
  // User exceeded 100 req/s across ALL their keys
}
```

---

## Multiple rate limits

You can set multiple limits on an identity, useful for different resource types:

```typescript
try {
  const { meta, data } = await unkey.identities.createIdentity({
    externalId: "user_123",
    ratelimits: [
      {
        name: "requests",
        limit: 500,
        duration: 3600000, // 500 requests per hour
      },
      {
        name: "tokens",
        limit: 20000,
        duration: 86400000, // 20k tokens per day
      },
    ],
  });
} catch (err) {
  console.error(err);
  throw err;
}
```

Then specify which limit to check during verification:

```typescript
// Check the "tokens" limit and consume 150 tokens
const { data } = await unkey.keys.verifyKey({
  key: "sk_...",
  ratelimits: [{ name: "tokens", cost: 150 }],
});
```

If _any_ specified limit is exceeded, verification fails.

---

## Next steps

<CardGroup cols={2}>
  <Card
    title="Quickstart"
    icon="rocket"
    href="/quickstart/identities/shared-ratelimits"
  >
    Step-by-step tutorial
  </Card>
  <Card
    title="Identities overview"
    icon="fingerprint"
    href="/platform/identities/overview"
  >
    Learn more about identities
  </Card>
</CardGroup>
