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

# API Keys

> Create, list, and revoke Hub API keys for demand-side access to Hub endpoints

## Overview

Hub API keys allow demand-side callers — agent developers and SDK clients — to authenticate against Hub discovery endpoints. Keys are **tier-gated** with daily request limits and use the `X-Hub-API-Key` request header for event ingestion (analytics events endpoint) or `Authorization: Bearer hub_live_…` for Hub discovery endpoints (search, composites, etc.).

**Base URL:** `https://ezforge.ai`

**Authentication for management endpoints:** All create/list/revoke operations require `Authorization: Bearer <user-token>` (session token).

<Info>
  This page is the dedicated API keys reference. For the consolidated Hub API reference covering both API keys and listing analytics in one place, see [Hub API Reference](/hub/api-reference).
</Info>

***

## Security model

* **SHA-256 hashed storage.** Raw key values are never stored. Only the SHA-256 hash is persisted in the database.
* **Key shown once.** The raw key is returned **exactly once**, in the `201` response body at creation time. If you lose the key, you must revoke it and create a new one.
* **Immediate revocation.** Revoking a key sets `revokedAt` instantly. Any subsequent request using the revoked key returns `401`.
* **Prefix for identification.** The `keyPrefix` field (first 16 characters of the key) is safe to display in UIs and logs for identification without exposing the full key.

***

## Tier limits

| Tier       | Daily limit          |
| ---------- | -------------------- |
| `explorer` | 100 requests/day     |
| `builder`  | 10,000 requests/day  |
| `partner`  | 100,000 requests/day |

Rate limit counters reset at **UTC midnight**. When the limit is exceeded, the API returns `429` with `Retry-After: 86400`.

***

## Create API key

```
POST /api/v1/hub/api-keys
```

Creates a new Hub API key for the authenticated user. The raw key is returned **exactly once** — store it securely immediately after creation.

### Request body

```json theme={null}
{
  "tier": "explorer"
}
```

| Field  | Type   | Required | Description                                                            |
| ------ | ------ | -------- | ---------------------------------------------------------------------- |
| `tier` | string | —        | Key tier: `explorer`, `builder`, or `partner`. Defaults to `explorer`. |

### Response `201`

```json theme={null}
{
  "data": {
    "key": "hub_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "meta": {
      "id": "01JQXYZ0000000000000000000",
      "userId": "01JQABC0000000000000000000",
      "keyPrefix": "hub_live_xxxxxxx",
      "tier": "explorer",
      "dailyRequestCount": 0,
      "lastRequestAt": null,
      "createdAt": "2026-05-15T10:00:00.000Z",
      "revokedAt": null
    }
  }
}
```

<Warning>
  The `key` field is returned only once, at creation time. Store it securely — it cannot be retrieved again.
</Warning>

**Response fields (`meta`):**

| Field               | Type               | Description                                          |
| ------------------- | ------------------ | ---------------------------------------------------- |
| `id`                | string             | ULID key identifier. Used to revoke the key.         |
| `userId`            | string             | ULID of the owning user.                             |
| `keyPrefix`         | string             | First 16 characters of the key (safe to display).    |
| `tier`              | string             | Key tier: `explorer`, `builder`, or `partner`.       |
| `dailyRequestCount` | integer            | Requests made today (resets UTC midnight).           |
| `lastRequestAt`     | ISO 8601 or `null` | Timestamp of the most recent request using this key. |
| `createdAt`         | ISO 8601           | Key creation timestamp.                              |
| `revokedAt`         | ISO 8601 or `null` | Set when the key is revoked; `null` for active keys. |

**Error responses:**

| Status | Code                  | Condition                                                                         |
| ------ | --------------------- | --------------------------------------------------------------------------------- |
| 401    | `unauthorized`        | Missing or invalid session token.                                                 |
| 422    | `validation_error`    | `tier` is not one of `explorer`, `builder`, or `partner`.                         |
| 429    | `rate_limited`        | IP rate limit exceeded (`Retry-After` reflects seconds until window reset, ≤ 60). |
| 503    | `service_unavailable` | Rate-limit service temporarily unavailable.                                       |

