> ## Documentation Index
> Fetch the complete documentation index at: https://unkey.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 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 theme={"theme":"kanagawa-wave"}
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 theme={"theme":"kanagawa-wave"}
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 theme={"theme":"kanagawa-wave"}
  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 theme={"theme":"kanagawa-wave"}
  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 theme={"theme":"kanagawa-wave"}
  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 theme={"theme":"kanagawa-wave"}
  // 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 theme={"theme":"kanagawa-wave"}
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 theme={"theme":"kanagawa-wave"}
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 theme={"theme":"kanagawa-wave"}
// 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>
