> ## 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.

# API Keys

> Issue, verify, and manage API keys at any scale with Unkey. Explore key creation, verification, rotation, and access control features.

API keys are the most common way to authenticate requests to your API. Unkey handles the entire lifecycle, creating keys, verifying them on every request, tracking usage, and revoking them when needed, so you can focus on your actual API logic.

## When to use API keys

API keys work best when you need:

* **Machine-to-machine authentication**: Backend services, scripts, or integrations calling your API
* **Usage tracking per customer**: Know who's making requests and how many
* **Simple integration**: A single header (`Authorization: Bearer sk_...`) that developers understand
* **Granular control**: Per-key rate limits, expiration, and permissions

<Note>
  For user-facing authentication (login flows, sessions), you'll typically use
  OAuth, JWTs, or an auth provider like Clerk or Auth0 alongside Unkey. Unkey
  handles the API key layer, not user sessions.
</Note>

## How it works

<Steps>
  <Step title="Create a keyspace in Unkey">
    A keyspace in Unkey is a container for keys. You might have separate keyspaces for
    "Production" and "Staging", or for different products.
  </Step>

  <Step title="Issue keys to users">
    When a user signs up or requests API access, create a key for them. You can
    attach metadata (user ID, plan tier), set limits, and configure expiration.
  </Step>

  <Step title="Verify on every request">
    When a request hits your API, extract the key from the header and verify it
    with Unkey. We'll tell you if it's valid, who it belongs to, and how many
    requests they have left.
  </Step>

  <Step title="Manage the lifecycle">
    Revoke keys when users churn. Rotate keys when security requires it. Update
    limits when users upgrade. All through the dashboard or API.
  </Step>
</Steps>

## Quick example

Here's what verification looks like in practice:

<CodeGroup>
  ```ts TypeScript theme={"theme":"kanagawa-wave"}
  import { Unkey } from "@unkey/api";

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

  export async function handler(req: Request) {
    // 1. Extract the key from the Authorization header
    const key = req.headers.get("Authorization")?.replace("Bearer ", "");

    if (!key) {
      return new Response("Missing API key", { status: 401 });
    }

    try {
      // 2. Verify with Unkey
      const { meta, data } = await unkey.keys.verifyKey({ key });

      if (!data.valid) {
        // Key is invalid, expired, rate limited, or has no remaining uses
        return new Response("Unauthorized", { status: 401 });
      }
      // Continue with your API logic...
      return new Response("Hello!");
    } catch (err) {
      console.error(err);
      return new Response("Service unavailable", { status: 503 });
    }
  }
  ```

  ```python Python theme={"theme":"kanagawa-wave"}
  from unkey import Unkey

  unkey = Unkey(root_key="unkey_...")

  def handler(request):
      key = request.headers.get("Authorization", "").replace("Bearer ", "")

      if not key:
          return Response("Missing API key", status=401)

      result = unkey.keys.verify_key(key=key)

      if not result.valid:
          return Response("Unauthorized", status=401)

      # Key is valid, continue with your API logic
      return Response("Hello!")
  ```

  ```go Go theme={"theme":"kanagawa-wave"}
  package main

  import (
      "context"
      "net/http"
      "os"
      "strings"
      unkey "github.com/unkeyed/sdks/api/go/v2"
      "github.com/unkeyed/sdks/api/go/v2/components"
  )

  func handler(w http.ResponseWriter, r *http.Request) {
      auth := r.Header.Get("Authorization")
      key := strings.TrimPrefix(strings.TrimSpace(auth), "Bearer ")

      client := unkey.New(unkey.WithSecurity(os.Getenv("UNKEY_ROOT_KEY")))

      res, err := client.Keys.VerifyKey(context.Background(), components.V2KeysVerifyKeyRequestBody{
          Key: key,
      })

      if err != nil || !res.Valid {
          http.Error(w, "Unauthorized", http.StatusUnauthorized)
          return
      }

      w.Write([]byte("Hello!"))
  }
  ```

  ```bash cURL theme={"theme":"kanagawa-wave"}
  curl -X POST https://api.unkey.com/v2/keys.verifyKey \
    -H "Authorization: Bearer $UNKEY_ROOT_KEY" \
    -H "Content-Type: application/json" \
    -d '{"key": "sk_1234..."}'
  ```
</CodeGroup>

## What you get with each verification

When you verify a key, Unkey returns:

| Field         | Type        | Description                                                         |
| ------------- | ----------- | ------------------------------------------------------------------- |
| `valid`       | `boolean`   | Whether the key passed all checks                                   |
| `code`        | `string`    | Status code (`VALID`, `NOT_FOUND`, `RATE_LIMITED`, etc.)            |
| `keyId`       | `string`    | The key's unique identifier                                         |
| `name`        | `string?`   | Human-readable name of the key                                      |
| `meta`        | `object?`   | Custom metadata associated with the key                             |
| `expires`     | `number?`   | Unix timestamp (in milliseconds) when the key will expire. (if set) |
| `credits`     | `number?`   | Remaining uses (if usage limits set)                                |
| `enabled`     | `boolean`   | Whether the key is enabled                                          |
| `roles`       | `string[]?` | Permissions attached to the key                                     |
| `permissions` | `string[]?` | Permissions attached to the key                                     |
| `identity`    | `object?`   | Identity info if `externalId` was set when creating the key         |
| `ratelimits`  | `object[]?` | Rate limit states (if rate limiting configured)                     |

## Features

Unkey keys support much more than basic authentication:

<CardGroup cols={2}>
  <Card title="Rate limiting" icon="gauge-high" href="/platform/apis/features/ratelimiting/overview">
    Limit requests per key, per second, minute, hour, or any window.
  </Card>

  <Card title="Usage limits" icon="calculator" href="/platform/apis/features/remaining">
    Cap total requests per key. Perfect for API credits or trial limits.
  </Card>

  <Card title="Auto-refill" icon="arrows-rotate" href="/platform/apis/features/refill">
    Automatically restore usage limits on a schedule (daily, monthly, etc).
  </Card>

  <Card title="Expiration" icon="clock" href="/platform/apis/features/temp-keys">
    Create keys that automatically expire after a set time.
  </Card>

  <Card title="Permissions" icon="user-shield" href="/platform/apis/features/authorization/introduction">
    Attach roles and permissions for fine-grained access control.
  </Card>

  <Card title="Analytics" icon="chart-line" href="/platform/analytics/overview">
    See usage patterns, top consumers, and verification trends.
  </Card>
</CardGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart: API Keys" icon="rocket" href="/quickstart/apis/nextjs">
    Full walkthrough for Next.js, Bun, Express, or Hono.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/overview">
    All endpoints for creating, updating, and managing keys.
  </Card>
</CardGroup>