***

## List API keys

```
GET /api/v1/hub/api-keys
```

Returns all active (non-revoked) Hub API keys for the authenticated user, ordered oldest-first. Returns up to 100 keys. **Raw key values are never returned.**

### Response `200`

```json theme={null}
{
  "data": [
    {
      "id": "01JQXYZ0000000000000000000",
      "userId": "01JQABC0000000000000000000",
      "keyPrefix": "hub_live_xxxxxxx",
      "tier": "builder",
      "dailyRequestCount": 42,
      "lastRequestAt": "2026-05-15T09:14:00.000Z",
      "createdAt": "2026-03-01T08:00:00.000Z",
      "revokedAt": null
    }
  ]
}
```

**Error responses:**

| Status | Code                  | Condition                                                                         |
| ------ | --------------------- | --------------------------------------------------------------------------------- |
| 401    | `unauthorized`        | Missing or invalid session token.                                                 |
| 429    | `rate_limited`        | IP rate limit exceeded (`Retry-After` reflects seconds until window reset, ≤ 60). |
| 503    | `service_unavailable` | Rate-limit service temporarily unavailable.                                       |

***

## Revoke API key

```
DELETE /api/v1/hub/api-keys/:id
```

Immediately revokes a Hub API key. Any subsequent requests using this key will receive `401`. Revocation cannot be undone — create a new key if you need to restore access.

### Path parameters

| Parameter | Type   | Description                                                                  |
| --------- | ------ | ---------------------------------------------------------------------------- |
| `id`      | string | ULID of the key to revoke (from `meta.id` at creation or the list endpoint). |

### Response `204`

No content.

**Error responses:**

| Status | Code                  | Condition                                                                         |
| ------ | --------------------- | --------------------------------------------------------------------------------- |
| 401    | `unauthorized`        | Missing or invalid session token.                                                 |
| 404    | `not_found`           | Key not found or not owned by the authenticated user.                             |
| 409    | `conflict`            | Key is already revoked.                                                           |
| 429    | `rate_limited`        | IP rate limit exceeded (`Retry-After` reflects seconds until window reset, ≤ 60). |
| 503    | `service_unavailable` | Rate-limit service temporarily unavailable.                                       |

***

## Using your API key

Once you have a key, pass it in the appropriate header depending on the endpoint:

| Header                             | Used by                                                                                   |
| ---------------------------------- | ----------------------------------------------------------------------------------------- |
| `X-Hub-API-Key: hub_live_…`        | [Analytics events ingestion](/hub/analytics-events) (`POST /api/v1/hub/analytics/events`) |
| `Authorization: Bearer hub_live_…` | Hub discovery endpoints (search, composites, etc.)                                        |

The `X-Hub-API-Key` header is intentionally separate from `Authorization` so that SDK clients sending telemetry cannot accidentally forward the key to third-party services.

***

## Deprecated endpoints

<Warning>
  **`/api/v1/hub/keys` is deprecated.** Use the `/api/v1/hub/api-keys` endpoints documented above for all new integrations. The `/api/v1/hub/keys` path will be sunset on **2028-01-01** and removed in a future release.
</Warning>

Responses from the deprecated path include the following headers to signal migration:

```
Deprecation: true
Link: </api/v1/hub/api-keys>; rel="successor-version"
Sunset: Sat, 01 Jan 2028 00:00:00 GMT
```

| Deprecated path               | Replacement                       |
| ----------------------------- | --------------------------------- |
| `POST /api/v1/hub/keys`       | `POST /api/v1/hub/api-keys`       |
| `GET /api/v1/hub/keys`        | `GET /api/v1/hub/api-keys`        |
| `DELETE /api/v1/hub/keys/:id` | `DELETE /api/v1/hub/api-keys/:id` |
