---
title: "Create Organization Api Key"
method: POST
path: "/v1/api-keys/"
tags: ["API Keys"]
---

# Create Organization Api Key

`POST /v1/api-keys/`

## Request

- Base URL: `https://logfire-api.pydantic.dev/api`
- URL: `https://logfire-api.pydantic.dev/api/v1/api-keys/`
- Auth: OAuth 2
  - Authorization code: `api/oauth/authorize`
  - Token URL: `/api/oauth/token` scopes: `organization:create_api_key`
- TypeScript: <https://skmtc.dev/pydantic/apis/pydantic-logfire-api/docs/v1/api-keys/post.ts> (a function with typed inputs; its response is checked against the schema)

Create an API key delegated from the calling credential.

The new key can never exceed the caller's own grant: its scopes, personal/service
kind, and project scope are all constrained to the caller. Creation is audit-logged
by the service layer.

Omitting `project_id` makes an organization-wide key. One may carry a project-bound
scope (`project:gateway_proxy`, `project:read_otlp`, `project:write_otlp`) only
alongside `organization:create_api_key`, and then only to pass on: it resolves no
project, so it can grant the scope to the project keys it creates but never use it.
The one exception is `project:read_otlp` beside `project:read`, which lets the key query
every readable project through the MCP server. Any other pairing is rejected with 422.

## Request body

- APIKeyCreate: Request body for creating an API key via the public API. `scopes` must be a subset of the caller's own scopes. Omitting `project_id` (or passing `null`) mints an org-wide key; giving a `project_id` scopes the key to that project. `claims` carries optional per-scope settings (today only `project:gateway_proxy`). Whether the new key is personal or a service key is derived from the caller, not chosen here.
  - `name` string, required
  - `scopes` OAuthScopeId[], required
  - `description` string, nullable
  - `claims` ScopeClaims
    - `project:gateway_proxy` GatewayProxyClaims: Settings carried by the `project:gateway_proxy` scope.
      - `spending_limit_daily` integer, nullable
      - `spending_limit_weekly` integer, nullable
      - `spending_limit_monthly` integer, nullable
      - `spending_limit_total` integer, nullable
      - `cache_enabled` boolean, nullable
  - `project_id` string, uuid, nullable
  - `expires_at` string, date-time, nullable

## Response `201`

Successful Response

- APIKeyCreateOutput: The created key plus its plaintext token (returned only once, at creation).
  - `api_key` APIKeyRead, required
    - `id` string, uuid, required
    - `organization_id` string, uuid, required
    - `name` string, required
    - `description` string, nullable, required
    - `scopes` OAuthScopeId[], required
    - `project_id` string, uuid, nullable, required
    - `project_name` string, nullable, required
    - `all_projects` boolean, required
    - `created_by` string, uuid, nullable, required
    - `created_by_name` string, nullable, required
    - `created_at` string, date-time, required
    - `last_used_at` string, date-time, nullable, required
    - `expires_at` string, date-time, nullable, required
    - `user_id` string, uuid, nullable, required
    - `active` boolean, required
    - `updated_at` string, date-time, nullable, required
    - `updated_by` string, uuid, nullable, required
    - `claims` APIKeyClaims
      - `project:gateway_proxy` GatewayKeySettings: AI Gateway spend caps and response caching for a `project:gateway_proxy` key. All fields are optional: an omitted or `null` spending limit means no limit for that window, and `cache_enabled=null` inherits the project default.
        - `spending_limit_daily` integer, nullable
        - `spending_limit_weekly` integer, nullable
        - `spending_limit_monthly` integer, nullable
        - `spending_limit_total` integer, nullable
        - `cache_enabled` boolean, nullable
  - `token` string, required

## Other responses

- `403`: Requested scopes or project scoping exceed the caller's own grant, or its owner lacks the permissions those scopes require on the target project
- `404`: Project not found. A caller whose own project authorization is checked gets the 403 above instead, which does not distinguish a project it cannot reach from one that does not exist
- `422`: Validation Error
- `429`: Rate limit exceeded

---

[API](https://skmtc.dev/pydantic/apis/pydantic-logfire-api.md) - [All operations](https://skmtc.dev/pydantic/apis/pydantic-logfire-api/llms.txt) - [OpenAPI document](https://skmtc.dev/pydantic/apis/pydantic-logfire-api/revisions/7996e45256f4?raw)
