diff --git a/docs/talos/CLAUDE.md b/docs/talos/CLAUDE.md
new file mode 100644
index 000000000..5d6fd8846
--- /dev/null
+++ b/docs/talos/CLAUDE.md
@@ -0,0 +1,115 @@
+# Documentation Instructions
+
+## JSON Processing
+
+Use `jq` instead of `python3` for all JSON operations in code examples:
+
+- **Pretty-print:** `| jq .` not `| python3 -m json.tool`
+- **Extract required fields:** `| jq -er '.field'` (the `-e` flag exits non-zero on `null` so `set -e` aborts the snippet instead
+ of silently exporting an empty value).
+- **Extract optional fields:** `| jq -r '.field'` is fine when the field may legitimately be missing.
+
+**Never write curl output to temporary files.** Capture responses in shell variables instead. File-based operations fail when
+`/tmp` doesn't exist or isn't writable.
+
+## Passing state between doctest blocks
+
+Doctest runs each code block in a fresh `bash -eu -o pipefail` subprocess and auto-captures the exported environment after each
+successful block. To make a value available to the next block, just `export` it — no manual write to `$DOCTEST_ENV_FILE` is
+needed.
+
+```bash
+# Good: variable-based, exported for the next block, asserts the field is present
+RESPONSE=$(curl -s -X POST "$URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{"name": "my-key"}')
+echo "$RESPONSE" | jq .
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.key_id')
+
+# Bad: file-based
+curl -s ... -o /tmp/response.json
+jq . /tmp/response.json
+KEY_ID=$(jq -r '.key_id' /tmp/response.json)
+rm -f /tmp/response.json
+
+# Bad: redirecting to $DOCTEST_ENV_FILE (legacy; auto-capture handles this now)
+KEY_ID=$(echo "$RESPONSE" | jq -r '.key_id')
+echo "export KEY_ID=$KEY_ID" >> "$DOCTEST_ENV_FILE"
+```
+
+## API Field Documentation
+
+Integration guides under `integrate/` must NOT duplicate API field tables, error code tables, or enum tables. These are maintained
+in the canonical references:
+
+- **Field tables** -> auto-generated API reference at `reference/api/*.api.mdx`
+- **Error codes** -> `reference/error-codes.md`
+
+### What belongs in integration guides
+
+- **Workflow and examples**: curl commands, step-by-step instructions, the "how" and "why"
+- **Brief inline mentions**: 1-3 sentences highlighting the most important fields (e.g., "The response includes a `secret` field
+ -- store it securely")
+- **Conceptual comparisons**: tables comparing patterns, trade-offs, or usage scenarios (e.g., JWT vs macaroon)
+- **Operational constraints**: limits, cache control headers, retry strategies
+- **Links to reference**: always link to the canonical source for complete field/error details
+
+### What does NOT belong in integration guides
+
+- Full request/response field tables (use API reference link instead)
+- Error code enum tables (use error codes reference link instead)
+- Query parameter tables (use API reference link instead)
+- Revocation reason enum tables (use API reference link instead)
+
+### Link format
+
+**All links MUST be relative links to markdown/mdx files with the file extension.** Never use absolute links (starting with `/`)
+or links without a file extension. Hashbang anchors are allowed after the file extension.
+
+- Links to `.md` files: `[text](../reference/error-codes.md#section)`
+- Links to `.api.mdx` files: `[text](../reference/api/admin-issue-api-key.api.mdx)`
+- Links to directory index pages: `[text](../operate/cache/index.md)` (never `../operate/cache/`)
+- Links within the same directory: `[text](./sibling-page.md)`
+
+```text
+# Good: relative links with file extensions
+For the complete field reference, see the [IssueAPIKey API reference](../reference/api/admin-issue-api-key.api.mdx).
+For the full list of error codes, see the [error codes reference](../reference/error-codes.md#verification-error-codes).
+
+# Bad: absolute links without file extensions
+For the complete field reference, see the [IssueAPIKey API reference](/reference/api/admin-issue-api-key).
+For the full list of error codes, see the [error codes reference](/reference/error-codes#verification-error-codes).
+```
+
+### API reference URL pattern
+
+API reference pages are `.api.mdx` files at `reference/api/{plane}-{method}.api.mdx` where:
+
+- `{plane}` is `admin` or `data`
+- `{method}` is the kebab-case method name (e.g., `issue-api-key`, `verify-api-key`)
+
+The API overview page is `reference/api/ory-talos-api.info.mdx`.
+
+### Notes and callouts
+
+Ensure that notes / callouts have two line breaks, or they will get formatted incorrectly.
+
+**Incorrect:**
+
+```md
+:::note Internal package The Go client is in an `internal/` package and cannot be imported by external Go modules. :::
+```
+
+```md
+:::note Internal package The Go client is in an `internal/` package and cannot be imported by external Go modules. :::
+```
+
+Correct:
+
+```md
+:::note
+
+Internal package The Go client is in an `internal/` package and cannot be imported by external Go modules.
+
+:::
+```
diff --git a/docs/talos/concepts/architecture.md b/docs/talos/concepts/architecture.md
new file mode 100644
index 000000000..35ace68a1
--- /dev/null
+++ b/docs/talos/concepts/architecture.md
@@ -0,0 +1,213 @@
+---
+title: Architecture
+---
+
+# Architecture
+
+Talos separates API key management into two planes.
+
+## Admin plane
+
+The admin plane handles all key management and verification operations: key issuance, rotation, revocation, token derivation,
+JWKS, and verification (single and batch). It is exposed only to internal services and clients with admin credentials.
+
+Endpoints: `/v2alpha1/admin/`, including `/v2alpha1/admin/apiKeys:verify` and `/v2alpha1/admin/apiKeys:batchVerify`.
+
+For low-latency verification close to clients, deploy the commercial [edge proxy](../operate/deploy/edge-proxy.md) as a sidecar.
+The proxy caches admin verify responses locally, so applications get sub-millisecond cache hits without exposing the admin plane
+publicly.
+
+## Data plane
+
+The data plane handles self-service operations that credential holders perform with proof of possession of the credential itself,
+no admin authentication required.
+
+Endpoints: `POST /v2alpha1/apiKeys:selfRevoke`
+
+## Verification flow
+
+```
+Client --> Verifier --> Cache (hit?) --> Database --> Response
+ | ^
+ +-- cache hit ---------------+
+```
+
+1. Client sends credential to `POST /v2alpha1/admin/apiKeys:verify`
+2. Talos identifies the credential type (generated, imported, JWT, macaroon)
+3. For generated keys, the UUID is extracted from the token identifier
+4. For imported keys, a tenant-scoped SHA-512/256 hash is computed
+5. Database lookup (or cache hit) returns key metadata
+6. Response includes key status, owner, scopes, and metadata
+
+## Deployment topologies
+
+| Topology | Edition | Description |
+| ------------ | ---------- | -------------------------------------------------------------------- |
+| Single-node | OSS | One process serves both planes |
+| Split planes | Commercial | Admin and data planes as separate deployments |
+| Edge proxy | Commercial | Sidecar proxy at the edge that caches admin verify responses locally |
+
+Both planes share the same database. Verification uses caching (memory or Redis) to minimize database load.
+
+## Ports
+
+| Port | Purpose |
+| ---- | ------------------ |
+| 4420 | HTTP API (default) |
+| 4422 | Prometheus metrics |
+
+## Design philosophy
+
+### Separation of concerns
+
+The system is divided into distinct layers:
+
+- **Admin plane**: Management operations (CRUD for keys, rotation, import, token derivation)
+- **Data plane**: High-throughput verification operations
+- **Persistence layer**: Database abstraction with pluggable drivers
+- **Cache layer**: Performance optimization with multiple backends
+
+This separation allows independent scaling of components, different SLOs for different operations (admin targets \<100ms p99, data
+plane targets \<3ms p99), and clear boundaries between responsibilities.
+
+### Production-first design
+
+- Hard isolation between admin and data operations
+- Metrics, traces, and structured logs are emitted by default
+- Graceful degradation when the database or cache backend is unavailable
+- Zero-downtime deployments via rolling updates and stateless verification
+
+### Performance characteristics
+
+- Self-contained tokens (JWT/macaroon) enable stateless verification
+- HMAC-SHA256 keeps the revocation check on the order of microseconds; bcrypt would cap a single core at roughly 10 verifications
+ per second
+- LRU caching for hot paths
+- Minimal allocations in the verification path
+
+## System architecture
+
+```
+Clients (CLI, SDK, HTTP)
+ |
+ v
++----------------------------------+
+| HTTP Server (grpc-gateway) |
+| Port: 4420 |
++----------------------------------+
+ |
+ v
++----------------------------------+
+| Middleware |
+| Logging, Metrics, Tracing |
++----------------------------------+
+ |
+ +-----+----------+
+ | |
+ v v
++-----------+ +-----------+
+| Admin | | Data |
+| Plane | | Plane |
+| <100ms | | <3ms p99 |
++-----------+ +-----------+
+ | |
+ v v
++----------------------------------+
+| Service Layer |
+| Business logic, Validation |
++----------------------------------+
+ |
+ +-----+----------+
+ | |
+ v v
++-----------+ +-----------+
+| Persist. | | Cache |
+| SQLite | | Memory |
+| PG/MySQL | | LRU |
+| CRDB | | Redis |
++-----------+ +-----------+
+```
+
+All requests enter through a single HTTP server built on grpc-gateway (port 4420) and pass through middleware for logging,
+metrics, and tracing before being routed to the appropriate plane.
+
+## Component overview
+
+### HTTP server
+
+The API layer uses grpc-gateway for HTTP/JSON routing with protobuf-based schemas. It serves both planes through a single port,
+handles CORS and compression, and exposes OpenAPI documentation.
+
+### Service layer
+
+Business logic is split between the admin plane service (key lifecycle, import, token derivation, input validation) and the data
+plane verifier (token parsing, signature verification, revocation checking, cache management). The verifier is optimized for the
+hot path with minimal allocations.
+
+### Persistence
+
+Database access uses sqlc-generated type-safe queries with pluggable drivers:
+
+- **SQLite** -- OSS edition, zero-config, suitable for millions of keys
+- **PostgreSQL** -- production workloads
+- **MySQL** -- production workloads
+- **CockroachDB** -- distributed deployments
+
+Schema changes are managed through versioned migrations using golang-migrate.
+
+### Cache
+
+The cache layer reduces database load on the verification path:
+
+- **Memory LRU** (OSS) -- local to each instance, configurable size limits
+- **Redis** (Commercial) -- distributed, supports cluster and sentinel modes
+- **Hierarchical L1+L2** (Commercial) -- memory for speed, Redis for shared state
+
+### Crypto
+
+Talos supports multiple JWT signing algorithms and a separate API key hashing mechanism:
+
+- **JWT signing algorithms**
+- `Ed25519 (EdDSA)` -- default, fastest signing and smallest keys
+- `RSA-2048/4096 (RS256)` -- legacy compatibility
+- **API key hashing**
+- `HMAC-SHA256` -- used for API key revocation checks (\<1ms with constant-time comparison)
+
+The JWT signing algorithm is determined per JWK by its `alg` field, so one JWKS can contain keys for multiple signing algorithms
+at the same time.
+
+### Observability
+
+Built-in instrumentation across three pillars:
+
+- **Metrics** -- Prometheus exposition on port 4422 with request latency histograms and error rate counters
+- **Tracing** -- OpenTelemetry with W3C Trace Context propagation, configurable sampling, OTLP and Jaeger exporters
+- **Logging** -- structured JSON logging via slog with correlation IDs and contextual fields
+
+## Scalability
+
+### Small (\<1k RPS)
+
+A single Talos instance handles both planes with SQLite and an in-memory LRU cache. No external dependencies required.
+
+- OSS edition sufficient
+- 1 CPU, 512MB RAM
+- Cost: $5-10/month
+
+### Medium (10-50k RPS)
+
+Separate admin and data plane deployments behind a load balancer. PostgreSQL replaces SQLite for durability. Redis provides shared
+caching across data plane instances.
+
+- Commercial edition
+- Auto-scaling for data plane
+- Cost: $100-500/month
+
+### Large (200k+ RPS)
+
+A cluster of 10-50+ stateless data plane instances with auto-scaling, backed by a distributed Redis cache and PostgreSQL with read
+replicas and connection pooling. Supports multi-region deployment.
+
+- Commercial edition
+- Regional data plane deployment
+- Cost: $1-5k/month
diff --git a/docs/talos/concepts/caching.md b/docs/talos/concepts/caching.md
new file mode 100644
index 000000000..8fb4f9e16
--- /dev/null
+++ b/docs/talos/concepts/caching.md
@@ -0,0 +1,53 @@
+---
+title: Caching and consistency
+---
+
+# Caching and consistency
+
+Talos caches verification results to reduce database load and improve latency. The OSS edition ships a no-op cache; in-memory and
+Redis backends are commercial-only — see [Caching](../operate/cache/index.md) for backend selection.
+
+## How it works
+
+When caching is enabled, the first verification request for a key hits the database. Subsequent requests within the cache TTL are
+served from cache without a database lookup.
+
+## Cache types
+
+| Type | Scope | Use case |
+| ------ | ----------- | ----------------------------------- |
+| Memory | Per-process | Single node or per-instance caching |
+| Redis | Shared | Multi-instance deployments |
+
+## Eventual consistency
+
+Caching introduces eventual consistency for revocation:
+
+1. Admin revokes a key via `POST /v2alpha1/admin/apiKeys/{key_id}:revoke`
+2. The revocation takes effect in the database immediately
+3. Cached verification results for that key remain valid until the cache entry expires
+4. After TTL expiry, the next verification hits the database and returns `is_active: false`
+
+## Cache bypass
+
+To force a database lookup (bypassing cache), include the `Cache-Control: no-cache` header:
+
+```bash
+curl -X POST http://localhost:4420/v2alpha1/admin/apiKeys:verify \
+ -H "Content-Type: application/json" \
+ -H "Cache-Control: no-cache" \
+ -d '{"credential": "..."}'
+```
+
+See the [quickstart revocation check](../quickstart/index.mdx) and the [curl SDK reference](../integrate/sdk/curl.md) for tested
+examples using cache bypass.
+
+## TTL guidelines
+
+| TTL | Trade-off |
+| ----- | ------------------------------------------------- |
+| `1m` | Fast revocation propagation, higher database load |
+| `5m` | Balanced (recommended default) |
+| `30m` | Low database load, slower revocation propagation |
+
+See [Cache operations guide](../operate/cache/index.md) for configuration details.
diff --git a/docs/talos/concepts/credential-types.md b/docs/talos/concepts/credential-types.md
new file mode 100644
index 000000000..38e45d880
--- /dev/null
+++ b/docs/talos/concepts/credential-types.md
@@ -0,0 +1,38 @@
+---
+title: Credential types
+---
+
+# Credential types
+
+Talos manages four credential types.
+
+## Issued API keys
+
+Generated by Talos with the format `prefix_v1_identifier_checksum`. Long-lived with configurable TTL. The key ID (UUID) is
+embedded in the token for direct database lookup. The full secret is returned once at creation.
+
+**Lifecycle**: Issue, rotate, update metadata, revoke.
+
+## Imported API keys
+
+External credentials (Stripe, GitHub, etc.) stored by hash. Any string format accepted. Talos stores
+`SHA-512/256(network_id + 0x00 + raw_key)` and never the raw key. Supports the same metadata and scopes as issued keys.
+
+**Lifecycle**: Import, update metadata, revoke, delete.
+
+## Derived JWTs
+
+Short-lived tokens derived from a parent API key. The signing algorithm is determined by the `alg` field in the JWK (EdDSA or
+RS256). Can be verified independently using the JWKS endpoint (`GET /v2alpha1/admin/derivedKeys/jwks.json`). Claims include
+`key_id`, `actor_id`, scopes, and expiration.
+
+## Derived macaroons
+
+Short-lived tokens with HMAC binding. Format: `prefix_v1_base64data`. Support scope restriction and contextual attenuation.
+
+## Credential routing
+
+When a credential is submitted to `/v2alpha1/admin/apiKeys:verify`, Talos identifies the type automatically by its format and
+routes it to the appropriate verification handler. See the
+[credential routing table](../reference/token-format.md#credential-routing) for the full format-to-type mapping and lookup
+methods.
diff --git a/docs/talos/concepts/index.md b/docs/talos/concepts/index.md
new file mode 100644
index 000000000..6ae6bef95
--- /dev/null
+++ b/docs/talos/concepts/index.md
@@ -0,0 +1,16 @@
+---
+title: Concepts
+---
+
+# Concepts
+
+Core ideas behind Ory Talos.
+
+- [Architecture](architecture.md) — admin plane and data plane separation
+- [Credential types](credential-types.md) — generated keys, imported keys, JWTs, macaroons
+- [Token format](token-format.md) — v1 key format specification
+- [Security model](security-model.md) — cryptographic primitives and tenant isolation
+- [Caching and consistency](caching.md) — verification caching and revocation propagation
+- [Token derivation security](token-derivation-security.md) — stateless verification and revocation semantics
+- [Rate limiting](rate-limiting.md) — rate limit metadata on API keys
+- [IP restrictions](ip-restrictions.md) — CIDR-based access control for API keys
diff --git a/docs/talos/concepts/ip-restrictions.md b/docs/talos/concepts/ip-restrictions.md
new file mode 100644
index 000000000..aa67aaf7b
--- /dev/null
+++ b/docs/talos/concepts/ip-restrictions.md
@@ -0,0 +1,87 @@
+---
+title: IP restrictions
+description: CIDR-based allowlists that restrict which client IPs can use an API key
+---
+
+# IP restrictions
+
+Talos supports per-key IP restrictions that limit which client IP addresses can use an API key. Restrictions are defined as a list
+of CIDR ranges (for example, `192.168.1.0/24` or `2001:db8::/32`). Only requests originating from an IP within the allowlist are
+accepted. Keys without IP restrictions accept traffic from any address.
+
+## How IP restrictions work
+
+IP restriction enforcement has two stages: **IP resolution** and **CIDR matching**.
+
+### IP resolution
+
+When a verification request arrives, Talos captures all IP-related headers from the HTTP request into context through middleware.
+At verification time, the configured **client IP source** determines which header to use for extracting the client address. The
+available sources are:
+
+| Source | Header / value used | Typical use case |
+| ------------------ | ---------------------------- | -------------------------------------- |
+| `REMOTE_ADDR` | TCP remote address | Direct connections without a proxy |
+| `CF_CONNECTING_IP` | `Cf-Connecting-Ip` | Behind Cloudflare |
+| `X_FORWARDED_FOR` | `X-Forwarded-For` (leftmost) | Behind a standard reverse proxy |
+| `X_REAL_IP` | `X-Real-Ip` | Behind NGINX with `proxy_set_header` |
+| `TRUE_CLIENT_IP` | `True-Client-Ip` | Behind Akamai or Cloudflare Enterprise |
+
+If the selected header is empty, Talos falls back to the TCP remote address. The client IP source is set once at startup and
+applies to all verification requests.
+
+### CIDR matching
+
+After resolving the client IP, Talos parses the key's allowed CIDR list and checks whether the IP falls within any of the ranges.
+Both IPv4 and IPv6 CIDR notation are supported (for example, `10.0.0.0/8` and `fd00::/8`). A single IP can be expressed as a `/32`
+(IPv4) or `/128` (IPv6) range.
+
+If the IP matches at least one CIDR range, verification proceeds. If no range matches, verification fails with error code
+`VERIFICATION_ERROR_IP_NOT_ALLOWED`.
+
+## Fail-closed behavior
+
+IP restrictions use a **fail-closed** design. If Talos cannot determine the client IP -- for example, because the request context
+does not contain IP metadata -- the verification request is denied. This prevents accidental access when header forwarding is
+misconfigured.
+
+This is the opposite of [rate limiting](rate-limiting.md), which fails open to avoid blocking legitimate traffic during limiter
+outages.
+
+## Cache interaction
+
+Cached verification results still contain the key's allowed CIDR list. When a cached key is returned, Talos re-evaluates the IP
+restriction against the **current request's** client IP before returning a success response. This means IP restrictions are
+enforced on every request, regardless of whether the result came from cache or the database.
+
+The enforcement sequence is:
+
+1. Resolve the key from cache or database.
+2. Validate key status and expiration.
+3. Resolve the client IP from the current request context.
+4. Check the client IP against the key's allowed CIDR list.
+5. Return the verification result.
+
+## IPv4 and IPv6 support
+
+IP restrictions support both address families. You can mix IPv4 and IPv6 CIDR ranges in the same allowlist. Talos parses client
+addresses using Go's `net.ParseIP`, which handles both formats transparently. There is no implicit mapping between IPv4 and IPv6
+-- a `10.0.0.0/8` range does not match the IPv4-mapped IPv6 address `::ffff:10.0.0.1`.
+
+## Key concepts
+
+- **Allowlist model** -- IP restrictions define which IPs are permitted. Any IP not in the list is denied. Keys without
+ restrictions accept all IPs.
+- **Per-key granularity** -- each key has its own CIDR list. Keys do not share IP restrictions.
+- **Fail-closed** -- if the client IP cannot be resolved, the request is denied. Misconfigured proxies cannot bypass restrictions.
+- **CIDR notation** -- ranges use standard CIDR format (`ip/prefix_length`). Single IPs use `/32` (IPv4) or `/128` (IPv6).
+- **`VERIFICATION_ERROR_IP_NOT_ALLOWED`** -- the error code returned when a request IP is outside the key's allowed ranges. See
+ the [error codes reference](../reference/error-codes.md#verification-error-codes) for the full list.
+- **Cache-safe** -- IP restrictions are enforced on every verification request, even when the key is served from cache.
+
+## Next steps
+
+- [Security model](security-model.md) -- cryptographic primitives and tenant isolation
+- [Configuration reference](../reference/config.mdx) -- client IP source and related settings
+- [Error codes reference](../reference/error-codes.md#verification-error-codes) -- verification error codes including
+ `VERIFICATION_ERROR_IP_NOT_ALLOWED`
diff --git a/docs/talos/concepts/rate-limiting.md b/docs/talos/concepts/rate-limiting.md
new file mode 100644
index 000000000..f81f4018e
--- /dev/null
+++ b/docs/talos/concepts/rate-limiting.md
@@ -0,0 +1,99 @@
+---
+title: Rate limiting
+description: Per-key rate limit policies with metadata-only (OSS) or server-side enforcement (Commercial)
+---
+
+# Rate limiting
+
+Talos supports per-key rate limit policies that control how many requests a key can make within a time window. A rate limit policy
+consists of two fields: a **quota** (maximum request count) and a **window** (time period in seconds). Keys without a policy are
+never rate limited.
+
+How enforcement works depends on your edition.
+
+## OSS edition: metadata and headers
+
+In the OSS edition, Talos stores rate limit policies on keys and returns them in verification responses. It does not enforce
+limits itself. Your API gateway or reverse proxy reads the policy from the response headers and applies enforcement externally.
+
+This keeps Talos stateless while letting you use purpose-built rate limiting infrastructure (Envoy, NGINX, Kong, or a dedicated
+service). Verification responses include IETF-format headers that gateways can consume directly:
+
+- **`RateLimit-Policy`** -- declares the key's quota and window (e.g., `"default";q=100;w=60`).
+- **`RateLimit`** -- reports remaining quota (e.g., `"default";r=42`).
+
+## Commercial edition: server-side enforcement
+
+The commercial edition enforces rate limits inside Talos. When a key exceeds its quota, the verification response returns
+`is_active: false` with error code `VERIFICATION_ERROR_RATE_LIMITED`. The HTTP status remains **200** because the verification
+endpoint always returns a structured response — the rate limit status is conveyed through the response body, not the HTTP status
+code. This design allows gateways to distinguish transport errors from application-level rate limiting decisions.
+
+### Backends
+
+The commercial edition supports two enforcement backends:
+
+| Backend | Algorithm | Scope | Persistence |
+| -------- | --------- | -------------------------------- | ----------------- |
+| `memory` | GCRA | Single process (not shared) | Lost on restart |
+| `redis` | GCRA | Shared across all connected pods | Survives restarts |
+
+Both backends use the GCRA (Generic Cell Rate Algorithm), which provides smooth, sliding-window rate limiting without the
+boundary-burst problem of fixed-window counters. GCRA tracks a single timestamp per key and allows requests as long as the average
+rate stays within the configured quota.
+
+**Memory** is suited for single-node deployments or development. Each process maintains independent counters per key, so state is
+not shared across pods.
+
+**Redis** uses an atomic Lua script to maintain GCRA state shared across all pods connected to the same Redis instance. State
+survives process restarts as long as Redis is available.
+
+### Configuration
+
+```yaml
+rate_limit:
+ enabled: true # Hot-reloadable: toggle per-request without restart
+ backend: memory # Requires restart: changes the backend type
+```
+
+- **`rate_limit.enabled`** is checked on every verification request through the config provider. You can toggle it at runtime by
+ editing the config file -- Talos picks up the change automatically.
+- **`rate_limit.backend`** selects the enforcement backend (`memory` or `redis`). Changing this value requires a restart because
+ it initializes different infrastructure (in-memory maps vs. Redis connections).
+
+## HTTP response headers
+
+When a key has a rate limit policy, verification responses include IETF draft-compliant headers regardless of edition:
+
+| Header | Description | Example |
+| ------------------ | --------------------------------------------------- | ---------------------- |
+| `RateLimit-Policy` | Declares the policy: quota and window | `"default";q=100;w=60` |
+| `RateLimit` | Reports remaining quota | `"default";r=42` |
+| `Retry-After` | Seconds to wait before retrying (only when limited) | `18` |
+
+Gateways and clients can use these headers for both external enforcement (OSS) and client-side backoff (Commercial).
+
+## Fail-open behavior
+
+If the rate limiter encounters an error (for example, Redis is temporarily unavailable), Talos **fails open**: verification
+succeeds but rate limit metadata is omitted from the response. This design prevents limiter outages from blocking legitimate
+traffic.
+
+## Key concepts
+
+- **Per-key isolation** -- each key has its own counter. Keys do not share rate limit budgets.
+- **Policy fields** -- `quota` (integer, maximum requests) and `window` (duration string, e.g. `"60s"`). Both must be set for
+ enforcement to apply.
+- **No policy = no limit** -- keys without a `rate_limit_policy` field are never subject to rate limiting.
+- **`VERIFICATION_ERROR_RATE_LIMITED`** -- the error code returned when a key exceeds its quota (Commercial only). See the
+ [error codes reference](../reference/error-codes.md#verification-error-codes) for the full list.
+- **Cache interaction** -- rate limit checks happen after cache resolution. A cached verification result that is still valid will
+ be returned without consulting the rate limiter.
+
+## Next steps
+
+- [Rate limiting integration guide](../integrate/rate-limiting.mdx) -- attach policies, verify rate-limited keys, and handle quota
+ exhaustion
+- [Configuration reference](../reference/config.mdx) -- all `rate_limit.*` settings
+- [Error codes reference](../reference/error-codes.md#verification-error-codes) -- verification error codes including
+ `VERIFICATION_ERROR_RATE_LIMITED`
diff --git a/docs/talos/concepts/security-model.md b/docs/talos/concepts/security-model.md
new file mode 100644
index 000000000..b3cda1d9b
--- /dev/null
+++ b/docs/talos/concepts/security-model.md
@@ -0,0 +1,149 @@
+---
+title: Security model
+---
+
+# Security model
+
+## Cryptographic primitives
+
+| Purpose | Algorithm | Keyed by |
+| ---------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------- |
+| API key checksum | HMAC-SHA256 (full 32-byte digest, base58-encoded) | `secrets.hmac.current` |
+| Imported key hashing | SHA-512/256 over `nid \|\| 0x00 \|\| raw_key` | Tenant `nid` (no shared secret) |
+| Macaroon root-key derivation | HMAC-SHA256 with domain `"talos/macaroon/v1/root-key"` | `secrets.hmac.current` |
+| Macaroon caveat binding | HMAC-SHA256 (libmacaroons V2) | Derived macaroon root key |
+| JWT signing | EdDSA (Ed25519) or RS256, determined by JWK `alg` | JWKS at `credentials.derived_tokens.jwt.jwks.urls` |
+| Pagination-token encryption | NaCl secretbox (XSalsa20-Poly1305) keyed by SHA-256(secret) | `secrets.pagination.current` (falls back to `secrets.default.current`) |
+
+`secrets.hmac.current` is shared between the API key checksum and the macaroon root key. Rotating it rotates both at once;
+verification falls back through `secrets.hmac.retired` for both purposes. Pagination secrets are completely independent from
+`secrets.hmac.*`. See [Secret management](../operate/secrets.md).
+
+## JWT signing key selection
+
+The data plane resolves the active signing key on every derive request:
+
+1. If `credentials.derived_tokens.jwt.signing_key_id` is set, Talos selects the JWK with the matching `kid`. If no JWK in the
+ configured JWKS has that `kid`, signing fails with `InternalError` and `signing_key_id` is included in the error details.
+2. Otherwise, Talos prefers the first key with `"use": "sig"`.
+3. Otherwise, Talos returns the first key in the JWKS.
+
+Set `signing_key_id` explicitly in production so rotation becomes a config change rather than a JWKS-ordering side effect.
+Multi-tenant deployments resolve the JWKS per tenant via the contextualizer; the `kid` hint is also per-tenant.
+
+## Secret rotation
+
+Talos supports zero-downtime secret rotation. Configure the new secret as `current` and move the old one to `retired`. During
+verification, all secrets in the same family are tried in order.
+
+- **HMAC rotation** (`secrets.hmac.*`) rotates both the API key checksum and the macaroon root key. Existing API keys and
+ macaroons remain valid as long as the previous secret is in `retired`.
+- **Pagination rotation** (`secrets.pagination.*` or `secrets.default.*`) only affects `next_page_token` values. Outstanding
+ tokens decode for as long as the previous secret stays in `retired`.
+
+The two families are independent. Rotate them on independent schedules.
+
+## Tenant isolation
+
+Multi-tenant deployments use Network IDs (NID) for data isolation:
+
+- **Database**: Composite primary keys `(nid, key_id)` prevent cross-tenant access
+- **Token claims**: NID is embedded in derived tokens and validated during verification
+- **Imported key hashing**: NID is included in the hash salt, so the same raw key produces different hashes per tenant
+
+## Cache security
+
+Cache keys use SHA-256 hashes of API credentials. Raw credentials never appear in cache keys, Redis keys, or memory cache entries.
+This prevents credential leakage through cache inspection, Redis `MONITOR` commands, or memory dumps.
+
+- **Cache key format:** `namespace:nid:sha256(credential)` -- deterministic, no plaintext
+- **Reverse index:** Stores `key_id → sha256(credential)` for invalidation lookups -- no raw secrets
+- **Cached values:** Contain only non-sensitive metadata (status, scopes, owner, expiration)
+
+## Admin/data plane separation
+
+The admin plane (key management) and data plane (verification) can be deployed separately. The admin plane should be restricted to
+internal networks. The data plane can be exposed publicly.
+
+## Key lifecycle
+
+Keys transition through defined states: `ACTIVE` -> `REVOKED` or `EXPIRED`. Revocation is irreversible. Expired keys are rejected
+during verification.
+
+## Why HMAC over bcrypt
+
+Password hashing algorithms like bcrypt are designed for **low-entropy** inputs (human-chosen passwords with ~40-60 bits of
+entropy). They use intentional slowness (~100ms per hash) to make brute-force attacks against weak passwords expensive.
+
+API keys are fundamentally different. They are **cryptographically random** with 128+ bits of entropy, making dictionary attacks
+impossible. The key space of 2^128 (~3.4 × 10^38) renders brute force infeasible regardless of hashing speed.
+
+HMAC-SHA256 is a **keyed** hash function. The HMAC secret is stored in a vault, never in the database. A database breach alone is
+insufficient to verify candidate keys -- the attacker must also compromise the secret. This provides a stronger security boundary
+than bcrypt, which stores everything needed for verification in the database itself.
+
+### Performance comparison
+
+| Metric | bcrypt | HMAC-SHA256 |
+| ----------------------- | ------------ | ---------------- |
+| Single verification | ~100ms | \<1ms |
+| Throughput (per core) | ~10 ops/sec | >100,000 ops/sec |
+| 1,000 verifications | ~100 seconds | \<1 second |
+| 10,000 req/sec capacity | ~1,000 cores | 1 core |
+
+This yields a roughly **1,000x cost reduction** in compute for verification workloads.
+
+### Attack model
+
+**Database breach:** The attacker obtains HMAC hashes but not the HMAC secret (stored in vault). Without the secret, they cannot
+verify any candidate key against the stored hashes.
+
+**Brute force with secret:** Even if the attacker obtains the HMAC secret, the 2^128 key space makes exhaustive search
+computationally infeasible with current or foreseeable technology.
+
+## Why Ed25519 for token signing
+
+Talos uses Ed25519 (EdDSA over Curve25519) as the default signing algorithm for derived JWTs.
+
+| Property | Ed25519 | RSA-2048 |
+| ------------------ | --------------- | -------------- |
+| Signing speed | ~40,000 ops/sec | ~4,000 ops/sec |
+| Verification speed | ~15,000 ops/sec | ~7,500 ops/sec |
+| Signature size | 64 bytes | 256 bytes |
+| Security level | 128 bits | 112 bits |
+
+Ed25519 is **deterministic** -- it does not require a random nonce, eliminating an entire class of implementation vulnerabilities
+(unlike ECDSA P-256, where a weak nonce leaks the private key). It is also constant-time by design, providing immunity to timing
+side-channel attacks.
+
+RSA-2048 (RS256) is supported for **legacy compatibility** when integrating with systems that do not support EdDSA. The signing
+algorithm is determined by the `alg` field in the JWK configuration.
+
+## Security requirements
+
+For the cryptographic model to hold, the following operational requirements must be met:
+
+1. **HMAC secret management** -- The HMAC secret must be stored in a secrets manager or vault (e.g., HashiCorp Vault, AWS Secrets
+ Manager). It must never be stored in the database or committed to version control. Talos supports zero-downtime rotation by
+ maintaining current and retired secrets.
+
+2. **Key entropy** -- API keys must be generated using a cryptographically secure random number generator with at least 128 bits
+ of entropy. Talos generates keys internally; user-provided key material is not accepted for issued keys.
+
+3. **Transport security** -- All communication must use TLS. API key secrets must never appear in URLs, query parameters, or log
+ output.
+
+4. **Signing key protection** -- Ed25519 and RSA private keys used for JWT signing must be stored securely and never exposed
+ through API responses or logs.
+
+## Industry precedent
+
+Major cloud providers use HMAC for API key authentication:
+
+- **AWS** -- HMAC-SHA256 for Signature Version 4 request signing
+- **Google Cloud** -- HMAC keys for Cloud Storage interoperability
+- **Stripe** -- HMAC for API authentication and webhook signature verification
+- **GitHub** -- HMAC-SHA256 for webhook payload signatures
+
+These systems share the same rationale: high-entropy keys do not benefit from slow hashing, and verification throughput is a
+critical operational requirement.
diff --git a/docs/talos/concepts/token-derivation-security.md b/docs/talos/concepts/token-derivation-security.md
new file mode 100644
index 000000000..2cb37e35d
--- /dev/null
+++ b/docs/talos/concepts/token-derivation-security.md
@@ -0,0 +1,89 @@
+---
+title: Token derivation security
+description: Stateless verification model and revocation semantics for derived tokens
+---
+
+# Token derivation security
+
+## Overview
+
+Talos derives short-lived JWTs and macaroons from long-lived API keys. These derived tokens are **stateless capability tokens**:
+all security constraints are enforced at creation time, and verification requires no database access. This design gives
+predictable sub-millisecond verification, zero database load on the hot path, and straightforward edge deployment.
+
+## Creation-time enforcement
+
+When a token is derived via `POST /v2alpha1/tokens:derive`, all security constraints are enforced before the token is signed:
+
+- **Parent key must be ACTIVE.** A revoked or expired parent key cannot produce new tokens.
+- **Scopes must be a subset of the parent.** The derived token can have equal or fewer scopes than the parent, never more.
+- **TTL cannot exceed the parent's remaining lifetime.** The derived token expires at or before the parent key's expiration.
+- **Subject and owner are inherited.** These fields are copied from the parent and cannot be overridden.
+
+If any constraint is violated, the derivation request fails with an appropriate error code. No token is issued.
+
+## Verification-time behavior
+
+Verifying a derived token is purely cryptographic. The system checks:
+
+1. **Signature validity** -- the token was signed by a trusted JWK signing key.
+2. **Expiration** -- the `exp` claim has not passed.
+
+There are no database lookups, no parent key status checks, and no scope re-validation against the parent. This produces:
+
+- **Low latency.** Verification completes in 1-2 ms compared to 5-10 ms with database round-trips.
+- **Zero database load.** Derived token verification never touches the database.
+- **Edge deployability.** Verification nodes need only the public JWK set, not a database connection.
+- **High availability.** Verification is unaffected by database outages.
+
+## Revocation model
+
+When a parent API key is revoked:
+
+- **New derivations are blocked.** Any attempt to derive from the revoked parent returns an error.
+- **Existing tokens remain valid until they expire.** The cryptographic signature is still valid and the token has not expired.
+- **The parent key itself is immediately rejected.** Direct verification of the parent key returns a revocation error.
+
+This behavior is intentional. It provides:
+
+- **Predictable token lifetimes.** Applications can rely on tokens remaining valid for their full TTL.
+- **No cascading failures.** Revoking a parent does not invalidate thousands of active sessions simultaneously.
+- **Graceful degradation.** Downstream systems have time to transition before tokens expire.
+
+## Immediate revocation strategies
+
+If your threat model requires faster invalidation of derived tokens, use one or more of these approaches:
+
+- **Short TTLs.** Set derived token TTLs to 5-15 minutes. Services can re-derive tokens frequently with minimal overhead. This is
+ the primary recommended approach.
+- **External deny lists.** Maintain a deny list of revoked token IDs (`jti` claims) outside Talos. Check the deny list during your
+ application's authorization step.
+- **Key rotation.** Rotate the JWK signing keys. Tokens signed with the old key will fail signature verification immediately. This
+ invalidates all derived tokens, not just those from one parent.
+
+## TTL guidelines
+
+| Use case | Recommended TTL | Rationale |
+| -------------------------- | ----------------------- | -------------------------------------------------- |
+| User sessions (web/mobile) | 15-60 min | Balances user experience with security exposure |
+| Service-to-service auth | 5-15 min | Services re-derive easily; minimal exposure window |
+| Sensitive operations | 1-5 min | Limits damage from token theft |
+| Long-running batch jobs | Use parent key directly | Avoids re-derivation during long processes |
+
+Short TTLs are the simplest and most effective control. When combined with the stateless verification model, they give security
+properties equivalent to stateful parent-status checks without the latency or availability cost.
+
+## Security properties
+
+Derived tokens are capability tokens with time-bounded authority:
+
+1. **All constraints enforced at creation.** The token can only be issued if the parent passes all checks.
+2. **Cryptographically unforgeable.** Tokens are signed with EdDSA or RS256 and cannot be tampered with.
+3. **Time-bounded exposure.** Short TTLs limit the window in which a compromised token is useful.
+4. **Immutable claims.** Subject, owner, scopes, and expiry are sealed in the token.
+5. **No privilege escalation.** Scopes can never exceed the parent's scopes at creation time.
+
+## Next steps
+
+- [Security model](security-model.md) -- cryptographic primitives and tenant isolation
+- [Derive tokens](../integrate/derive-tokens.mdx) -- integration guide for the token derivation API
diff --git a/docs/talos/concepts/token-format.md b/docs/talos/concepts/token-format.md
new file mode 100644
index 000000000..00519c7dd
--- /dev/null
+++ b/docs/talos/concepts/token-format.md
@@ -0,0 +1,29 @@
+---
+title: Token format
+---
+
+# Token format
+
+Issued API keys follow a structured v1 format:
+
+```
+{prefix}_v1_{identifier}_{checksum}
+```
+
+## Components
+
+| Part | Length | Description |
+| ---------- | ----------- | ---------------------------------------- |
+| Prefix | 1-8 chars | Configurable label (e.g., `prod`, `dev`) |
+| `v1` | 2 chars | Format version |
+| Identifier | ~32 chars | Base58-encoded timestamp + UUID |
+| Checksum | 10-11 chars | HMAC-SHA256, truncated, Base58 |
+
+## How it works
+
+The identifier contains a Unix timestamp and UUID v4, Base58-encoded. The UUID is the `key_id` used for database lookup. The
+checksum is HMAC-SHA256 over the payload, enabling tamper detection.
+
+During verification, all configured secrets (current + retired) are tried, supporting zero-downtime secret rotation.
+
+See [Token format reference](../reference/token-format.md) for the full specification.
diff --git a/docs/talos/index.md b/docs/talos/index.md
new file mode 100644
index 000000000..7836d6e7f
--- /dev/null
+++ b/docs/talos/index.md
@@ -0,0 +1,47 @@
+---
+title: Ory Talos
+slug: /
+---
+
+# Ory Talos
+
+Ory Talos is an API key management service. It handles the full lifecycle of API credentials: issuing keys, verifying them on the
+data plane, deriving short-lived tokens (JWT and macaroon), and revoking access. Verification is sub-millisecond on a warm cache
+and stays under 5 ms p99 against a local SQL backend on commodity hardware.
+
+Talos separates **admin operations** (issue, rotate, revoke, derive) from **data-plane operations** (verify, self-revoke) so you
+can scale and secure each path independently.
+
+## Choose your path
+
+### I want to integrate Talos into my application
+
+You're a developer building an application that needs API key authentication. Start here:
+
+- **[Quickstart](./quickstart/index.mdx)** — issue and verify your first API key in 5 minutes
+- **[Integration guide](./integrate/index.md)** — full API walkthrough for issuing, verifying, importing keys, and deriving tokens
+- **[Error handling](./integrate/error-handling.mdx)** — error codes and retry strategies
+
+### I want to run Talos in production
+
+You're a platform engineer responsible for deploying and operating Talos. Start here:
+
+- **[Install](./operate/install.md)** — binary install or build from source
+- **[Configure](./operate/configure.md)** — configuration file, environment variables, and hot-reload behavior
+- **[Deploy](./operate/deploy/index.md)** — Docker, Kubernetes, and split admin/data plane topologies
+- **[Monitor](./operate/monitoring/index.md)** — Prometheus metrics, OpenTelemetry tracing, and health endpoints
+
+## Editions
+
+**Ory Talos OSS** (Apache 2.0) runs on a single node with a SQLite backend. It includes the full key lifecycle, token derivation,
+and CLI.
+
+**Ory Talos Commercial** adds multi-tenancy, PostgreSQL/MySQL/CockroachDB backends, distributed caching (Redis, in-memory), edge
+proxy nodes, and the admin UI. Pages that cover commercial-only features are marked with a "Commercial" badge.
+
+## Learn more
+
+- **[Concepts](./concepts/index.md)** — architecture, credential types, security model, and caching behavior
+- **[API reference](./reference/api/ory-talos-api.info.mdx)** — full admin and data plane endpoint documentation
+- **[CLI reference](./reference/index.md)** — command-line tool documentation
+- **[Configuration reference](./reference/config.mdx)** — all configuration keys and their defaults
diff --git a/docs/talos/integrate/batch-operations.mdx b/docs/talos/integrate/batch-operations.mdx
new file mode 100644
index 000000000..e6ad836d3
--- /dev/null
+++ b/docs/talos/integrate/batch-operations.mdx
@@ -0,0 +1,161 @@
+---
+title: Batch operations
+description: Verify and import multiple credentials in a single request
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Batch operations
+
+Talos supports batch endpoints for high-throughput scenarios. Batch operations process items in parallel and return per-item
+results.
+
+
+
+
+First, issue two keys to use in batch operations:
+
+
+
+
+
+
+```bash
+export KEY1=$(talos keys issue "batch-key-1" \
+ --actor user_1 --scopes "read" \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null | jq -er '.secret')
+
+export KEY2=$(talos keys issue "batch-key-2" \
+ --actor user_2 --scopes "write" \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null | jq -er '.secret')
+
+echo "Keys issued"
+```
+
+
+
+
+```bash
+export KEY1=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{"name":"batch-key-1","actor_id":"user_1","scopes":["read"]}' | \
+ jq -er '.secret')
+
+export KEY2=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{"name":"batch-key-2","actor_id":"user_2","scopes":["write"]}' | \
+ jq -er '.secret')
+
+echo "Keys issued"
+```
+
+
+
+
+## Batch verify
+
+Verify up to 100 credentials in a single request:
+
+
+
+
+
+
+```bash
+talos keys batch-verify "$KEY1" "$KEY2" "invalid-key-for-testing" \
+ --format json \
+ -e "$TALOS_URL" | jq .
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:batchVerify" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"requests\": [
+ {\"credential\": \"$KEY1\"},
+ {\"credential\": \"$KEY2\"},
+ {\"credential\": \"invalid-key-for-testing\"}
+ ]
+ }" | jq .
+```
+
+
+
+
+### Response format
+
+The response contains a `results` array. Each element has the same fields as a single
+[verify response](./issue-and-verify.mdx#verification-response). Results are returned in the same order as the requests.
+
+Invalid credentials return `active: false` with an `error_code` — they do not cause the batch request to fail.
+
+### Limits
+
+| Constraint | Value |
+| ------------------------------- | ----- |
+| Maximum credentials per request | 100 |
+| Minimum credentials per request | 1 |
+
+## Batch import
+
+Import up to 1000 keys in a single request:
+
+
+
+
+
+
+```bash
+talos keys imported batch-import --file - -e "$TALOS_URL" <<'JSON'
+[
+ {"raw_key": "legacy_key_aaa", "name": "Legacy Key A", "actor_id": "migration"},
+ {"raw_key": "legacy_key_bbb", "name": "Legacy Key B", "actor_id": "migration"},
+ {"raw_key": "legacy_key_ccc", "name": "Legacy Key C", "actor_id": "migration", "scopes": ["read"]}
+]
+JSON
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/importedApiKeys:batchImport" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "requests": [
+ {"raw_key": "legacy_key_aaa", "name": "Legacy Key A", "actor_id": "migration"},
+ {"raw_key": "legacy_key_bbb", "name": "Legacy Key B", "actor_id": "migration"},
+ {"raw_key": "legacy_key_ccc", "name": "Legacy Key C", "actor_id": "migration", "scopes": ["read"]}
+ ]
+ }' | jq .
+```
+
+
+
+
+### Response format
+
+The response includes a `results` array with per-item outcomes, plus `success_count` and `failure_count` counters. The HTTP
+response is `200 OK` if at least one key succeeds. Check `failure_count` and individual `error_code` fields to detect partial
+failures.
+
+For the complete field reference, see the
+[BatchImportAPIKeys API reference](../reference/api/admin-batch-import-api-keys.api.mdx). For batch import error codes, see the
+[error codes reference](../reference/error-codes.md#batch-import-error-codes).
+
+### Limits
+
+| Constraint | Value |
+| ------------------------ | ----- |
+| Maximum keys per request | 1000 |
+
+## Next steps
+
+- [Import keys](import-keys.mdx) — single key import with full field reference
+- [Issue and verify](issue-and-verify.mdx) — create and verify individual keys
diff --git a/docs/talos/integrate/derive-tokens.mdx b/docs/talos/integrate/derive-tokens.mdx
new file mode 100644
index 000000000..0fa32a2f3
--- /dev/null
+++ b/docs/talos/integrate/derive-tokens.mdx
@@ -0,0 +1,238 @@
+---
+title: Derive tokens
+description: Mint short-lived JWT or macaroon tokens from API keys
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Derive tokens
+
+Token derivation creates short-lived JWT or macaroon tokens from a long-lived API key. Use derived tokens when you need:
+
+- **Browser-safe credentials** — JWTs can be verified client-side without hitting the server.
+- **Temporary access** — grant time-limited access with a subset of the parent key's scopes.
+- **Custom claims** — embed application-specific data in the token.
+
+Derived tokens inherit permissions from the parent API key and can be verified on the same data plane endpoint.
+
+
+
+
+First, issue a parent key for token derivation:
+
+
+
+
+
+
+```bash
+RESPONSE=$(talos keys issue "derive-test" \
+ --actor user_1 \
+ --scopes "read,write" \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+```
+
+
+
+
+```bash
+ISSUE_RESP=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{"name":"derive-test","actor_id":"user_1","scopes":["read","write"]}')
+
+echo "$ISSUE_RESP" | jq .
+
+export API_SECRET=$(echo "$ISSUE_RESP" | jq -er '.secret')
+```
+
+
+
+
+## Derive a JWT
+
+Send the parent key's secret to the derive endpoint with `TOKEN_ALGORITHM_JWT`:
+
+
+
+
+
+
+```bash
+RESPONSE=$(talos keys derive-token "$API_SECRET" \
+ --algorithm jwt \
+ --ttl 1h \
+ --claims '{"role": "viewer", "tenant": "acme"}' \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export JWT_TOKEN=$(echo "$RESPONSE" | jq -er '.token.token')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:derive" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"credential\": \"$API_SECRET\",
+ \"algorithm\": \"TOKEN_ALGORITHM_JWT\",
+ \"ttl\": \"1h\",
+ \"scopes\": [\"read\"],
+ \"custom_claims\": {\"role\": \"viewer\", \"tenant\": \"acme\"}
+ }")
+
+echo "$RESPONSE" | jq .
+
+export JWT_TOKEN=$(echo "$RESPONSE" | jq -er '.token.token')
+```
+
+
+
+
+### Request fields
+
+The key fields are `credential` (the parent API key secret), `algorithm` (`TOKEN_ALGORITHM_JWT` or `TOKEN_ALGORITHM_MACAROON`),
+optional `ttl`, `scopes` (subset of parent's), and `custom_claims`. For the complete field reference, see the
+[DeriveToken API reference](../reference/api/admin-derive-token.api.mdx).
+
+For HTTP API requests, `ttl` accepts extended formats such as `1y`, `1mo`, `1w`, `1d`, and compounds like `1y6mo` in addition to
+standard Go durations. The current CLI `--ttl` flag still expects standard Go durations such as `1h` or `30m`.
+
+### Response
+
+The response contains a `token` object with `token.token` (the derived token string), `token.expire_time`, `token.scopes`, and
+`token.claims`. For the complete field reference, see the
+[DeriveToken API reference](../reference/api/admin-derive-token.api.mdx).
+
+## Verify a derived token
+
+Derived tokens are verified on the same data plane endpoint as API keys:
+
+
+
+
+
+
+```bash
+talos keys verify "$JWT_TOKEN" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\":\"$JWT_TOKEN\"}" | jq .
+```
+
+
+
+
+The verification response includes the token's scopes, actor, and metadata from the parent key.
+
+## Derive a macaroon
+
+Macaroons use HMAC-based authentication with support for caveats:
+
+
+
+
+
+
+```bash
+talos keys derive-token "$API_SECRET" \
+ --algorithm macaroon \
+ --ttl 30m \
+ -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:derive" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"credential\": \"$API_SECRET\",
+ \"algorithm\": \"TOKEN_ALGORITHM_MACAROON\",
+ \"ttl\": \"30m\"
+ }" | jq .
+```
+
+
+
+
+## JWT vs macaroon
+
+| Feature | JWT | Macaroon |
+| ------------------------ | -------------------------------------------------- | ----------------------------------------- |
+| Verification | Signature-based (can verify client-side with JWKS) | HMAC-based (requires server verification) |
+| Size | Larger (base64 JSON + signature) | Smaller (binary format) |
+| Client-side verification | Yes, via JWKS endpoint | No |
+| Custom claims | Yes | Yes (as caveats) |
+
+## JWKS endpoint
+
+For client-side JWT verification, fetch the public keys from the JWKS endpoint at `/v2alpha1/admin/derivedKeys/jwks.json`:
+
+
+
+
+
+
+```bash
+talos jwk get -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/derivedKeys/jwks.json" | jq .
+```
+
+
+
+
+The endpoint serves the active public signing keys plus any retired keys still inside the verification window. Each entry includes
+a `kid` field that matches the `kid` header on tokens signed with that key.
+
+### Client-side caching and refresh
+
+Cache the JWKS response on the client so verification does not call Talos on every request. Recommended settings:
+
+| Setting | Recommended value | Notes |
+| -------------------- | ----------------- | ------------------------------------------------------- |
+| Cache TTL | 5 – 15 minutes | Bounds how long a rotated-out key keeps verifying. |
+| Refresh-on-miss | Enabled | If a token's `kid` is unknown, refetch JWKS once. |
+| Refresh failure mode | Serve stale | If the refetch fails, keep the previous keys until TTL. |
+
+Most mature JWT libraries (`jose` for Node, `PyJWT`/`PyJWKClient` for Python, `go-jose`, `jjwt` for Java) support these patterns
+natively — set the cache TTL and enable refresh-on-unknown-kid. Do not poll the endpoint on a fixed interval shorter than 1
+minute; it adds load without changing the practical revocation window, which is bounded by the longest issued token TTL.
+
+When you rotate signing keys, keep the previous key in the JWKS response (mark it retired in the server config, do not delete the
+JWK) for at least the longest issued token TTL plus the maximum client cache TTL. Otherwise clients with a freshly cached JWKS
+that lacks the new `kid` can reject valid tokens until their cache expires.
+
+## Scope restrictions
+
+Derived tokens can only have scopes that are a subset of the parent key's scopes. If you request any scope that the parent key
+does not have, the request fails with a `403 Forbidden` error. To restrict scopes, request only scopes that exist on the parent
+key.
+
+## Next steps
+
+- [Issue and verify](issue-and-verify.mdx) — create the parent API keys used for derivation
+- [Key lifecycle](key-lifecycle.mdx) — rotate and revoke parent keys
+- [Self-revocation](self-revocation.mdx) — allow key holders to revoke their own keys
diff --git a/docs/talos/integrate/error-handling.mdx b/docs/talos/integrate/error-handling.mdx
new file mode 100644
index 000000000..9a6d095be
--- /dev/null
+++ b/docs/talos/integrate/error-handling.mdx
@@ -0,0 +1,145 @@
+---
+title: Error handling
+description: Error response format, error codes, and retry logic
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Error handling
+
+All Talos API errors follow the [google.rpc.Status](https://cloud.google.com/apis/design/errors#error_model) shape. This guide
+covers the error response structure, common error codes, and retry strategies.
+
+
+
+
+## Error response format
+
+Every non-2xx response uses the `google.rpc.Status` envelope:
+
+```json
+{
+ "code": 5,
+ "message": "API key not found",
+ "details": [
+ {
+ "@type": "type.googleapis.com/google.rpc.ErrorInfo",
+ "reason": "API_KEY_NOT_FOUND",
+ "domain": "talos.ory.sh",
+ "metadata": {
+ "key_id": "01J9X7…"
+ }
+ }
+ ]
+}
+```
+
+| Field | Description |
+| --------- | ------------------------------------------------------------------------------------------------------ |
+| `code` | Canonical [gRPC status code](https://grpc.github.io/grpc/core/md_doc_statuscodes.html) (integer 0-16). |
+| `message` | Human-readable summary. Suitable for logging, not for end-user display. |
+| `details` | Optional list of typed error details. `ErrorInfo` carries the machine-readable `reason`. |
+
+The HTTP status code is set from the canonical [gRPC-to-HTTP mapping](https://cloud.google.com/apis/design/errors#http_mapping).
+For example, code `5` (`NOT_FOUND`) returns HTTP 404; code `7` (`PERMISSION_DENIED`) returns HTTP 403.
+
+### Reading the reason
+
+The stable, machine-readable identifier is `details[*].reason` on the `ErrorInfo` detail. Match on `reason` — never on `message`,
+which can change between releases.
+
+```bash
+REASON=$(echo "$RESPONSE" | jq -er '.details[]? | select(."@type" | endswith("ErrorInfo")).reason')
+```
+
+## Verification errors
+
+The verify endpoint (`POST /v2alpha1/admin/apiKeys:verify`) is the one exception. A verification failure is part of the normal
+verification result, not a transport-level error, so it returns `200 OK` with `is_active: false` and a structured error code:
+
+```json
+{
+ "is_active": false,
+ "error_code": "VERIFICATION_ERROR_REVOKED",
+ "error_message": "The API key has been revoked."
+}
+```
+
+Treat the response as successful; act on `is_active` and `error_code`. Only fall back to the `google.rpc.Status` handling above
+when the HTTP status is not 2xx (for example, the verify request itself was malformed).
+
+For the complete list of verification error codes (`VERIFICATION_ERROR_*`), see the
+[error codes reference](../reference/error-codes.md#verification-error-codes).
+
+## HTTP status codes
+
+For the complete list of HTTP status codes and reasons, see the [error codes reference](../reference/error-codes.md).
+
+Key categories:
+
+- **4xx errors**: Client errors (bad request, not found, conflict). Fix the request before retrying.
+- **5xx errors**: Server errors. Retry with exponential backoff.
+
+## Retry strategy
+
+### Safe to retry
+
+- **`UNAVAILABLE` (HTTP 503)** — the server is temporarily overloaded. Retry with exponential backoff.
+- **`DEADLINE_EXCEEDED` (HTTP 504)** — the request timed out. Retry with backoff.
+- **Network errors** — connection refused, DNS failure, etc. Retry with backoff.
+
+### Not safe to retry without an idempotency key
+
+- **`ALREADY_EXISTS` (HTTP 409)** — the resource already exists. Read the existing resource and reconcile.
+- **`INVALID_ARGUMENT` (HTTP 400)** / **`FAILED_PRECONDITION` (HTTP 400)** — fix the request before retrying.
+
+### Idempotency key
+
+When issuing API keys, include `request_id` in the request body. This field is stored on the key for client-side deduplication:
+
+
+
+
+
+
+```bash
+# Note: request_id is only available via the HTTP API.
+talos keys issue "my-service" --actor user_1 -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "my-service",
+ "actor_id": "user_1",
+ "request_id": "unique-request-id-123"
+ }' | jq .
+```
+
+
+
+
+The `request_id` is recorded in the key's metadata. The server does not enforce server-side idempotent replay — sending the same
+`request_id` twice creates two keys.
+
+## Recommended backoff
+
+```
+attempt 1: wait 100ms
+attempt 2: wait 200ms
+attempt 3: wait 400ms
+attempt 4: wait 800ms
+attempt 5: wait 1600ms (give up after this)
+```
+
+Add jitter (random 0-50% of the wait time) to avoid thundering-herd effects.
+
+## Next steps
+
+- [Issue and verify](issue-and-verify.mdx) — verification response format
+- [Batch operations](batch-operations.mdx) — partial failure handling
diff --git a/docs/talos/integrate/import-keys.mdx b/docs/talos/integrate/import-keys.mdx
new file mode 100644
index 000000000..e16a268ab
--- /dev/null
+++ b/docs/talos/integrate/import-keys.mdx
@@ -0,0 +1,230 @@
+---
+title: Import existing keys
+description: Import API keys from external systems into Talos
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Import existing keys
+
+Talos can manage API keys that were created outside the system. Import lets you migrate from a legacy key management solution or
+centralize keys from multiple providers without rotating credentials. For large migrations, use the batchImport API to import up
+to 1000 keys in a single request.
+
+## How import works
+
+When you import a key, Talos stores a cryptographic hash (HMAC-SHA256) of the raw key. The original key is never stored.
+Verification works by computing the same hash and looking it up in the database.
+
+Imported keys support the same features as issued keys: scopes, metadata, expiration, token derivation (JWT/macaroon), and
+revocation.
+
+
+
+
+## Import a single key
+
+
+
+
+
+
+```bash
+RESPONSE=$(talos keys imported import "Stripe production key" \
+ --raw-key "sk_live_test_51OxAM2Qly" \
+ --actor payment-service \
+ --scopes "payments:read,payments:write" \
+ --ttl 8760h \
+ --metadata '{"source": "stripe", "environment": "production"}' \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export IMPORTED_KEY_ID=$(echo "$RESPONSE" | jq -er '.imported_api_key.key_id')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/importedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "raw_key": "sk_live_test_51OxAM2Qly",
+ "name": "Stripe production key",
+ "actor_id": "payment-service",
+ "scopes": ["payments:read", "payments:write"],
+ "ttl": "8760h",
+ "metadata": {"source": "stripe", "environment": "production"}
+ }')
+
+echo "$RESPONSE" | jq .
+
+export IMPORTED_KEY_ID=$(echo "$RESPONSE" | jq -er '.key_id')
+```
+
+
+
+
+### Request fields
+
+The key fields are `raw_key` (the actual API key string), `name`, `actor_id`, and optional `scopes`, `ttl`, and `metadata`. For
+the complete field reference, see the [ImportAPIKey API reference](../reference/api/admin-import-api-key.api.mdx).
+
+The response returns an `imported_api_key` object. The `raw_key` is **never returned** after import.
+
+## Verify an imported key
+
+Imported keys use the same verification endpoint as issued keys. The data plane automatically detects the credential type:
+
+
+
+
+
+
+```bash
+talos keys verify "sk_live_test_51OxAM2Qly" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d '{"credential":"sk_live_test_51OxAM2Qly"}' | jq .
+```
+
+
+
+
+## Batch import
+
+Import up to 1000 keys in a single request:
+
+
+
+
+
+
+```bash
+talos keys imported batch-import --file - -e "$TALOS_URL" <<'JSON'
+[
+ {"raw_key": "ghp_batch_key_001", "name": "GitHub PAT 1", "actor_id": "dev-team"},
+ {"raw_key": "ghp_batch_key_002", "name": "GitHub PAT 2", "actor_id": "dev-team"}
+]
+JSON
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/importedApiKeys:batchImport" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "requests": [
+ {"raw_key": "ghp_batch_key_001", "name": "GitHub PAT 1", "actor_id": "dev-team"},
+ {"raw_key": "ghp_batch_key_002", "name": "GitHub PAT 2", "actor_id": "dev-team"}
+ ]
+ }' | jq .
+```
+
+
+
+
+### Batch response
+
+The response includes a `results` array with per-item outcomes (`imported_api_key` on success, `error_code` and `error_message` on
+failure), plus `success_count` and `failure_count` counters. If at least one key succeeds, the HTTP response is `200 OK`.
+
+For the complete response field reference, see the
+[BatchImportAPIKeys API reference](../reference/api/admin-batch-import-api-keys.api.mdx). For batch import error codes, see the
+[error codes reference](../reference/error-codes.md#batch-import-error-codes).
+
+## List imported keys
+
+
+
+
+
+
+```bash
+talos keys imported list -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/importedApiKeys?actor_id=payment-service&page_size=10" | jq .
+```
+
+
+
+
+## Revoke an imported key
+
+Imported keys are revoked through the same unified endpoint as issued keys:
+
+
+
+
+
+
+```bash
+talos keys revoke "$IMPORTED_KEY_ID" --reason superseded -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys/$IMPORTED_KEY_ID:revoke" \
+ -H "Content-Type: application/json" \
+ -d '{"reason": "REVOCATION_REASON_SUPERSEDED"}'
+echo ""
+echo "Imported key revoked"
+```
+
+
+
+
+## Delete an imported key
+
+For permanent removal (no audit trail), use the delete endpoint:
+
+
+
+
+
+
+```bash
+talos keys imported delete "$IMPORTED_KEY_ID" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X DELETE "$TALOS_URL/v2alpha1/admin/importedApiKeys/$IMPORTED_KEY_ID"
+echo ""
+echo "Imported key deleted"
+```
+
+
+
+
+:::caution
+
+Delete is permanent and irreversible. Prefer revocation for audit trail.
+
+:::
+
+## Next steps
+
+- [Batch operations](batch-operations.mdx) -- batch verify and batch import in detail
+- [Key lifecycle](key-lifecycle.mdx) -- update, rotate, and revoke keys
+- [Derive tokens](derive-tokens.mdx) -- mint JWTs or macaroons from imported keys
diff --git a/docs/talos/integrate/index.md b/docs/talos/integrate/index.md
new file mode 100644
index 000000000..6cd573e6b
--- /dev/null
+++ b/docs/talos/integrate/index.md
@@ -0,0 +1,83 @@
+---
+title: Integrate
+description: Add API key authentication to your application
+---
+
+# Integrate Ory Talos
+
+Ory Talos exposes two logical planes that map to distinct responsibilities:
+
+- **Admin plane** — Create, update, rotate, and revoke API keys. Deploy behind your internal network or VPN. All admin endpoints
+ live under `/v2alpha1/admin/...`.
+- **Data plane** — Verify credentials with low latency and let key holders revoke their own keys. The two public verification
+ endpoints are `POST /v2alpha1/admin/apiKeys:verify` and `POST /v2alpha1/admin/apiKeys:batchVerify`; the self-service endpoint is
+ `POST /v2alpha1/apiKeys:selfRevoke`.
+
+Most integrations follow a simple pattern: issue keys on the admin plane, then verify them on the data plane every time a request
+arrives.
+
+The verify endpoints share the `/admin/` URL prefix for historical reasons. They are still safe to expose publicly — they take a
+credential and return verification metadata only — but you must restrict the rest of `/admin/` at your edge. See
+[Exposing only the verify endpoints publicly](#exposing-only-the-verify-endpoints-publicly) below.
+
+## Common workflows
+
+| Task | Endpoint | Guide |
+| --------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------- |
+| Issue a key and verify it | `POST /v2alpha1/admin/issuedApiKeys`, `POST /v2alpha1/admin/apiKeys:verify` | [Issue and verify](issue-and-verify.mdx) |
+| Import keys from another system | `POST /v2alpha1/admin/importedApiKeys` | [Import keys](import-keys.mdx) |
+| Mint short-lived JWT or macaroon tokens | `POST /v2alpha1/admin/apiKeys:derive` | [Derive tokens](derive-tokens.mdx) |
+| Verify many credentials at once | `POST /v2alpha1/admin/apiKeys:batchVerify` | [Batch operations](batch-operations.mdx) |
+| Update, rotate, or revoke a key | `PATCH`, `:rotate`, `:revoke` | [Key lifecycle](key-lifecycle.mdx) |
+| Enforce per-key rate limits | `rate_limit_policy` on issue/update | [Rate limiting](rate-limiting.mdx) |
+| Let key holders revoke their own key | `POST /v2alpha1/apiKeys:selfRevoke` | [Self-revocation](self-revocation.mdx) |
+| Handle errors and retries | All endpoints | [Error handling](error-handling.mdx) |
+
+## Authentication
+
+The admin plane does not enforce authentication by default. Protect it at the infrastructure level (VPN, service mesh, reverse
+proxy with mTLS). The data plane is public-facing and requires no authentication — callers supply the credential they want to
+verify.
+
+## Exposing only the verify endpoints publicly
+
+Talos has no built-in admin authentication, so do not put `/v2alpha1/admin/*` on the public internet. Instead, run a reverse proxy
+(NGINX, Envoy, HAProxy, an API gateway) in front of the data-plane process and allow only the verify and self-revoke paths
+through:
+
+| Path | Method | Public | Reason |
+| ------------------------------------------- | ------ | ------ | ------------------------------------- |
+| `/v2alpha1/admin/apiKeys:verify` | POST | Yes | Verification — credential in request. |
+| `/v2alpha1/admin/apiKeys:batchVerify` | POST | Yes | Batch verification. |
+| `/v2alpha1/apiKeys:selfRevoke` | POST | Yes | Self-revocation by the key holder. |
+| `/health/alive`, `/health/ready` | GET | Maybe | Required for load-balancer probes. |
+| Everything else under `/v2alpha1/admin/...` | any | No | Issuance, rotation, admin revocation. |
+
+Example NGINX snippet that fronts the data plane:
+
+```nginx
+location = /v2alpha1/admin/apiKeys:verify { proxy_pass http://talos_data; }
+location = /v2alpha1/admin/apiKeys:batchVerify { proxy_pass http://talos_data; }
+location = /v2alpha1/apiKeys:selfRevoke { proxy_pass http://talos_data; }
+location = /health/alive { proxy_pass http://talos_data; }
+location = /health/ready { proxy_pass http://talos_data; }
+location / { return 404; }
+```
+
+Run the admin plane on a separate listener (or a separate process — see
+[Separate admin and data planes](../operate/deploy/separate-planes.md)) bound to an internal network so it cannot be reached even
+if the public proxy is misconfigured.
+
+## Request format
+
+All endpoints accept and return JSON with `Content-Type: application/json`. Field names use `snake_case` (for example `actor_id`,
+`key_id`, `expire_time`).
+
+Durations accept both Go format (`168h`, `30m`, `1h30m`) and protobuf format (`604800s`).
+
+Timestamps follow RFC 3339 in UTC (`2025-06-15T10:30:00Z`).
+
+## SDK and examples
+
+- [curl cheat sheet](sdk/curl.md) — every endpoint as a copy-paste curl command
+- [Go SDK](sdk/go.md) — using the generated Go client
diff --git a/docs/talos/integrate/ip-restrictions.mdx b/docs/talos/integrate/ip-restrictions.mdx
new file mode 100644
index 000000000..7af0202ab
--- /dev/null
+++ b/docs/talos/integrate/ip-restrictions.mdx
@@ -0,0 +1,244 @@
+---
+title: IP restrictions
+description: Restrict API key usage to specific IP addresses or CIDR ranges
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# IP restrictions
+
+IP restrictions let you limit which client IPs can use an API key. When enabled, verification rejects requests from IPs outside
+the allowed CIDR ranges. Keys without IP restrictions are unrestricted.
+
+## Prerequisites
+
+A running Talos server. See the [quickstart](../quickstart/index.mdx) to start one locally.
+
+
+
+
+## Configure client IP source
+
+By default, Talos uses the TCP remote address (`REMOTE_ADDR`) to determine client IP. If your server runs behind a reverse proxy
+or CDN, configure the correct header in your Talos config:
+
+```yaml
+serve:
+ http:
+ client_ip_source: CLIENT_IP_SOURCE_CF_CONNECTING_IP
+```
+
+Supported values:
+
+- `CLIENT_IP_SOURCE_UNSPECIFIED` or `CLIENT_IP_SOURCE_REMOTE_ADDR` — TCP remote address (default)
+- `CLIENT_IP_SOURCE_CF_CONNECTING_IP` — Cloudflare
+- `CLIENT_IP_SOURCE_X_FORWARDED_FOR` — Standard proxy header
+- `CLIENT_IP_SOURCE_X_REAL_IP` — Nginx
+- `CLIENT_IP_SOURCE_TRUE_CLIENT_IP` — Cloudflare Enterprise
+
+This is a global setting — all IP restriction checks use the same source. Set it once to match your infrastructure topology.
+
+## Issue a key with IP restrictions
+
+Add the `ip_restriction` field when creating a key. The `allowed_cidrs` array accepts both individual IPs (with `/32` or `/128`
+suffix) and CIDR ranges:
+
+
+
+
+
+
+```bash
+RESPONSE=$(talos keys issue "restricted-key" \
+ --actor service_payments \
+ --allowed-cidrs "127.0.0.1/32,10.0.0.0/8" \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "restricted-key",
+ "actor_id": "service_payments",
+ "ip_restriction": {
+ "allowed_cidrs": ["127.0.0.1/32", "10.0.0.0/8"]
+ }
+ }')
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+For the complete request field reference, see the [IssueAPIKey API reference](../reference/api/admin-issue-api-key.api.mdx).
+
+## Verify from an allowed IP
+
+When the client IP is within an allowed CIDR range, verification succeeds:
+
+
+
+
+
+
+```bash
+talos keys verify "$API_SECRET" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+VERIFY_RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\": \"$API_SECRET\"}")
+
+echo "$VERIFY_RESPONSE" | jq .
+```
+
+
+
+
+The response includes the key metadata with `is_active: true`.
+
+## Verification from a disallowed IP
+
+When the client IP is outside all allowed CIDR ranges, verification returns `VERIFICATION_ERROR_IP_NOT_ALLOWED`. The response does
+not reveal which CIDRs are configured.
+
+For the full list of verification error codes, see the
+[error codes reference](../reference/error-codes.md#verification-error-codes).
+
+## Update IP restrictions on an existing key
+
+Use `PATCH` to add, change, or remove IP restrictions on an existing key:
+
+
+
+
+
+
+```bash
+talos keys issued update "$KEY_ID" \
+ --allowed-cidrs "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" \
+ -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+UPDATE_RESPONSE=$(curl -s -X PATCH "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "ip_restriction": {
+ "allowed_cidrs": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
+ }
+ }')
+
+echo "$UPDATE_RESPONSE" | jq .
+```
+
+
+
+
+To remove all IP restrictions (making the key unrestricted), set `allowed_cidrs` to an empty array:
+
+
+
+
+
+
+```bash
+talos keys issued update "$KEY_ID" \
+ --allowed-cidrs "" \
+ -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+UNRESTRICT_RESPONSE=$(curl -s -X PATCH "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "ip_restriction": {
+ "allowed_cidrs": []
+ }
+ }')
+
+echo "$UNRESTRICT_RESPONSE" | jq .
+```
+
+
+
+
+For the complete update field reference, see the
+[UpdateIssuedAPIKey API reference](../reference/api/admin-update-issued-api-key.api.mdx).
+
+## Import keys with IP restrictions
+
+You can also set IP restrictions when importing external keys:
+
+
+
+
+
+
+```bash
+talos keys imported import "imported-restricted" \
+ --raw-key "sk_live_example_key_for_import_test" \
+ --actor "user_restrict" \
+ --allowed-cidrs "203.0.113.0/24" \
+ -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+IMPORT_RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/importedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "imported-restricted",
+ "raw_key": "sk_live_example_key_for_import_test",
+ "actor_id": "user_restrict",
+ "ip_restriction": {
+ "allowed_cidrs": ["203.0.113.0/24"]
+ }
+ }')
+
+echo "$IMPORT_RESPONSE" | jq .
+```
+
+
+
+
+For the complete import field reference, see the [ImportAPIKey API reference](../reference/api/admin-import-api-key.api.mdx).
+
+## Behavior notes
+
+- **Allowlist model**: Only listed CIDRs are permitted. An empty `allowed_cidrs` array means the key is unrestricted (all IPs
+ allowed).
+- **Cache TTL**: IP restriction changes take effect after the cache TTL expires. See
+ [cache configuration](../operate/cache/index.md) for TTL settings.
+- **Fail-closed**: If client IP resolution fails, the request is denied.
+- **IPv4 and IPv6**: Both address families are supported. Use `/32` for single IPv4 addresses and `/128` for single IPv6
+ addresses.
+- **Derived tokens**: IP restrictions apply to the underlying API key, not to derived tokens (JWTs/macaroons). Token verification
+ checks the key's IP restrictions at derivation time.
diff --git a/docs/talos/integrate/issue-and-verify.mdx b/docs/talos/integrate/issue-and-verify.mdx
new file mode 100644
index 000000000..09b13d269
--- /dev/null
+++ b/docs/talos/integrate/issue-and-verify.mdx
@@ -0,0 +1,204 @@
+---
+title: Issue and verify API keys
+description: Create API keys on the admin plane and verify them on the data plane
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Issue and verify API keys
+
+This guide walks through the full lifecycle of issuing an API key and verifying it. All examples are executable and tested in CI.
+
+## Prerequisites
+
+A running Talos server and the `talos` CLI. See the [quickstart](../quickstart/index.mdx) to start one locally.
+
+
+
+
+## Issue an API key
+
+Send a request to the admin plane to create a new key:
+
+
+
+
+
+
+```bash
+RESPONSE=$(talos keys issue "backend-service" \
+ --actor user_42 \
+ --scopes "read:orders,write:orders" \
+ --ttl 720h \
+ --metadata '{"team": "payments", "environment": "staging"}' \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "backend-service",
+ "actor_id": "user_42",
+ "scopes": ["read:orders", "write:orders"],
+ "ttl": "720h",
+ "metadata": {"team": "payments", "environment": "staging"}
+ }')
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.key_id')
+```
+
+
+
+
+### Request fields
+
+The key fields are `name` (human-readable label), `actor_id` (key actor), and optional `scopes`, `ttl`, `metadata`, and
+`rate_limit_policy`. For the complete field reference, see the
+[IssueAPIKey API reference](../reference/api/admin-issue-api-key.api.mdx).
+
+For HTTP API requests, `ttl` also accepts extended formats such as `1y`, `1mo`, `1w`, `1d`, and compounds like `1y6mo`. The
+current CLI `--ttl` flag examples still use standard Go durations such as `720h` and `1h30m`.
+
+### Response fields
+
+The response contains two top-level fields:
+
+- **`issued_api_key`** — The key metadata (ID, name, actor, scopes, status, timestamps).
+- **`secret`** — The full API key credential. This value is returned **only once** and cannot be retrieved later. Store it
+ securely.
+
+For the complete metadata field reference, see the [IssueAPIKey API reference](../reference/api/admin-issue-api-key.api.mdx).
+
+## Verify a key
+
+Send the secret to the data plane to check whether a credential is valid:
+
+
+
+
+
+
+```bash
+talos keys verify "$API_SECRET" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\":\"$API_SECRET\"}" | jq .
+```
+
+
+
+
+### Verification response
+
+The response includes `is_active` (boolean), `key_id`, `actor_id`, `issuer`, `scopes`, `metadata`, and `expire_time` when valid.
+When `is_active` is `false`, `error_code` and `error_message` indicate the reason. When rate limit enforcement is enabled
+(Commercial), the response also includes `rate_limit_remaining` and `rate_limit_reset_time` for keys with a rate limit policy. For
+the complete field reference, see the [VerifyAPIKey API reference](../reference/api/admin-verify-api-key.api.mdx).
+
+### Verification error codes
+
+When `is_active` is `false`, the `error_code` field indicates why. Common codes include `VERIFICATION_ERROR_EXPIRED`,
+`VERIFICATION_ERROR_REVOKED`, `VERIFICATION_ERROR_NOT_FOUND`, and `VERIFICATION_ERROR_RATE_LIMITED` (Commercial, when the key's
+rate limit quota is exhausted). For the complete list, see the
+[verification error codes reference](../reference/error-codes.md#verification-error-codes).
+
+## Cache bypass
+
+Verification results are cached for performance. After revoking a key, you can bypass the cache for immediate consistency:
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -H "Cache-Control: no-cache" \
+ -d '{"credential":"sk_..."}'
+```
+
+Cache control headers:
+
+| Header | Effect |
+| ------------------------- | ------------------------------------------- |
+| `Cache-Control: no-cache` | Bypass cache read, force fresh DB lookup |
+| `Cache-Control: no-store` | Bypass both cache read and write |
+| `Pragma: no-cache` | Same as `no-cache` (HTTP/1.0 compatibility) |
+
+## Retrieve a key by ID
+
+Look up key metadata without the secret:
+
+
+
+
+
+
+```bash
+talos keys issued get "$KEY_ID" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" | jq .
+```
+
+
+
+
+The secret is never returned from `GET` requests.
+
+## List keys
+
+List all issued keys with optional filtering and pagination:
+
+
+
+
+
+
+```bash
+talos keys issued list --actor user_42 --page-size 10 -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/issuedApiKeys?page_size=10&actor_id=user_42" | jq .
+```
+
+
+
+
+### Query parameters
+
+Key parameters are `page_size`, `page_token` (cursor-based pagination), `actor_id`, and `status` (filtering). For the complete
+parameter reference, see the [ListIssuedAPIKeys API reference](../reference/api/admin-list-issued-api-keys.api.mdx).
+
+The response includes a `next_page_token` field. When empty, you have reached the last page.
+
+## Next steps
+
+- [Key lifecycle](key-lifecycle.mdx) — update, rotate, and revoke keys
+- [Import keys](import-keys.mdx) — bring existing keys into Talos
+- [Derive tokens](derive-tokens.mdx) — mint short-lived JWTs or macaroons
+- [Error handling](error-handling.mdx) — error response format and retry logic
diff --git a/docs/talos/integrate/key-lifecycle.mdx b/docs/talos/integrate/key-lifecycle.mdx
new file mode 100644
index 000000000..52ff45a6c
--- /dev/null
+++ b/docs/talos/integrate/key-lifecycle.mdx
@@ -0,0 +1,228 @@
+---
+title: Key lifecycle
+description: Update, rotate, and revoke API keys
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Key lifecycle
+
+After issuing an API key, you can update its metadata, rotate the secret, or revoke it. All lifecycle operations use the admin
+plane.
+
+
+
+
+First, issue a key to work with:
+
+
+
+
+
+
+```bash
+RESPONSE=$(talos keys issue "lifecycle-test" \
+ --actor user_1 \
+ --scopes "read,write" \
+ --metadata '{"team":"backend"}' \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+```bash
+ISSUE_RESP=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{"name":"lifecycle-test","actor_id":"user_1","scopes":["read","write"],"metadata":{"team":"backend"}}')
+
+echo "$ISSUE_RESP" | jq .
+
+export API_SECRET=$(echo "$ISSUE_RESP" | jq -er '.secret')
+export KEY_ID=$(echo "$ISSUE_RESP" | jq -er '.key_id')
+```
+
+
+
+
+When you set `ttl` on issue or import requests, the HTTP API accepts extended formats such as `1y`, `1mo`, `1w`, `1d`, and
+compounds like `1y6mo` in addition to standard Go durations. The current CLI `--ttl` flags still expect standard Go duration
+strings; see the [configuration reference](../reference/config.mdx) for the canonical duration format summary.
+
+## Update key metadata
+
+Use `PATCH` to update a key's name, scopes, metadata, or rate limit policy without changing the secret:
+
+
+
+
+
+
+```bash
+talos keys issued update "$KEY_ID" \
+ --name "lifecycle-test-updated" \
+ --scopes "read" \
+ --metadata '{"team": "backend", "tier": "premium"}' \
+ -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X PATCH "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "lifecycle-test-updated",
+ "scopes": ["read"],
+ "metadata": {"team": "backend", "tier": "premium"},
+ "update_mask": {"paths": ["name", "scopes", "metadata"]}
+ }' | jq .
+```
+
+
+
+
+### Update mask
+
+The `update_mask` field controls which fields are modified. Only fields listed in `paths` are changed. This follows the
+[AIP-134](https://google.aip.dev/134) standard for partial updates.
+
+Updatable fields include `name`, `scopes`, `metadata`, and `rate_limit_policy`. For the complete field reference, see the
+[UpdateIssuedAPIKey API reference](../reference/api/admin-update-issued-api-key.api.mdx).
+
+## Rotate a key
+
+Rotation creates a new key with a new secret and immediately revokes the old one:
+
+
+
+
+
+
+```bash
+RESPONSE=$(talos keys issued rotate "$KEY_ID" \
+ --scopes "read,write,admin" \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys/${KEY_ID}:rotate" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "scopes": ["read", "write", "admin"],
+ "update_mask": {"paths": ["scopes"]}
+ }')
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.key_id')
+```
+
+
+
+
+### Rotation response
+
+The response includes the new `issued_api_key` (with a new `key_id`), the new `secret` (shown once), and `old_issued_api_key`
+(status `KEY_STATUS_REVOKED`). For the complete field reference, see the
+[RotateIssuedAPIKey API reference](../reference/api/admin-rotate-issued-api-key.api.mdx).
+
+### Zero-downtime rotation
+
+The `:rotate` endpoint revokes the old key immediately. For zero-downtime rotation:
+
+1. Issue a new key with `POST /v2alpha1/admin/issuedApiKeys`
+2. Deploy the new secret to all services
+3. Verify the new secret works everywhere
+4. Revoke the old key with `POST /v2alpha1/admin/apiKeys/{old_key_id}:revoke`
+
+## Revoke a key
+
+Revocation is irreversible. Once revoked, the key fails verification immediately (subject to cache TTL):
+
+
+
+
+
+
+```bash
+talos keys revoke "$KEY_ID" --reason superseded -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys/${KEY_ID}:revoke" \
+ -H "Content-Type: application/json" \
+ -d '{"reason": "REVOCATION_REASON_SUPERSEDED"}'
+echo ""
+echo "Key revoked"
+```
+
+
+
+
+### Revocation reasons
+
+Standard reasons include `REVOCATION_REASON_KEY_COMPROMISE`, `REVOCATION_REASON_SUPERSEDED`,
+`REVOCATION_REASON_AFFILIATION_CHANGED`, and `REVOCATION_REASON_PRIVILEGE_WITHDRAWN` (admin only). For the complete list, see the
+[RevokeAPIKey API reference](../reference/api/admin-revoke-api-key.api.mdx).
+
+When using `PRIVILEGE_WITHDRAWN`, you can include a `reason_text` field with a human-readable explanation.
+
+### Revocation and caching
+
+Revocation takes effect in the database immediately. However, if caching is enabled, previously cached verification results may
+remain valid until the cache entry expires. To force immediate effect, use the `Cache-Control: no-cache` header on verification
+requests.
+
+## Verify after revocation
+
+Confirm the key is no longer valid:
+
+
+
+
+
+
+```bash
+talos keys verify "$API_SECRET" --no-cache -e "$TALOS_URL" || true
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -H "Cache-Control: no-cache" \
+ -d "{\"credential\":\"$API_SECRET\"}" | jq .
+```
+
+
+
+
+## Next steps
+
+- [Self-revocation](self-revocation.mdx) -- let key holders revoke their own keys
+- [Issue and verify](issue-and-verify.mdx) -- create new keys to replace revoked ones
+- [Error handling](error-handling.mdx) -- handle revocation-related errors
diff --git a/docs/talos/integrate/rate-limiting.mdx b/docs/talos/integrate/rate-limiting.mdx
new file mode 100644
index 000000000..f0fc9b004
--- /dev/null
+++ b/docs/talos/integrate/rate-limiting.mdx
@@ -0,0 +1,211 @@
+---
+title: Rate limiting
+description: Attach and enforce rate limit policies on API keys
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Rate limiting
+
+Rate limit policies let you cap how many verification requests a key can serve within a time window. Talos stores the policy on
+the key, returns it in verification responses, and -- in the Commercial edition -- enforces it server-side. For background on how
+enforcement works in each edition, see the [rate limiting concepts page](../concepts/rate-limiting.md).
+
+## Prerequisites
+
+A running Talos server with rate limiting enabled. See the [quickstart](../quickstart/index.mdx) to start one locally.
+
+
+
+
+## Attach a rate limit policy
+
+Set a rate limit policy when issuing a key. The policy defines a `quota` (maximum requests) and a `window` (time window as a
+duration string, e.g. `"60s"`):
+
+
+
+
+```bash
+RESPONSE=$(talos keys issue "rate-limited-key" \
+ --actor service_api \
+ --rate-limit-quota 100 \
+ --rate-limit-window "60s" \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "rate-limited-key",
+ "actor_id": "service_api",
+ "rate_limit_policy": {
+ "quota": 100,
+ "window": "60s"
+ }
+ }')
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.key_id')
+```
+
+
+
+
+The response includes the full key metadata with the `rate_limit_policy` attached. For the complete request and response field
+reference, see the [IssueAPIKey API reference](../reference/api/admin-issue-api-key.api.mdx).
+
+## Verify a rate-limited key
+
+Verify the key as you would any other credential. When the key has a rate limit policy, the response includes the policy metadata:
+
+
+
+
+```bash
+talos keys verify "$API_SECRET" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\":\"$API_SECRET\"}" | jq .
+```
+
+
+
+
+When rate limiting is enabled (Commercial), the response also includes `rate_limit_remaining` (approximate requests available
+before the limit is reached) and `rate_limit_reset_time` (when full capacity is recovered). For the complete response field
+reference, see the [VerifyAPIKey API reference](../reference/api/admin-verify-api-key.api.mdx).
+
+## Exceeding the limit
+
+When a key's quota is exhausted, verification returns `is_active: false` with error code `VERIFICATION_ERROR_RATE_LIMITED`
+(Commercial edition). The response body includes the error code and a human-readable message:
+
+```json
+{
+ "is_active": false,
+ "error_code": "VERIFICATION_ERROR_RATE_LIMITED",
+ "error_message": "Rate limit exceeded"
+}
+```
+
+The HTTP response also includes a `Retry-After` header indicating how many seconds the client should wait before retrying. In the
+OSS edition, enforcement is external -- Talos always returns the policy metadata but does not reject requests based on quota.
+
+For the complete list of verification error codes, see the
+[error codes reference](../reference/error-codes.md#verification-error-codes).
+
+## Update rate limit policy
+
+Use `PATCH` to change a key's rate limit policy without rotating the secret. Include `rate_limit_policy` in the `update_mask`:
+
+
+
+
+```bash
+talos keys issued update "$KEY_ID" \
+ --rate-limit-quota 500 \
+ --rate-limit-window "120s" \
+ -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X PATCH "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "rate_limit_policy": {
+ "quota": 500,
+ "window": "120s"
+ },
+ "update_mask": {"paths": ["rate_limit_policy"]}
+ }' | jq .
+```
+
+
+
+
+The updated policy takes effect on the next verification request (subject to cache TTL). For the complete update field reference,
+see the [UpdateIssuedAPIKey API reference](../reference/api/admin-update-issued-api-key.api.mdx).
+
+## Remove rate limit policy
+
+To remove a rate limit policy entirely, set `rate_limit_policy` to an empty object:
+
+
+
+
+```bash
+talos keys issued update "$KEY_ID" \
+ --rate-limit-quota 0 \
+ --rate-limit-window "0s" \
+ -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X PATCH "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "rate_limit_policy": {},
+ "update_mask": {"paths": ["rate_limit_policy"]}
+ }' | jq .
+```
+
+
+
+
+Once removed, the key is no longer subject to rate limiting.
+
+## HTTP response headers
+
+When a key has a rate limit policy, the HTTP gateway includes IETF draft-compliant headers in verification responses:
+
+| Header | When present | Description |
+| ------------------ | -------------------- | -------------------------------------------------- |
+| `RateLimit-Policy` | Always (with policy) | Declares the quota and window: `100;w=60` |
+| `RateLimit` | Always (with policy) | Current state: `limit=100, remaining=42, reset=18` |
+| `Retry-After` | Only when limited | Seconds to wait before the next allowed request |
+
+These headers are present in both editions. In the OSS edition, your API gateway can read them to apply enforcement. In the
+Commercial edition, clients can use them for backoff and retry logic.
+
+## Behavior notes
+
+- **Fail-open on limiter errors** -- if the rate limiter backend is unavailable (e.g., Redis is down), verification succeeds but
+ rate limit metadata is omitted. Limiter failures never block legitimate traffic.
+- **Cache interaction** -- rate limit checks happen after cache resolution. If a verification result is served from cache, the
+ rate limiter is not consulted. This means cached responses do not decrement the counter.
+- **Per-key isolation** -- each key maintains its own counter. Keys do not share rate limit budgets, even if they belong to the
+ same actor.
+- **Policy changes** -- updated policies take effect on the next cache miss. To force immediate effect, use the
+ `Cache-Control: no-cache` header on verification requests.
+
+## Next steps
+
+- [Rate limiting concepts](../concepts/rate-limiting.md) -- how enforcement works in OSS vs. Commercial
+- [Key lifecycle](./key-lifecycle.mdx) -- update, rotate, and revoke keys
+- [Error handling](./error-handling.mdx) -- error response format and retry logic
diff --git a/docs/talos/integrate/sdk/curl.md b/docs/talos/integrate/sdk/curl.md
new file mode 100644
index 000000000..6ab83e204
--- /dev/null
+++ b/docs/talos/integrate/sdk/curl.md
@@ -0,0 +1,264 @@
+---
+title: curl cheat sheet
+description: Every Talos API endpoint as a copy-paste curl command
+---
+
+# curl cheat sheet
+
+Replace `$TALOS_URL` with your Talos server address (e.g., `http://127.0.0.1:4420`).
+
+
+
+
+## Admin plane — Issued keys
+
+### Issue a key
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "my-service",
+ "actor_id": "user_123",
+ "scopes": ["read", "write"],
+ "ttl": "720h",
+ "metadata": {"team": "backend"}
+ }')
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+### Get a key
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" | jq .
+```
+
+### List keys
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/issuedApiKeys?page_size=50&actor_id=user_123&status=KEY_STATUS_ACTIVE" | jq .
+```
+
+### Update a key
+
+
+
+```bash
+curl -s -X PATCH "$TALOS_URL/v2alpha1/admin/issuedApiKeys/$KEY_ID" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "updated-name",
+ "scopes": ["read"],
+ "update_mask": {"paths": ["name", "scopes"]}
+ }' | jq .
+```
+
+### Rotate a key
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys/${KEY_ID}:rotate" \
+ -H "Content-Type: application/json" \
+ -d '{}')
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+```
+
+## Admin plane — Imported keys
+
+### Import a key
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/importedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "raw_key": "sk_live_abc123",
+ "name": "External key",
+ "actor_id": "user_123",
+ "scopes": ["read"]
+ }')
+
+echo "$RESPONSE" | jq .
+
+export IMPORTED_KEY_ID=$(echo "$RESPONSE" | jq -er '.imported_api_key.key_id')
+```
+
+### Batch import
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/importedApiKeys:batchImport" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "requests": [
+ {"raw_key": "key_1", "name": "Key 1", "actor_id": "user_1"},
+ {"raw_key": "key_2", "name": "Key 2", "actor_id": "user_2"}
+ ]
+ }' | jq .
+```
+
+### Get an imported key
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/importedApiKeys/$IMPORTED_KEY_ID" | jq .
+```
+
+### List imported keys
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/importedApiKeys?page_size=50&actor_id=user_123" | jq .
+```
+
+### Delete an imported key
+
+
+
+```bash
+curl -s -X DELETE "$TALOS_URL/v2alpha1/admin/importedApiKeys/$IMPORTED_KEY_ID" | jq .
+```
+
+## Admin plane — Token derivation
+
+### Derive a JWT token
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:derive" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"credential\": \"$API_SECRET\",
+ \"algorithm\": \"TOKEN_ALGORITHM_JWT\",
+ \"ttl\": \"1h\",
+ \"scopes\": [\"read\"],
+ \"custom_claims\": {\"role\": \"viewer\"}
+ }")
+
+echo "$RESPONSE" | jq .
+
+export JWT_TOKEN=$(echo "$RESPONSE" | jq -er '.token.token')
+```
+
+### Derive a macaroon token
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:derive" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"credential\": \"$API_SECRET\",
+ \"algorithm\": \"TOKEN_ALGORITHM_MACAROON\",
+ \"ttl\": \"30m\"
+ }" | jq .
+```
+
+### Get JWKS (public keys)
+
+
+
+```bash
+curl -s "$TALOS_URL/v2alpha1/admin/derivedKeys/jwks.json" | jq .
+```
+
+## Data plane
+
+### Verify a credential
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\":\"$API_SECRET\"}" | jq .
+```
+
+### Verify with cache bypass
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -H "Cache-Control: no-cache" \
+ -d "{\"credential\":\"$API_SECRET\"}" | jq .
+```
+
+### Batch verify
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:batchVerify" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"requests\": [
+ {\"credential\": \"$API_SECRET\"},
+ {\"credential\": \"$JWT_TOKEN\"}
+ ]
+ }" | jq .
+```
+
+## Revocation
+
+### Revoke a key (admin)
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys/${KEY_ID}:revoke" \
+ -H "Content-Type: application/json" \
+ -d '{"reason": "REVOCATION_REASON_KEY_COMPROMISE"}' | jq .
+```
+
+### Self-revoke a key
+
+
+
+```bash
+# Issue a fresh key for the self-revocation demo
+SELF_REVOKE_RESP=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{"name":"self-revoke-demo","actor_id":"user_123"}')
+
+SELF_REVOKE_SECRET=$(echo "$SELF_REVOKE_RESP" | jq -er '.secret')
+
+curl -s -X POST "$TALOS_URL/v2alpha1/apiKeys:selfRevoke" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"credential\": \"$SELF_REVOKE_SECRET\",
+ \"reason\": \"REVOCATION_REASON_KEY_COMPROMISE\"
+ }" | jq .
+```
+
+## Health checks
+
+
+
+```bash
+# Liveness
+curl -s "$TALOS_URL/health/alive" | jq .
+
+# Readiness
+curl -s "$TALOS_URL/health/ready" | jq .
+```
diff --git a/docs/talos/integrate/sdk/go.md b/docs/talos/integrate/sdk/go.md
new file mode 100644
index 000000000..830a0436a
--- /dev/null
+++ b/docs/talos/integrate/sdk/go.md
@@ -0,0 +1,225 @@
+---
+title: Go SDK
+description: Using the generated Go HTTP client
+---
+
+# Go SDK
+
+Talos provides a generated Go HTTP client based on the OpenAPI specification. The client is generated using `openapi-generator`
+and lives in the `internal/client/generated` package.
+
+:::note
+
+Internal package: the Go client is in an `internal/` package and cannot be imported by external Go modules. It is used for Talos's
+own integration tests and the admin UI backend. If you need a Go client for your application, generate one from the OpenAPI spec
+at `api/talos.openapi-v3.json` using [OpenAPI Generator](https://openapi-generator.tech/).
+
+:::
+
+
+
+
+## Generate your own client
+
+```bash
+openapi-generator generate \
+ -i api/talos.openapi-v3.json \
+ -g go \
+ -o generated/go-client
+```
+
+The examples below use the internal client's types for illustration. A generated external client has the same API shape.
+
+:::tip
+
+Full working example: see
+[`tools/doctest/examples/go_sdk/main.go`](https://github.com/ory-corp/talos/blob/dev/tools/doctest/examples/go_sdk/main.go) for a
+complete, runnable program that exercises all operations shown below.
+
+:::
+
+
+
+```bash
+go build -o .bin/doctest-go-sdk ./tools/doctest/examples/go_sdk
+./.bin/doctest-go-sdk
+```
+
+## Initialize the client
+
+
+
+```go
+cfg := client.NewConfiguration()
+cfg.Servers = client.ServerConfigurations{
+ {URL: talosURL},
+}
+c := client.NewAPIClient(cfg)
+```
+
+## Issue an API key
+
+
+
+```go
+issueResp, _, err := c.StaticCredentialsAPI.
+ AdminIssueAPIKey(ctx).
+ V2alpha1IssueAPIKeyRequest(client.V2alpha1IssueAPIKeyRequest{
+ Name: new("my-service"),
+ ActorId: new("user_123"),
+ Scopes: []string{"read", "write"},
+ Ttl: new("720h"),
+ }).
+ Execute()
+if err != nil {
+ return fmt.Errorf("issue key: %w", err)
+}
+
+// Secret is only available at creation time
+issuedKey := issueResp.GetIssuedApiKey()
+fmt.Println("Key ID:", issuedKey.GetKeyId())
+fmt.Println("Secret:", issueResp.GetSecret())
+```
+
+## Verify a credential
+
+
+
+```go
+verifyResp, _, err := c.StaticCredentialsAPI.
+ AdminVerifyAPIKey(ctx).
+ V2alpha1VerifyAPIKeyRequest(client.V2alpha1VerifyAPIKeyRequest{
+ Credential: new(secret),
+ }).
+ Execute()
+if err != nil {
+ return fmt.Errorf("verify key: %w", err)
+}
+
+if verifyResp.GetIsActive() {
+ fmt.Println("Key is valid, owner:", verifyResp.GetActorId())
+} else {
+ fmt.Println("Key is invalid:", verifyResp.GetErrorMessage())
+}
+```
+
+## Batch verify
+
+
+
+```go
+batchResp, _, err := c.StaticCredentialsAPI.
+ AdminBatchVerifyAPIKeys(ctx).
+ V2alpha1BatchVerifyAPIKeysRequest(client.V2alpha1BatchVerifyAPIKeysRequest{
+ Requests: []client.V2alpha1VerifyAPIKeyRequest{
+ {Credential: new(secret)},
+ {Credential: new("invalid-key-for-testing")},
+ },
+ }).
+ Execute()
+if err != nil {
+ return fmt.Errorf("batch verify: %w", err)
+}
+
+for i, result := range batchResp.GetResults() {
+ fmt.Printf("Key %d: is_active=%v\n", i, result.GetIsActive())
+}
+```
+
+## Revoke a key
+
+Enum fields use typed constants, not raw strings:
+
+
+
+```go
+reason := client.V2ALPHA1REVOCATIONREASON_REVOCATION_REASON_KEY_COMPROMISE
+_, _, err = c.StaticCredentialsAPI.
+ AdminRevokeAPIKey(ctx, keyID).
+ StaticCredentialsAdminRevokeAPIKeyBody(client.StaticCredentialsAdminRevokeAPIKeyBody{
+ Reason: &reason,
+ }).
+ Execute()
+if err != nil {
+ return fmt.Errorf("revoke key: %w", err)
+}
+fmt.Println("Key revoked successfully")
+```
+
+## Derive a JWT token
+
+
+
+```go
+algorithm := client.V2ALPHA1TOKENALGORITHM_TOKEN_ALGORITHM_JWT
+deriveResp, _, err := c.StaticCredentialsAPI.
+ AdminDeriveToken(ctx).
+ V2alpha1DeriveTokenRequest(client.V2alpha1DeriveTokenRequest{
+ Credential: new(secret),
+ Algorithm: &algorithm,
+ Ttl: new("1h"),
+ Scopes: []string{"read"},
+ }).
+ Execute()
+if err != nil {
+ return fmt.Errorf("derive token: %w", err)
+}
+
+derivedToken := deriveResp.GetToken()
+fmt.Println("JWT:", derivedToken.GetToken())
+```
+
+## Error handling
+
+The SDK returns an error for every non-2xx response. The error wraps a
+[`google.rpc.Status`](https://cloud.google.com/apis/design/errors#error_model) body — read it via the typed `GenericOpenAPIError`,
+not the HTTP response, so you get the canonical gRPC code, human-readable message, and any `ErrorInfo` details.
+
+
+
+```go
+_, httpResp, err := c.StaticCredentialsAPI.
+ AdminGetIssuedAPIKey(ctx, "nonexistent-id").
+ Execute()
+if err != nil {
+ var apiErr *client.GenericOpenAPIError
+ if errors.As(err, &apiErr) {
+ var status struct {
+ Code int32 `json:"code"`
+ Message string `json:"message"`
+ Details []struct {
+ Type string `json:"@type"`
+ Reason string `json:"reason"`
+ Domain string `json:"domain"`
+ Metadata map[string]string `json:"metadata"`
+ } `json:"details"`
+ }
+ if jsonErr := json.Unmarshal(apiErr.Body(), &status); jsonErr == nil {
+ fmt.Println("gRPC code:", status.Code) // 5 = NOT_FOUND
+ fmt.Println("HTTP status:", httpResp.StatusCode) // 404
+ fmt.Println("Message:", status.Message)
+ for _, d := range status.Details {
+ if strings.HasSuffix(d.Type, "ErrorInfo") {
+ fmt.Println("Reason:", d.Reason) // Stable; switch on this
+ }
+ }
+ }
+ }
+}
+```
+
+Match on `details[*].reason` from the `ErrorInfo` detail — it is the stable, machine-readable identifier. The `message` field is
+meant for logs and can change between releases.
+
+For the verify endpoint, a verification failure returns `200 OK` with `is_active: false`, not an HTTP error. Branch on
+`verifyResp.GetIsActive()` and inspect `verifyResp.GetErrorCode()` instead of treating it as an SDK error.
+
+## Regenerating the client
+
+The Go SDK is regenerated with:
+
+```bash
+make generate-sdk
+```
+
+This reads the OpenAPI spec from `api/talos.openapi-v3.json` and outputs to `internal/client/generated/`.
diff --git a/docs/talos/integrate/self-revocation.mdx b/docs/talos/integrate/self-revocation.mdx
new file mode 100644
index 000000000..495750ed1
--- /dev/null
+++ b/docs/talos/integrate/self-revocation.mdx
@@ -0,0 +1,148 @@
+---
+title: Self-revocation
+description: Allow API key holders to revoke their own keys
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Self-revocation
+
+The self-revoke endpoint lets an API key holder revoke their own key by proving possession of the secret. This is a data plane
+operation — it does not require admin access.
+
+## Prerequisites
+
+A running Talos server. See the [quickstart](../quickstart/index.mdx) to start one locally.
+
+
+
+
+## When to use self-revocation
+
+- **Key compromise** — a user discovers their key was leaked and wants to revoke it immediately.
+- **User-initiated cleanup** — a user decommissions an integration and revokes unused keys.
+- **Security automation** — an automated system detects anomalous usage and revokes the key.
+
+## Self-revoke a key
+
+First, issue a key to get a secret:
+
+
+
+
+
+
+```bash
+export SELF_REVOKE_SECRET=$(talos keys issue "self-revoke-demo" \
+ --actor user_99 \
+ --scopes "read:data" \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null | jq -er '.secret')
+```
+
+
+
+
+```bash
+ISSUE_RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "self-revoke-demo",
+ "actor_id": "user_99",
+ "scopes": ["read:data"]
+ }')
+
+export SELF_REVOKE_SECRET=$(echo "$ISSUE_RESPONSE" | jq -er '.secret')
+```
+
+
+
+
+Send the full key secret as proof of possession:
+
+
+
+
+
+
+```bash
+talos keys self-revoke "$SELF_REVOKE_SECRET" \
+ --reason key_compromise \
+ -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/apiKeys:selfRevoke" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"credential\": \"$SELF_REVOKE_SECRET\",
+ \"reason\": \"REVOCATION_REASON_KEY_COMPROMISE\"
+ }"
+echo ""
+echo "Key self-revoked"
+```
+
+
+
+
+Verify the key is no longer active:
+
+
+
+
+
+
+```bash
+talos keys verify "$SELF_REVOKE_SECRET" --no-cache -e "$TALOS_URL" || true
+echo "Self-revocation confirmed"
+```
+
+
+
+
+```bash
+VERIFY_RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -H "Cache-Control: no-cache" \
+ -d "{\"credential\":\"$SELF_REVOKE_SECRET\"}")
+
+echo "$VERIFY_RESPONSE" | jq .
+
+if echo "$VERIFY_RESPONSE" | jq -e '.is_active == false' > /dev/null 2>&1; then
+ echo "Self-revocation confirmed"
+else
+ echo "ERROR: Key should have been revoked"
+ exit 1
+fi
+```
+
+
+
+
+The request requires `credential` (the full API key secret) and optionally `reason` (revocation reason enum). For the complete
+field reference, see the [SelfRevokeAPIKey API reference](../reference/api/revoke-api-key.api.mdx).
+
+Only issued and imported API keys can be self-revoked. Derived tokens (JWTs and macaroons) are stateless and cannot be revoked.
+All revocation reasons except `REVOCATION_REASON_PRIVILEGE_WITHDRAWN` are allowed — that reason is reserved for admin-initiated
+revocations.
+
+A successful self-revocation returns an empty response with HTTP status `200 OK`. The key is immediately revoked.
+
+## Admin vs self-revocation
+
+| | Admin revocation | Self-revocation |
+| --------------------- | ---------------------------------------------- | ----------------------------------- |
+| Endpoint | `POST /v2alpha1/admin/apiKeys/{key_id}:revoke` | `POST /v2alpha1/apiKeys:selfRevoke` |
+| Plane | Admin | Data |
+| Authentication | Requires admin access | Proof of possession (key secret) |
+| Identifier | Key ID | Key secret |
+| `PRIVILEGE_WITHDRAWN` | Allowed | Not allowed |
+
+## Next steps
+
+- [Key lifecycle](key-lifecycle.mdx) — admin-side key management
+- [Error handling](error-handling.mdx) — handle revocation errors
diff --git a/docs/talos/operate/benchmarks.md b/docs/talos/operate/benchmarks.md
new file mode 100644
index 000000000..ed8ee014c
--- /dev/null
+++ b/docs/talos/operate/benchmarks.md
@@ -0,0 +1,133 @@
+---
+title: Benchmarks
+description: Performance benchmarks and load testing for Ory Talos
+---
+
+# Benchmarks
+
+Talos includes a k6-based load test suite that measures throughput, latency, and correctness under concurrent load. Use these
+benchmarks to validate your deployment and catch performance regressions.
+
+:::note
+
+These benchmarks require the **Commercial edition** with PostgreSQL (or CockroachDB/MySQL). The OSS edition uses SQLite, which
+does not support concurrent writers and cannot handle the parallel load generated by multi-VU test profiles.
+
+:::
+
+## Reference results
+
+Measured on Apple M-series (M4 Pro Max), single-process commercial binary with PostgreSQL 16, stress profile (ramping 0→437 VUs
+over 5 minutes):
+
+| Metric | Value |
+| ------------------- | ------------ |
+| Total requests | ~5,000,000 |
+| Peak throughput | 16,766 req/s |
+| Overall p99 latency | 123ms |
+| Verify p95 latency | 48ms |
+| Verify p99 latency | 95ms |
+| Error rate | 0.00% |
+| Peak VUs | 437 |
+| Key creations | 493/s |
+| Verifications | 3,797/s |
+| Token derivations | 3,797/s |
+
+## Profiles
+
+The test suite provides three profiles selected via the `TEST_PROFILE` environment variable:
+
+| Profile | VUs | Duration | Executor | Purpose |
+| -------- | ----------------- | -------- | ------------ | ---------------------------------------------- |
+| `smoke` | 1 read + 1 write | 15s | constant-vus | Quick validation after changes |
+| `load` | 15 read + 5 write | 2min | constant-vus | Sustained load for regression detection |
+| `stress` | 0→437 ramping | 5min | ramping-vus | Find breaking points and measure peak capacity |
+
+The stress profile ramps through four stages:
+
+1. **Warm-up**: 0→25 VUs over 30s
+2. **Ramp 1**: 25→75 VUs over 60s
+3. **Ramp 2**: 75→150 VUs over 60s
+4. **Hold**: 150 VUs for 120s
+5. **Ramp down**: 150→0 VUs over 30s
+
+Read scenarios (verify, batch verify, get key, list keys, JWKS, derive token) get ~70% of VUs. Write scenarios (create, rotate,
+revoke, import, update, self-revoke) get ~30%.
+
+## Running benchmarks
+
+### Prerequisites
+
+- [k6](https://k6.io/docs/get-started/installation/) load testing tool
+- Docker (for local PostgreSQL) or an existing PostgreSQL instance
+- Go toolchain (to build the binary)
+
+### Quick start
+
+```bash
+# Smoke test (quick validation)
+TEST_PROFILE=smoke bash test/load/run.sh
+
+# Load test (sustained)
+TEST_PROFILE=load bash test/load/run.sh
+
+# Stress test (peak capacity)
+TEST_PROFILE=stress bash test/load/run.sh
+```
+
+The `run.sh` script handles everything: builds the commercial binary, starts PostgreSQL in Docker, runs migrations, seeds tenant
+data, starts the server, and executes k6.
+
+### Using an existing database
+
+```bash
+SKIP_DOCKER=true DB_DSN="postgres://user:pass@host:5432/db?sslmode=disable" \
+ TEST_PROFILE=load bash test/load/run.sh
+```
+
+### Environment variables
+
+| Variable | Default | Description |
+| -------------- | ------------------------------------------------------------------ | ---------------------------------------------- |
+| `TEST_PROFILE` | `smoke` | Test profile: `smoke`, `load`, or `stress` |
+| `BASE_URL` | `http://localhost:4420` | Server base URL |
+| `AUTH_TOKEN` | `test-token` | Bearer token for admin endpoints |
+| `DB_DSN` | `postgres://talos:talos@localhost:5432/talos_test?sslmode=disable` | PostgreSQL connection string |
+| `SKIP_DOCKER` | `false` | Skip Docker PostgreSQL setup (use existing DB) |
+
+## Thresholds
+
+Each profile enforces regression thresholds. Tests fail if any threshold is breached.
+
+### Smoke and load profiles
+
+| Metric | Threshold | Rationale |
+| ----------- | --------- | --------------------------------------- |
+| All checks | 100% pass | Zero tolerance for correctness failures |
+| HTTP errors | 0% | No errors allowed at low concurrency |
+| Overall p99 | < 500ms | Generous headroom for CI runners |
+| Verify p95 | < 50ms | ~25ms measured in CI (postgres) |
+| Verify p99 | < 100ms | Allows for CI variance |
+
+### Stress profile
+
+| Metric | Threshold | Rationale |
+| ----------- | --------- | ------------------------------------- |
+| All checks | 100% pass | Correctness under load |
+| HTTP errors | < 1% | Small tolerance for stress conditions |
+| Overall p99 | < 400ms | ~3x headroom over measured 123ms |
+| Verify p95 | < 100ms | ~2x headroom over measured 48ms |
+| Verify p99 | < 200ms | ~2x headroom over measured 95ms |
+
+## Interpreting results
+
+After a k6 run, look for:
+
+- **`checks` rate**: Must be 100%. Any failure indicates a correctness bug.
+- **`http_req_duration` percentiles**: Compare against the thresholds above. Significant increases suggest a regression.
+- **`http_req_failed` rate**: Should be 0% for smoke/load. Under 1% for stress.
+- **Custom counters** (`key_creations`, `verifications`, `token_derivations`): Compare rates against the reference results to
+ detect throughput regressions.
+- **`iteration_duration`**: End-to-end time for each VU iteration including all operations.
+
+Results are saved to `.test/k6-output.txt` (human-readable) and `.test/k6-results.json` (machine-readable).
diff --git a/docs/talos/operate/cache/index.md b/docs/talos/operate/cache/index.md
new file mode 100644
index 000000000..10760e254
--- /dev/null
+++ b/docs/talos/operate/cache/index.md
@@ -0,0 +1,31 @@
+---
+title: Cache
+---
+
+# Cache
+
+Talos can cache verification results to reduce database load and improve latency.
+
+## Backends
+
+| Backend | Edition | Shared | Description |
+| ------------------- | ---------- | ------ | ----------------------------- |
+| `noop` | OSS | N/A | No caching (default) |
+| [Memory](memory.md) | Commercial | No | Per-process LRU cache |
+| [Redis](redis.md) | Commercial | Yes | Shared cache across instances |
+
+## Configuration
+
+```yaml
+cache:
+ type: "memory" # "noop", "memory", or "redis"
+ ttl: "5m" # Cache entry lifetime
+```
+
+## Consistency
+
+Caching introduces eventual consistency. A revoked key may continue to pass verification until the cache entry expires (default: 5
+minutes).
+
+**Bypass cache:** Use `Cache-Control: no-cache` on verification requests to bypass the cache for individual requests when
+immediate consistency is required.
diff --git a/docs/talos/operate/cache/memory.md b/docs/talos/operate/cache/memory.md
new file mode 100644
index 000000000..1fba0276b
--- /dev/null
+++ b/docs/talos/operate/cache/memory.md
@@ -0,0 +1,33 @@
+---
+title: In-memory cache
+tags: [commercial]
+sidebar_custom_props:
+ badge: Commercial
+---
+
+# In-memory cache
+
+The in-memory cache stores verification results in the Talos process using a ristretto-based LRU cache.
+
+## Configuration
+
+```yaml
+cache:
+ type: "memory"
+ ttl: "5m"
+ memory:
+ max_size: 104857600 # 100MB
+ num_counters: 10000 # Frequency estimation counters
+```
+
+## Characteristics
+
+- **Per-process**: Each Talos instance has its own cache. Not shared across instances.
+- **LRU eviction**: Least-recently-used entries are evicted when the cache reaches `max_size`.
+- **TTL-based expiry**: Entries expire after the configured `ttl`.
+- **Zero network overhead**: No external dependencies.
+
+## When to use
+
+Use the in-memory cache for single-node deployments or when each Talos instance handles enough traffic to benefit from local
+caching. For multi-instance deployments, consider [Redis](redis.md) for shared cache across all instances.
diff --git a/docs/talos/operate/cache/redis.md b/docs/talos/operate/cache/redis.md
new file mode 100644
index 000000000..7f9d7b26f
--- /dev/null
+++ b/docs/talos/operate/cache/redis.md
@@ -0,0 +1,90 @@
+---
+title: Redis cache
+tags: [commercial]
+sidebar_custom_props:
+ badge: Commercial
+---
+
+# Redis cache
+
+Redis provides a shared cache across all Talos instances.
+
+## Configuration
+
+```yaml
+cache:
+ type: "redis"
+ ttl: "5m"
+ redis:
+ addrs: ["redis-0:6379", "redis-1:6379", "redis-2:6379"]
+ password: "secret"
+ db: 0
+ pool_size: 100
+ min_idle_conns: 2
+ conn_max_idle_time: "5m"
+ conn_max_lifetime: "30m"
+ timeout: "3s"
+ tls:
+ enabled: true
+```
+
+## Parameters
+
+| Parameter | Default | Range / format | Description |
+| -------------------- | -------------------- | ------------------------------- | ------------------------------------------------------------------------------- |
+| `addrs` | `["localhost:6379"]` | One or more `host:port` entries | Redis server addresses. Multiple entries enable cluster or sentinel topologies. |
+| `password` | — | Any string | Redis password. Leave empty for unauthenticated Redis. |
+| `db` | `0` | `0`–`15` | Logical Redis database. Cluster mode only supports `0`. |
+| `pool_size` | `100` | `1`–`1000` | Maximum number of connections per address. |
+| `min_idle_conns` | `2` | `≥ 0` | Minimum idle connections kept open per address. Reduces cold-start latency. |
+| `conn_max_idle_time` | `5m` | Go duration string | Maximum time a connection can sit idle before being closed. |
+| `conn_max_lifetime` | `30m` | Go duration string | Maximum time a connection can be reused before being recycled. |
+| `timeout` | `3s` | Go duration string | Timeout for individual Redis operations (`GET`, `SET`, etc.). |
+| `tls.enabled` | `false` | Boolean | Enable TLS using the system certificate pool. Required for TLS-only Redis. |
+
+All Redis parameters are immutable: changing them requires a server restart. Only `pool_size` and `timeout` can be tuned without
+restart.
+
+## Cluster and sentinel topologies
+
+Pass every node in `addrs`. The client auto-detects the topology:
+
+```yaml
+# Redis Cluster (3+ nodes)
+addrs:
+ - "redis-cluster-0.svc:6379"
+ - "redis-cluster-1.svc:6379"
+ - "redis-cluster-2.svc:6379"
+
+# Redis Sentinel (3+ sentinels)
+addrs:
+ - "sentinel-0.svc:26379"
+ - "sentinel-1.svc:26379"
+ - "sentinel-2.svc:26379"
+```
+
+In cluster mode, `db` must be `0` — Redis Cluster does not support multiple logical databases.
+
+## TLS
+
+Set `tls.enabled: true` when the Redis endpoint terminates TLS. Talos uses the operating system's certificate pool to verify the
+server certificate. Self-signed or private CA deployments must add the CA to the OS trust store on every Talos node — there is no
+per-process CA bundle option.
+
+## Connection pool sizing
+
+The defaults (`pool_size: 100`, `min_idle_conns: 2`, `conn_max_lifetime: 30m`) suit most deployments. Tune them only when you can
+show a problem:
+
+- **Saturated pool:** if `redis_pool_wait_seconds` (when exposed by your client metrics) is consistently non-zero, increase
+ `pool_size`.
+- **Connection churn:** if Redis logs show frequent connect/disconnect from Talos, increase `min_idle_conns`.
+- **Stale connections after failover:** lower `conn_max_lifetime` to force quicker rotation.
+
+Do not set `pool_size` above your Redis server's `maxclients` divided by the number of Talos instances — running out of Redis
+connections fails open with a cache miss but spams logs.
+
+## When to use
+
+Use Redis when running multiple Talos instances. A cache hit on one instance benefits all instances, reducing database load. Redis
+is also required for [edge proxy](../deploy/edge-proxy.md) deployments where each edge node shares a regional Redis instance.
diff --git a/docs/talos/operate/configure.md b/docs/talos/operate/configure.md
new file mode 100644
index 000000000..b5a877cb3
--- /dev/null
+++ b/docs/talos/operate/configure.md
@@ -0,0 +1,130 @@
+---
+title: Configure
+description: Configuration reference for Ory Talos
+---
+
+# Configure
+
+Talos is configured through a YAML file passed via the `--config` flag. All settings can also be set through environment variables
+or CLI flags. See the [Configuration reference](../reference/config.mdx) for the complete list of keys, types, defaults,
+environment variable mappings, and precedence rules.
+
+## Hot-reload
+
+Talos watches the config file for changes. Some settings reload automatically, others require a restart.
+
+**Hot-reloadable:**
+
+- `credentials.api_keys.default_ttl` / `max_ttl`
+- `credentials.api_keys.prefix.current` / `retired`
+- `credentials.derived_tokens.default_ttl`
+- `credentials.derived_tokens.macaroon.prefix.current` / `retired`
+- `rate_limit.enabled`
+
+**Requires restart** (marked with `x-immutable` in the schema):
+
+- `serve.http.host` / `port`
+- `serve.metrics.host` / `port` (Commercial only)
+- `db.dsn`
+- `cache.type` and all cache settings
+- `rate_limit.backend`
+- `log.level` / `format`
+- `tracing.*` (Commercial only)
+
+## Duration syntax
+
+All duration values (TTLs, timeouts, intervals) are Go duration strings. Combine one or more unsigned numbers with a unit, no
+spaces. Supported units:
+
+| Unit | Meaning |
+| ---- | ------------ |
+| `ns` | nanoseconds |
+| `us` | microseconds |
+| `µs` | microseconds |
+| `ms` | milliseconds |
+| `s` | seconds |
+| `m` | minutes |
+| `h` | hours |
+
+Examples: `500ms`, `30s`, `5m`, `1h30m`, `8760h` (one year). Days, weeks, months, and years are **not** supported — express them
+in hours (`24h`, `168h`, `8760h`).
+
+## Minimal configuration
+
+```yaml
+credentials:
+ issuer: "https://api.example.com"
+secrets:
+ default:
+ current: "a-32-byte-or-longer-secret-here!"
+db:
+ dsn: "sqlite:///var/lib/talos/data.db"
+```
+
+## Production configuration
+
+```yaml
+serve:
+ http:
+ host: "0.0.0.0"
+ port: 4420
+ cors:
+ enabled: true
+ allowed_origins: ["https://app.example.com"]
+ request_log:
+ exclude_health_endpoints: true
+ metrics: # Commercial only
+ host: "0.0.0.0"
+ port: 4422
+
+credentials:
+ issuer: "https://api.example.com"
+ api_keys:
+ default_ttl: "2160h" # 90 days
+ max_ttl: "8760h" # 1 year
+ prefix:
+ current: "talos"
+ derived_tokens:
+ jwt:
+ signing_key_id: "" # Optional JWKS kid hint; defaults to the first usable signing key
+ default_ttl: "1h"
+ signing_keys:
+ # Talos requires base64-encoded JWKS. To produce the value below, run:
+ # base64 < /etc/talos/jwks.json | tr -d '\n'
+ urls:
+ - "base64://eyJrZXlzIjpbXX0="
+
+db:
+ dsn: "postgres://talos:secret@db:5432/talos?max_conns=25&max_conn_lifetime=5m"
+
+cache:
+ type: "redis" # Commercial only
+ ttl: "5m"
+ redis:
+ addrs: ["redis:6379"]
+ password: "secret"
+ pool_size: 100
+ timeout: "3s"
+
+rate_limit: # Commercial only
+ enabled: true
+ backend: redis # "memory" for single-pod, "redis" for multi-pod
+
+secrets:
+ default:
+ current: "a-32-byte-or-longer-secret-here!"
+
+log:
+ level: "info"
+ format: "json"
+
+tracing: # Commercial only
+ enabled: true
+ service_name: "talos"
+ exporter: "otlp"
+ endpoint: "jaeger:4317"
+ sample_rate: 0.01
+```
+
+See the [Configuration reference](../reference/config.mdx) for all available keys with types, defaults, and environment variable
+mappings.
diff --git a/docs/talos/operate/database/cockroachdb.md b/docs/talos/operate/database/cockroachdb.md
new file mode 100644
index 000000000..9b93f1235
--- /dev/null
+++ b/docs/talos/operate/database/cockroachdb.md
@@ -0,0 +1,104 @@
+---
+title: CockroachDB
+tags: [commercial]
+sidebar_custom_props:
+ badge: Commercial
+---
+
+# CockroachDB
+
+CockroachDB provides distributed SQL with automatic sharding and multi-region replication.
+
+## Supported versions
+
+CockroachDB 23.1 and later.
+
+## Configuration
+
+```yaml
+db:
+ dsn: "cockroach://talos@crdb:26257/talos?sslmode=verify-full&max_conns=50"
+```
+
+Or via environment variable:
+
+```bash
+export TALOS_DB_DSN="cockroach://talos@crdb:26257/talos?sslmode=verify-full&max_conns=50"
+```
+
+## DSN format
+
+```
+cockroach://user:password@host:port/dbname?param=value¶m=value
+```
+
+Both `cockroach://` and `cockroachdb://` schemes are accepted. Internally, the scheme is converted to `postgres://` since
+CockroachDB uses the PostgreSQL wire protocol.
+
+## DSN parameters, connection pooling, and TLS
+
+CockroachDB uses the PostgreSQL `pgx` driver and shares the same pooling infrastructure, including both standard and advanced pool
+modes. For the full parameter reference, see the [PostgreSQL DSN parameters](postgresql.md#dsn-parameters),
+[connection pooling](postgresql.md#connection-pooling), and [TLS / SSL](postgresql.md#tls--ssl) documentation.
+
+Key differences from PostgreSQL:
+
+- **Higher pool sizes** — CockroachDB connections are lighter. Start with `max_conns=50` instead of `25`.
+- **Per-node connection limits still apply** — each CockroachDB node enforces its own
+ `sql.defaults.idle_in_transaction_session_timeout` and accepts a finite number of connections. Aim for the sum of every Talos
+ pool that targets a node to stay below that node's limit. You rarely need PgBouncer in front of CockroachDB, but the limit is
+ per-node, not global.
+- **Schema-change blast radius** — CockroachDB applies online schema changes asynchronously. Always run `talos migrate up` from a
+ single instance, then wait for the schema-change job to finish (`SHOW JOBS WHEN status = 'running'`) before starting a rolling
+ deploy of the new application version.
+- **Rollback path** — `talos migrate down` is supported but irreversible if the previous version has already written data using
+ the new schema. For destructive migrations, take a backup (`BACKUP INTO …`) before applying.
+
+## Migrations
+
+```bash
+talos-commercial migrate up --database "cockroach://talos@crdb:26257/talos"
+```
+
+## Multi-region
+
+Deploy Talos data plane nodes in each region alongside CockroachDB nodes to minimize verification latency. Talos does not require
+special configuration beyond pointing `db.dsn` at the local CockroachDB node.
+
+```yaml
+# Region: us-east-1
+db:
+ dsn: "cockroach://talos@crdb-us-east:26257/talos?sslmode=verify-full&max_conns=50"
+
+# Region: eu-west-1
+db:
+ dsn: "cockroach://talos@crdb-eu-west:26257/talos?sslmode=verify-full&max_conns=50"
+```
+
+## Performance
+
+CockroachDB has higher write latency than PostgreSQL due to distributed consensus (Raft). For verification-heavy workloads:
+
+- Enable [caching](../cache/index.md) to absorb verification reads
+- Use `max_conns=50` or higher — CockroachDB connections are lighter than PostgreSQL
+- Place Talos data plane nodes in the same region as CockroachDB nodes
+
+## Example DSNs
+
+**Development (CockroachDB Serverless):**
+
+```
+cockroach://talos:secret@free-tier.cockroachlabs.cloud:26257/talos?sslmode=require
+```
+
+**Production with standard pooling:**
+
+```
+cockroach://talos@crdb:26257/talos?sslmode=verify-full&sslrootcert=/certs/ca.crt&max_conns=50&max_idle_conns=10&max_conn_lifetime=5m&max_conn_idle_time=1m
+```
+
+**Production with advanced pooling (multi-region):**
+
+```
+cockroach://talos@crdb-local:26257/talos?sslmode=verify-full&sslrootcert=/certs/ca.crt&pool_mode=advanced
+```
diff --git a/docs/talos/operate/database/index.md b/docs/talos/operate/database/index.md
new file mode 100644
index 000000000..9c520783f
--- /dev/null
+++ b/docs/talos/operate/database/index.md
@@ -0,0 +1,29 @@
+---
+title: Database
+---
+
+# Database
+
+Talos stores API key data in a relational database. The backend is determined by the DSN scheme in `db.dsn`.
+
+## Supported backends
+
+| Backend | Edition | DSN scheme | Use case |
+| ----------------------------- | ---------- | -------------- | ------------------------------------ |
+| [SQLite](sqlite.md) | OSS | `sqlite://` | Development, single-node |
+| [PostgreSQL](postgresql.md) | Commercial | `postgres://` | Recommended production |
+| [MySQL](mysql.md) | Commercial | `mysql://` | Production with MySQL infrastructure |
+| [CockroachDB](cockroachdb.md) | Commercial | `cockroach://` | Multi-region, distributed |
+
+## Configuration
+
+```yaml
+db:
+ dsn: "sqlite:///var/lib/talos/data.db"
+```
+
+The `db.dsn` setting requires a server restart to take effect.
+
+## Migrations
+
+Run `talos migrate up` before first use and after each upgrade. See [Migrations](migrations.md).
diff --git a/docs/talos/operate/database/migrations.md b/docs/talos/operate/database/migrations.md
new file mode 100644
index 000000000..2654ef713
--- /dev/null
+++ b/docs/talos/operate/database/migrations.md
@@ -0,0 +1,93 @@
+---
+title: Migrations
+---
+
+# Migrations
+
+Talos includes built-in database migrations. Run them before first use and after each upgrade.
+
+## Commands
+
+```bash
+# Apply all pending migrations
+talos migrate up --database "sqlite:///var/lib/talos/data.db"
+
+# Roll back the last migration (--steps defaults to 1)
+talos migrate down --database "sqlite:///var/lib/talos/data.db"
+
+# Roll back the last three migrations
+talos migrate down --steps 3 --database "sqlite:///var/lib/talos/data.db"
+
+# Check migration status
+talos migrate status --database "sqlite:///var/lib/talos/data.db"
+
+# Force a specific version after a partial migration left the schema dirty
+talos migrate force 17 --database "sqlite:///var/lib/talos/data.db"
+```
+
+## Upgrade workflow
+
+1. **Back up the database.** For PostgreSQL or CockroachDB, take a logical backup with `pg_dump` or `BACKUP INTO`; for MySQL, use
+ `mysqldump`. SQLite users can simply copy the file.
+2. **Drain admin traffic.** Run `talos migrate up` from a single instance — concurrent migration runners race against each other
+ and can leave the schema dirty.
+3. **Apply migrations.** Run `talos migrate up`. Watch stderr; the command exits non-zero on failure.
+4. **Resolve dirty state if needed.** If migration fails partway through, `migrate up` and `migrate down` will refuse to run with
+ `Error: Database is in dirty state at version N`. Inspect the schema, complete or revert the partial change manually, then run
+ `talos migrate force ` to mark the migration tracker. Never rerun on top of a dirty state.
+5. **Verify with `talos migrate status`.** Confirm the version matches the new binary's expected schema and that `STATUS` reports
+ `OK`, not `DIRTY`.
+6. **Roll the application.** Start replicas of the new binary in a rolling deploy. Old replicas continue serving against the new
+ schema until they are replaced.
+
+## Production safety
+
+- Run `talos migrate up` from a Job, init container, or operator — never from inside the application's startup path. Concurrent
+ migration runners can deadlock or corrupt the migration tracker.
+- Pin the migration image to the same version as the application image. Do not use mutable tags (`latest`, `staging`) for
+ migration jobs.
+- Talos commercial migrations live under `commercial/persistence/migrations/{postgres,mysql,cockroach}/`; the OSS image only ships
+ SQLite migrations and cannot apply them. Use the `oryd/talos-commercial` image for PostgreSQL, MySQL, and CockroachDB.
+
+## DSN examples
+
+```bash
+# SQLite (OSS)
+talos migrate up --database "sqlite:///var/lib/talos/data.db"
+
+# PostgreSQL (Commercial)
+talos-commercial migrate up --database "postgres://talos:secret@db:5432/talos"
+
+# MySQL (Commercial)
+talos-commercial migrate up --database "mysql://talos:secret@tcp(db:3306)/talos?parseTime=true"
+
+# CockroachDB (Commercial)
+talos-commercial migrate up --database "cockroach://talos@crdb:26257/talos"
+```
+
+## Kubernetes
+
+Use a Job to apply migrations once, then start the application Deployment. The OSS image (`oryd/talos:latest`) only ships SQLite
+migrations; for PostgreSQL, MySQL, or CockroachDB use `oryd/talos-commercial:latest`.
+
+```yaml
+apiVersion: batch/v1
+kind: Job
+metadata:
+ name: talos-migrate
+spec:
+ backoffLimit: 0 # Do not retry — a failed migration leaves the schema dirty.
+ template:
+ spec:
+ containers:
+ - name: migrate
+ image: oryd/talos-commercial:latest # Pin to the same tag as the application image.
+ command: ["talos", "migrate", "up"]
+ env:
+ - name: TALOS_DB_DSN
+ valueFrom:
+ secretKeyRef:
+ name: talos-secrets
+ key: dsn
+ restartPolicy: Never
+```
diff --git a/docs/talos/operate/database/mysql.md b/docs/talos/operate/database/mysql.md
new file mode 100644
index 000000000..561cb3930
--- /dev/null
+++ b/docs/talos/operate/database/mysql.md
@@ -0,0 +1,158 @@
+---
+title: MySQL
+tags: [commercial]
+sidebar_custom_props:
+ badge: Commercial
+---
+
+# MySQL
+
+MySQL is supported as a production database in the Commercial edition.
+
+## Supported versions
+
+MySQL 8.0 and later.
+
+## Configuration
+
+```yaml
+db:
+ dsn: "mysql://talos:secret@tcp(db:3306)/talos?tls=true&parseTime=true"
+```
+
+Or via environment variable:
+
+```bash
+export TALOS_DB_DSN="mysql://talos:secret@tcp(db:3306)/talos?tls=true&parseTime=true"
+```
+
+## DSN format
+
+```
+mysql://user:password@tcp(host:port)/dbname?param=value¶m=value
+```
+
+The `mysql://` scheme prefix is required in the configuration. Talos strips it internally before passing the DSN to the Go MySQL
+driver.
+
+:::caution
+
+Required parameter: always include `parseTime=true` in the DSN. Without it, datetime columns are returned as byte arrays instead
+of `time.Time`, causing runtime errors.
+
+:::
+
+## DSN parameters
+
+### Connection pool parameters
+
+Pool parameters are parsed from the DSN query string and removed before the DSN is passed to the database driver.
+
+| Parameter | Type | Default | Description |
+| -------------------- | -------- | ------- | ------------------------------------------------------------ |
+| `max_conns` | integer | `25` | Maximum number of open connections in the pool |
+| `max_idle_conns` | integer | `5` | Maximum number of idle connections (must be ≤ `max_conns`) |
+| `max_conn_lifetime` | duration | `30m` | Maximum age of a connection before it is closed and replaced |
+| `max_conn_idle_time` | duration | `10m` | Maximum time a connection can sit idle before it is closed |
+
+Duration values use Go duration syntax: `5m` (5 minutes), `1h` (1 hour), `30s` (30 seconds).
+
+Talos sets non-zero defaults for `max_conn_lifetime` and `max_conn_idle_time` so connections are recycled through load balancers
+and DNS rotation. Setting either to `0` disables the recycle and is **not recommended** outside development.
+
+MySQL uses standard `database/sql` pooling only. There is no advanced pool mode.
+
+### MySQL driver parameters
+
+These parameters are passed through to the underlying Go MySQL driver.
+
+| Parameter | Description | Required |
+| ----------------- | ------------------------------------------ | -------------------------------- |
+| `parseTime` | Parse `DATETIME` columns to `time.Time` | **Yes** — always set to `true` |
+| `tls` | TLS mode (`true`, `skip-verify`, `custom`) | Recommended for production |
+| `charset` | Character set | Defaults to `utf8mb4` |
+| `collation` | Collation | Defaults to `utf8mb4_general_ci` |
+| `loc` | Timezone for time.Time values | Defaults to `UTC` |
+| `timeout` | Connection timeout (e.g., `10s`) | — |
+| `readTimeout` | Read timeout (e.g., `30s`) | — |
+| `writeTimeout` | Write timeout (e.g., `30s`) | — |
+| `multiStatements` | Allow multiple statements per query | Do not enable |
+
+## Connection pooling
+
+MySQL uses Go's `database/sql` connection pool with the `go-sql-driver/mysql` driver.
+
+```yaml
+db:
+ dsn: "mysql://talos:secret@tcp(db:3306)/talos?parseTime=true&max_conns=25&max_idle_conns=5&max_conn_lifetime=5m&max_conn_idle_time=1m"
+```
+
+Pool behavior:
+
+- Connections are created on demand up to `max_conns`
+- Idle connections are kept up to `max_idle_conns`
+- Connections older than `max_conn_lifetime` are closed and replaced
+- Connections idle longer than `max_conn_idle_time` are closed
+
+### Pool sizing
+
+Start with 25 connections per instance. The total pool across all instances should stay below MySQL's `max_connections` (default:
+151).
+
+| Deployment | `max_conns` | Notes |
+| --------------- | -------------- | ------------------------------------------- |
+| Single instance | `25` | Good starting point |
+| 3 instances | `25` each | 75 total — within default `max_connections` |
+| 5+ instances | `15`–`20` each | Use ProxySQL or MySQL Router to multiplex |
+
+For large deployments, place [ProxySQL](https://proxysql.com/) or [MySQL Router](https://dev.mysql.com/doc/mysql-router/en/)
+between Talos and MySQL for connection multiplexing.
+
+## Database preparation
+
+```sql
+CREATE DATABASE talos CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+CREATE USER 'talos'@'%' IDENTIFIED BY 'secret';
+GRANT ALL PRIVILEGES ON talos.* TO 'talos'@'%';
+```
+
+## Migrations
+
+```bash
+talos-commercial migrate up --database "mysql://talos:secret@tcp(db:3306)/talos?parseTime=true"
+```
+
+## TLS / SSL
+
+Use TLS parameters in the DSN for encrypted database connections:
+
+```yaml
+db:
+ dsn: "mysql://talos:secret@tcp(db:3306)/talos?parseTime=true&tls=true"
+```
+
+| Parameter | Description |
+| ----------------- | ---------------------------------------------------------------------- |
+| `tls=true` | Enable TLS with default settings |
+| `tls=skip-verify` | TLS without certificate verification |
+| `tls=custom` | Use custom TLS configuration registered with `mysql.RegisterTLSConfig` |
+
+## Example DSNs
+
+**Development:**
+
+```
+mysql://talos:secret@tcp(localhost:3306)/talos?parseTime=true
+```
+
+**Production with pooling:**
+
+```
+mysql://talos:secret@tcp(db:3306)/talos?parseTime=true&tls=true&max_conns=25&max_idle_conns=5&max_conn_lifetime=5m&max_conn_idle_time=1m
+```
+
+**With timeouts:**
+
+```
+mysql://talos:secret@tcp(db:3306)/talos?parseTime=true&tls=true&timeout=10s&readTimeout=30s&writeTimeout=30s&max_conns=25
+```
diff --git a/docs/talos/operate/database/postgresql.md b/docs/talos/operate/database/postgresql.md
new file mode 100644
index 000000000..ddb54fdbb
--- /dev/null
+++ b/docs/talos/operate/database/postgresql.md
@@ -0,0 +1,189 @@
+---
+title: PostgreSQL
+tags: [commercial]
+sidebar_custom_props:
+ badge: Commercial
+---
+
+# PostgreSQL
+
+PostgreSQL is the recommended production database backend. It provides connection pooling, ACID transactions, and
+high-availability via streaming replication.
+
+## Supported versions
+
+PostgreSQL 14 and later.
+
+## Configuration
+
+```yaml
+db:
+ dsn: "postgres://talos:secret@db:5432/talos?sslmode=require&max_conns=25&max_conn_lifetime=5m"
+```
+
+Or via environment variable:
+
+```bash
+export TALOS_DB_DSN="postgres://talos:secret@db:5432/talos?sslmode=require&max_conns=25&max_conn_lifetime=5m"
+```
+
+## DSN format
+
+```
+postgres://user:password@host:port/dbname?param=value¶m=value
+```
+
+Both `postgres://` and `postgresql://` schemes are accepted.
+
+## DSN parameters
+
+### Connection pool parameters
+
+Pool parameters are parsed from the DSN query string and removed before the DSN is passed to the database driver.
+
+| Parameter | Type | Default | Description |
+| -------------------- | -------- | ---------- | ------------------------------------------------------------ |
+| `max_conns` | integer | `25` | Maximum number of open connections in the pool |
+| `max_idle_conns` | integer | `5` | Maximum number of idle connections (must be ≤ `max_conns`) |
+| `max_conn_lifetime` | duration | `30m` | Maximum age of a connection before it is closed and replaced |
+| `max_conn_idle_time` | duration | `10m` | Maximum time a connection can sit idle before it is closed |
+| `pool_mode` | string | `standard` | Pool implementation: `standard` or `advanced` (see below) |
+
+Duration values use Go duration syntax: `5m` (5 minutes), `1h` (1 hour), `30s` (30 seconds).
+
+Talos sets non-zero defaults for `max_conn_lifetime` and `max_conn_idle_time` so connections are recycled through load balancers,
+DNS rotation, and PostgreSQL `tcp_keepalives_*`. Setting either to `0` disables the recycle and is **not recommended** outside
+development.
+
+### PostgreSQL driver parameters
+
+These parameters are passed through to the underlying PostgreSQL driver (`pgx`).
+
+| Parameter | Description | Recommended |
+| ------------------ | ----------------------------------------------------------- | ------------- |
+| `sslmode` | TLS mode (`disable`, `require`, `verify-ca`, `verify-full`) | `verify-full` |
+| `sslrootcert` | Path to CA certificate file | — |
+| `sslcert` | Path to client certificate file (for mTLS) | — |
+| `sslkey` | Path to client private key file (for mTLS) | — |
+| `connect_timeout` | Connection timeout in seconds | `10` |
+| `application_name` | Application name reported to PostgreSQL | — |
+
+## Connection pooling
+
+Talos supports two pool modes for PostgreSQL, controlled by the `pool_mode` DSN parameter.
+
+### Standard mode (default)
+
+Uses Go's `database/sql` connection pool with the `pgx` driver. This is the default and works with all tooling.
+
+```yaml
+db:
+ dsn: "postgres://talos:secret@db:5432/talos?max_conns=25&max_idle_conns=5&max_conn_lifetime=5m&max_conn_idle_time=1m"
+```
+
+Pool behavior:
+
+- Connections are created on demand up to `max_conns`
+- Idle connections are kept up to `max_idle_conns`
+- Connections older than `max_conn_lifetime` are closed and replaced
+- Connections idle longer than `max_conn_idle_time` are closed
+
+### Advanced mode
+
+Uses native `pgxpool` for high-availability deployments. Provides built-in health checks and is optimized for Kubernetes and cloud
+environments.
+
+```yaml
+db:
+ dsn: "postgres://talos:secret@db:5432/talos?pool_mode=advanced&pool_max_conns=50&pool_min_conns=2&pool_max_conn_lifetime=30m&pool_max_conn_idle_time=10m"
+```
+
+In advanced mode, pool sizing is configured through pgxpool's native parameters parsed from the DSN. The `max_conns`,
+`max_idle_conns`, `max_conn_lifetime`, and `max_conn_idle_time` parameters are **ignored** — use the `pool_*` equivalents instead.
+
+| pgxpool parameter | Default | Description |
+| -------------------------- | ---------------------- | ----------------------------------------------------- |
+| `pool_max_conns` | `4 × runtime.NumCPU()` | Maximum size of the pgxpool connection pool |
+| `pool_min_conns` | `0` | Minimum number of connections kept open |
+| `pool_max_conn_lifetime` | `1h` | Maximum age of a connection before it is replaced |
+| `pool_max_conn_idle_time` | `30m` | Maximum idle time before an idle connection is closed |
+| `pool_health_check_period` | `1m` | Interval between background health checks |
+
+Talos exposes the pgxpool through Go's `database/sql` interface. The wrapper's `SetMaxIdleConns` is forced to `0` so that
+`database/sql` never holds connections idle on top of pgxpool — the pgxpool layer is the single source of truth for pool sizing in
+advanced mode.
+
+Use advanced mode when:
+
+- Running in Kubernetes with connection health checks
+- Using cloud-managed PostgreSQL (RDS, Cloud SQL, AlloyDB) with aggressive connection recycling
+- Deploying with PgBouncer and needing precise pool control
+
+## Pool sizing
+
+Start with 25 connections per instance. The total pool across all instances must stay below PostgreSQL's `max_connections`
+(default: 100).
+
+| Deployment | `max_conns` | Notes |
+| --------------- | -------------- | ------------------------------------------- |
+| Single instance | `25` | Good starting point |
+| 3 instances | `25` each | 75 total — within default `max_connections` |
+| 5+ instances | `15`–`20` each | Use PgBouncer to multiplex connections |
+
+For large deployments, place [PgBouncer](https://www.pgbouncer.org/) between Talos and PostgreSQL. PgBouncer multiplexes many
+application connections over fewer database connections, allowing you to scale beyond PostgreSQL's connection limit.
+
+## Migrations
+
+```bash
+talos-commercial migrate up --database "postgres://talos:secret@db:5432/talos"
+```
+
+## TLS / SSL
+
+Use the `sslmode` parameter in the DSN for encrypted database connections:
+
+```yaml
+db:
+ dsn: "postgres://talos:secret@db:5432/talos?sslmode=verify-full&sslrootcert=/certs/ca.crt"
+```
+
+| Mode | Description |
+| ------------- | --------------------------------------------------- |
+| `disable` | No TLS |
+| `require` | TLS without certificate verification |
+| `verify-ca` | TLS with CA verification |
+| `verify-full` | TLS with CA and hostname verification (recommended) |
+
+For mutual TLS (mTLS), provide both client certificate and key:
+
+```yaml
+db:
+ dsn: "postgres://talos:secret@db:5432/talos?sslmode=verify-full&sslrootcert=/certs/ca.crt&sslcert=/certs/client.crt&sslkey=/certs/client.key"
+```
+
+## Example DSNs
+
+**Development:**
+
+```
+postgres://talos:secret@localhost:5432/talos?sslmode=disable
+```
+
+**Production with standard pooling:**
+
+```
+postgres://talos:secret@db:5432/talos?sslmode=verify-full&sslrootcert=/certs/ca.crt&max_conns=25&max_idle_conns=5&max_conn_lifetime=5m&max_conn_idle_time=1m
+```
+
+**Production with advanced pooling (Kubernetes):**
+
+```
+postgres://talos:secret@db:5432/talos?sslmode=verify-full&sslrootcert=/certs/ca.crt&pool_mode=advanced
+```
+
+**Behind PgBouncer:**
+
+```
+postgres://talos:secret@pgbouncer:6432/talos?sslmode=require&max_conns=50&max_idle_conns=10&max_conn_lifetime=5m
+```
diff --git a/docs/talos/operate/database/sqlite.md b/docs/talos/operate/database/sqlite.md
new file mode 100644
index 000000000..1778d5dbb
--- /dev/null
+++ b/docs/talos/operate/database/sqlite.md
@@ -0,0 +1,29 @@
+---
+title: SQLite
+---
+
+# SQLite
+
+SQLite is the default database for the OSS edition. It requires no external dependencies.
+
+## Configuration
+
+```yaml
+db:
+ dsn: "sqlite:///var/lib/talos/data.db"
+```
+
+Talos enables WAL mode automatically for better concurrency.
+
+## Migrations
+
+```bash
+talos migrate up --database "sqlite:///var/lib/talos/data.db"
+```
+
+## Limitations
+
+- Single-node only (no multi-instance deployments)
+- No connection pooling (single-writer lock)
+- Write throughput limited by disk I/O
+- Not suitable for [separate admin/data planes](../deploy/separate-planes.md) unless co-located
diff --git a/docs/talos/operate/deploy/docker.md b/docs/talos/operate/deploy/docker.md
new file mode 100644
index 000000000..24bac56ed
--- /dev/null
+++ b/docs/talos/operate/deploy/docker.md
@@ -0,0 +1,67 @@
+---
+title: Docker
+---
+
+# Docker
+
+## Quick start
+
+```bash
+docker run -d \
+ -p 4420:4420 \
+ -e TALOS_SECRETS_DEFAULT_CURRENT="my-secret-must-be-at-least-32-characters-long" \
+ -e TALOS_CREDENTIALS_ISSUER="http://localhost:4420" \
+ -e TALOS_DB_DSN="sqlite:///data/talos.db" \
+ -v talos-data:/data \
+ oryd/talos:latest serve
+```
+
+## With config file
+
+```bash
+docker run -d \
+ -p 4420:4420 \
+ -v ./config.yaml:/etc/talos/config.yaml \
+ -v talos-data:/data \
+ oryd/talos:latest serve --config /etc/talos/config.yaml
+```
+
+## Run migrations
+
+```bash
+docker run --rm \
+ -v talos-data:/data \
+ oryd/talos:latest migrate up --database "sqlite:///data/talos.db"
+```
+
+## Health check
+
+```yaml
+healthcheck:
+ test: ["CMD", "curl", "-sf", "http://localhost:4420/health/alive"]
+ interval: 10s
+ timeout: 5s
+ retries: 3
+```
+
+## Docker Compose
+
+```yaml
+services:
+ talos:
+ image: oryd/talos:latest
+ command: serve --config /etc/talos/config.yaml
+ ports:
+ - "4420:4420"
+ volumes:
+ - ./config.yaml:/etc/talos/config.yaml
+ - talos-data:/data
+ healthcheck:
+ test: ["CMD", "curl", "-sf", "http://localhost:4420/health/alive"]
+ interval: 10s
+ timeout: 5s
+ retries: 3
+
+volumes:
+ talos-data:
+```
diff --git a/docs/talos/operate/deploy/edge-proxy.md b/docs/talos/operate/deploy/edge-proxy.md
new file mode 100644
index 000000000..c7121593a
--- /dev/null
+++ b/docs/talos/operate/deploy/edge-proxy.md
@@ -0,0 +1,274 @@
+---
+title: Edge proxy
+tags: [commercial]
+sidebar_custom_props:
+ badge: Commercial
+---
+
+# Edge proxy
+
+Deploy a caching reverse proxy as a sidecar to your application for sub-millisecond verification latency.
+
+## Pattern
+
+```mermaid
+graph TB
+ subgraph edgeA["Edge Region A"]
+ dpA["Data Plane
+ Cache"]
+ end
+
+ subgraph edgeB["Edge Region B"]
+ dpB["Data Plane
+ Cache"]
+ end
+
+ subgraph core["Core Data Center"]
+ admin["Admin Plane"]
+ end
+
+ dpA -- shared DB --> db[("Database")]
+ dpB -- shared DB --> db
+ admin --> db
+```
+
+## Benefits
+
+- Verification latency matches the distance to the nearest edge node
+- Cache absorbs repeated lookups, reducing database load
+- Admin operations remain centralized and secured
+
+## How it works
+
+The edge proxy is an HTTP reverse proxy that sits between your application and a central Talos server. It intercepts `POST`
+requests to `/v2alpha1/admin/apiKeys:verify`, caches positive (active) verification responses locally, and proxies everything else
+to upstream unchanged. Verify is an admin endpoint, so the proxy must forward admin credentials accepted by the upstream Talos
+server. Batch verify (`POST /v2alpha1/admin/apiKeys:batchVerify`) is proxied transparently without caching.
+
+```mermaid
+sequenceDiagram
+ participant App
+ participant Proxy as Edge Proxy
+ participant Talos as Upstream Talos
+
+ App->>Proxy: POST /v2alpha1/admin/apiKeys:verify
+ alt Cache HIT
+ Proxy-->>App: 200 OK (cached, sub-ms)
+ else Cache MISS
+ Proxy->>Talos: POST /v2alpha1/admin/apiKeys:verify
+ Talos-->>Proxy: 200 OK (active=true)
+ Note over Proxy: Cache response
+ Proxy-->>App: 200 OK
+ end
+ App->>Proxy: POST /v2alpha1/admin/issuedApiKeys
+ Proxy->>Talos: Proxy unchanged
+ Talos-->>Proxy: 200 OK
+ Proxy-->>App: 200 OK
+```
+
+Non-verify requests (admin operations, key issuance, health checks to upstream) pass through the proxy transparently.
+
+## Sidecar deployment
+
+Run the proxy as a sidecar container alongside your application. Your application sends verify requests to `localhost` (sub-ms
+cache hits) instead of the central Talos server.
+
+```
+┌─────────────────────────────────┐
+│ Pod / VM / Task │
+│ │
+│ ┌───────────┐ ┌───────────┐ │
+│ │ App │──▶│ Proxy │─┼──▶ Upstream Talos
+│ │ │ │ :8080 │ │
+│ └───────────┘ └───────────┘ │
+└─────────────────────────────────┘
+```
+
+Point your application's Talos verify URL at `http://localhost:8080` (or whichever port the proxy listens on). All other Talos API
+calls (admin, key management) should go directly to the central server.
+
+## Configuration
+
+Start the proxy with `talos-commercial proxy`:
+
+```bash
+talos-commercial proxy \
+ --upstream http://talos-central:8080 \
+ --listen :9090 \
+ --cache-ttl 60s \
+ --cache-max-size 104857600
+```
+
+| Flag | Default | Description |
+| -------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
+| `--upstream` | _(required)_ | URL of the upstream Talos server. |
+| `--listen` | `:8080` | Address and port the proxy listens on. |
+| `--cache-ttl` | `60s` | Default TTL for cached verification responses. |
+| `--cache-max-size` | `104857600` (100 MB) | Maximum in-memory cache size in bytes. |
+| `--cache-num-counters` | `10000` | Number of frequency counters for cache admission policy. Higher values improve hit rates for large working sets. |
+| `--trust-x-forwarded-host` | `false` | Use `X-Forwarded-Host` header for tenant-aware cache keys. Enable only when the proxy runs behind a trusted load balancer. |
+| `--allowed-hosts` | _(none)_ | Comma-separated allowlist of valid `Host` / `X-Forwarded-Host` values. Requests with other hosts are rejected with `403 Forbidden`. |
+
+## Cache behavior
+
+### Cache key generation
+
+Cache keys are derived from `SHA256(host + credential)` using length-prefixed encoding to prevent collision attacks. The host
+component ensures tenant isolation in multi-tenant deployments: the same credential cached under `tenant-a.example.com` will not
+be served for requests from `tenant-b.example.com`.
+
+### What gets cached
+
+Only responses that meet **all** of the following criteria are cached:
+
+- The request is a `POST` to `/v2alpha1/admin/apiKeys:verify` (exact match — batch verify is not cached)
+- The upstream returned HTTP `200 OK`
+- The response body contains `"is_active": true`
+
+Inactive credentials, error responses, and non-verify endpoints are never cached.
+
+### TTL calculation
+
+The effective TTL for each entry is `min(configured_ttl, time_until_expires_at)`. If the verification response includes an
+`expires_at` timestamp, the proxy ensures the cached entry expires no later than the credential itself. If `expires_at` is absent,
+the configured `--cache-ttl` is used.
+
+### Cache headers
+
+Every response from the proxy includes an `Ory-Talos-Cache` header:
+
+| Header value | Meaning |
+| ------------ | ------------------------------------------------------------------------------ |
+| `HIT` | Response served from local cache. |
+| `MISS` | Response fetched from upstream (may have been cached for subsequent requests). |
+
+### Cache bypass
+
+Clients can bypass the cache by including a `Cache-Control` header:
+
+```bash
+curl -X POST http://localhost:8080/v2alpha1/admin/apiKeys:verify \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer $TALOS_ADMIN_TOKEN" \
+ -H "Cache-Control: no-cache" \
+ -d '{"credential": "phx_..."}'
+```
+
+Both `no-cache` and `no-store` directives trigger a cache bypass. The response is still eligible for caching.
+
+## Health checks
+
+The proxy exposes the following health endpoints:
+
+| Endpoint | Behavior |
+| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `/health/alive` | Always returns `200 OK`. Use as a liveness probe. |
+| `/health/ready` | Checks upstream connectivity by calling the upstream's `/health/alive` endpoint. Returns `200 OK` if upstream is reachable, `503 Service Unavailable` otherwise. Use as a readiness probe. |
+| `/metrics` | Prometheus metrics endpoint. |
+
+## Proxy metrics
+
+The proxy exposes Prometheus metrics under the `talos_proxy_` namespace:
+
+| Metric | Type | Description |
+| -------------------------------------- | --------- | ------------------------------------------------------------- |
+| `talos_proxy_cache_hits_total` | Counter | Total number of cache hits. |
+| `talos_proxy_cache_misses_total` | Counter | Total number of cache misses. |
+| `talos_proxy_upstream_requests_total` | Counter | Requests forwarded to upstream, labeled by `status` code. |
+| `talos_proxy_upstream_latency_seconds` | Histogram | Latency of upstream requests. |
+| `talos_proxy_request_duration_seconds` | Histogram | Total request duration, labeled by `cached` (`true`/`false`). |
+
+For general monitoring guidance, see [Metrics](../monitoring/metrics.md).
+
+## Docker Compose sidecar example
+
+```yaml
+services:
+ talos:
+ image: oryd/talos-commercial:latest
+ command: serve
+ ports:
+ - "8080:8080"
+ environment:
+ - TALOS_DB_DSN=postgres://talos:secret@db:5432/talos?sslmode=disable
+ - TALOS_CREDENTIALS_ISSUER=https://api.example.com
+ - TALOS_SECRETS_DEFAULT_CURRENT=use-a-random-64-char-pagination-token-secret-generated-at-deploy
+ - TALOS_SECRETS_HMAC_CURRENT=use-a-random-64-char-hmac-secret-for-api-key-checksum-validation
+
+ proxy:
+ image: oryd/talos-commercial:latest
+ command: >
+ proxy --upstream http://talos:8080 --listen :9090 --cache-ttl 60s
+ ports:
+ - "9090:9090"
+
+ app:
+ image: your-app:latest
+ environment:
+ # Verify requests go through the local proxy
+ - TALOS_VERIFY_URL=http://proxy:9090
+ # Admin requests go directly to the central server
+ - TALOS_ADMIN_URL=http://talos:8080
+ depends_on:
+ - proxy
+ - talos
+```
+
+## Kubernetes sidecar example
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: app-with-talos-proxy
+spec:
+ containers:
+ - name: app
+ image: your-app:latest
+ env:
+ # Verify requests go through the localhost sidecar
+ - name: TALOS_VERIFY_URL
+ value: "http://localhost:9090"
+ # Admin requests go directly to the central server
+ - name: TALOS_ADMIN_URL
+ value: "http://talos.talos-system.svc.cluster.local:8080"
+
+ - name: talos-proxy
+ image: oryd/talos-commercial:latest
+ args:
+ - proxy
+ - --upstream
+ - http://talos.talos-system.svc.cluster.local:8080
+ - --listen
+ - :9090
+ - --cache-ttl
+ - "60s"
+ ports:
+ - containerPort: 9090
+ name: proxy
+ livenessProbe:
+ httpGet:
+ path: /health/alive
+ port: proxy
+ initialDelaySeconds: 2
+ periodSeconds: 10
+ readinessProbe:
+ httpGet:
+ path: /health/ready
+ port: proxy
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "50m"
+ limits:
+ memory: "256Mi"
+ cpu: "200m"
+```
+
+## Eventual consistency
+
+Revocation takes effect in the database immediately but cached verification results persist until the cache TTL expires. To force
+an immediate re-check against upstream, send `Cache-Control: no-cache` on the verification request.
+
+Choose a `--cache-ttl` that balances latency savings against your revocation propagation requirements. Shorter TTLs provide faster
+revocation propagation at the cost of more upstream requests.
diff --git a/docs/talos/operate/deploy/index.md b/docs/talos/operate/deploy/index.md
new file mode 100644
index 000000000..b70d601bf
--- /dev/null
+++ b/docs/talos/operate/deploy/index.md
@@ -0,0 +1,23 @@
+---
+title: Deploy
+---
+
+# Deploy
+
+Talos can be deployed as a standalone binary, Docker container, or Kubernetes workload.
+
+## Deployment options
+
+| Method | Best for |
+| --------------------------- | ----------------------------------- |
+| [Docker](docker.md) | Development, small-scale production |
+| [Kubernetes](kubernetes.md) | Production with orchestration |
+| Binary | Custom deployments |
+
+## Architecture options
+
+| Topology | Edition | Description |
+| ------------------------------------- | ---------- | --------------------------------------------- |
+| Single-node | OSS | One process serves both admin and data planes |
+| [Separate planes](separate-planes.md) | Commercial | Independent admin and data plane deployments |
+| [Edge proxy](edge-proxy.md) | Commercial | Data plane at the edge, admin plane in core |
diff --git a/docs/talos/operate/deploy/kubernetes.md b/docs/talos/operate/deploy/kubernetes.md
new file mode 100644
index 000000000..62f75f5ba
--- /dev/null
+++ b/docs/talos/operate/deploy/kubernetes.md
@@ -0,0 +1,129 @@
+---
+title: Kubernetes
+---
+
+# Kubernetes
+
+The OSS edition uses an embedded SQLite database, so it cannot scale horizontally — a multi-replica Deployment backed by a shared
+volume will corrupt under concurrent writes. Run the OSS image as a single replica or move to the
+[Commercial edition](../../index.md#editions) for Postgres, MySQL, or CockroachDB.
+
+| Edition | Image | Backends | Replicas |
+| ---------- | ------------------------------ | ------------------------------ | --------------------- |
+| OSS | `oryd/talos:latest` | SQLite (embedded) | 1 (single-node only) |
+| Commercial | `oryd/talos-commercial:latest` | PostgreSQL, MySQL, CockroachDB | Horizontally scalable |
+
+## Deployment (Commercial, scalable)
+
+The manifest below uses the commercial image and a SQL backend stored as `dsn` in a Kubernetes `Secret`. Adjust `replicas` to your
+traffic profile.
+
+```yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: talos
+spec:
+ replicas: 3
+ selector:
+ matchLabels:
+ app: talos
+ template:
+ metadata:
+ labels:
+ app: talos
+ spec:
+ initContainers:
+ - name: migrate
+ image: oryd/talos-commercial:latest
+ command: ["talos", "migrate", "up"]
+ env:
+ - name: TALOS_DB_DSN
+ valueFrom:
+ secretKeyRef:
+ name: talos-secrets
+ key: dsn
+ containers:
+ - name: talos
+ image: oryd/talos-commercial:latest
+ args: ["serve", "--config", "/etc/talos/config.yaml"]
+ ports:
+ - containerPort: 4420
+ name: http
+ - containerPort: 4422
+ name: metrics
+ livenessProbe:
+ httpGet:
+ path: /health/alive
+ port: http
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ readinessProbe:
+ httpGet:
+ path: /health/ready
+ port: http
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ env:
+ - name: TALOS_DB_DSN
+ valueFrom:
+ secretKeyRef:
+ name: talos-secrets
+ key: dsn
+ - name: TALOS_SECRETS_DEFAULT_CURRENT
+ valueFrom:
+ secretKeyRef:
+ name: talos-secrets
+ key: hmac-secret
+ - name: TALOS_CREDENTIALS_ISSUER
+ value: "https://api.example.com"
+ volumeMounts:
+ - name: config
+ mountPath: /etc/talos
+ volumes:
+ - name: config
+ configMap:
+ name: talos-config
+```
+
+## Service
+
+```yaml
+apiVersion: v1
+kind: Service
+metadata:
+ name: talos
+spec:
+ selector:
+ app: talos
+ ports:
+ - name: http
+ port: 4420
+ - name: metrics
+ port: 4422
+```
+
+## Horizontal Pod Autoscaler
+
+Scale based on CPU or request rate:
+
+```yaml
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+ name: talos
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: talos
+ minReplicas: 3
+ maxReplicas: 20
+ metrics:
+ - type: Resource
+ resource:
+ name: cpu
+ target:
+ type: Utilization
+ averageUtilization: 70
+```
diff --git a/docs/talos/operate/deploy/separate-planes.md b/docs/talos/operate/deploy/separate-planes.md
new file mode 100644
index 000000000..b3597ee44
--- /dev/null
+++ b/docs/talos/operate/deploy/separate-planes.md
@@ -0,0 +1,96 @@
+---
+title: Separate admin and data planes
+---
+
+# Separate admin and data planes
+
+In production, you can deploy the admin plane and data plane as separate processes for independent scaling and security isolation.
+
+## Why run them separately
+
+- **Security**: Admin plane (write operations) stays internal; data plane (verification) can be exposed at the edge
+- **Scaling**: Data plane handles high-throughput verification and scales horizontally; admin plane handles lower-volume
+ management
+- **Network isolation**: Admin plane behind internal firewall; data plane behind public load balancer
+
+## Architecture
+
+Both planes share the same database. The admin plane writes keys; the data plane reads and verifies them.
+
+```mermaid
+graph TB
+ subgraph internal["Internal Network"]
+ admin["Admin Plane (× N)
Issue keys
Revoke keys
Derive tokens"]
+ end
+
+ subgraph public["Public Network"]
+ data["Data Plane (× N)
Verify keys
Self-revoke
Batch verify"]
+ end
+
+ admin -- shared DB --> db[("Database")]
+ data -- shared DB --> db
+ data --> cache["Cache (optional)"]
+```
+
+## Commands
+
+Talos provides separate subcommands for each plane:
+
+```bash
+# Run both planes in a single process (development/small deployments)
+talos serve --config config.yaml
+
+# Run only the admin plane (key management, token derivation)
+talos serve admin --config config.yaml
+
+# Run only the data plane (verification, self-revocation, caching)
+talos serve check --config config.yaml
+```
+
+## Configuration
+
+Both deployments use the same config file or environment variables. The key difference is network exposure:
+
+Both processes need the full configuration block (`secrets`, `credentials`, `db`). The split is driven by the `serve` subcommand
+and the bind address, not by stripping config keys.
+
+**Admin plane** — bind to an internal address:
+
+```yaml
+serve:
+ http:
+ host: "10.0.0.1"
+ port: 4420
+credentials:
+ issuer: "https://api.example.com"
+secrets:
+ default:
+ current: "use-the-same-pagination-secret-on-both-planes--64chars"
+ hmac:
+ current: "use-the-same-hmac-secret-on-both-planes-or-verify-fails-64chars"
+```
+
+**Data plane** — bind to all interfaces with caching. Use the same secrets and issuer as the admin plane so the two processes
+derive identical key checksums. If you co-locate both planes on the same host, change one port (for example, the admin plane on
+`4421`):
+
+```yaml
+serve:
+ http:
+ host: "0.0.0.0"
+ port: 4420
+credentials:
+ issuer: "https://api.example.com"
+secrets:
+ default:
+ current: "use-the-same-pagination-secret-on-both-planes--64chars"
+ hmac:
+ current: "use-the-same-hmac-secret-on-both-planes-or-verify-fails-64chars"
+cache:
+ type: "memory"
+ ttl: "5m"
+```
+
+## Network policies
+
+Restrict admin plane access to internal services only. Data plane can accept traffic from any source.
diff --git a/docs/talos/operate/index.md b/docs/talos/operate/index.md
new file mode 100644
index 000000000..3abd17941
--- /dev/null
+++ b/docs/talos/operate/index.md
@@ -0,0 +1,48 @@
+---
+title: Operate
+description: Install, configure, and deploy Ory Talos
+---
+
+# Operate Ory Talos
+
+How to install, configure, deploy, and operate Talos. Pages tagged `[commercial]` apply to the Commercial edition only — the OSS
+edition runs as a single-node binary with embedded SQLite and covers the install, configure, secrets, TLS, monitoring, and
+security-hardening guides below.
+
+## Getting started
+
+1. **[Install](install.md)** — build from source or download a binary
+2. **[Configure](configure.md)** — set up the config file, environment variables, and secrets
+3. **[Database](database/index.md)** — choose and configure a database backend
+4. **[Deploy](deploy/index.md)** — run Talos with Docker, Kubernetes, or as a systemd service
+
+## Production checklist
+
+Before going to production, review these guides (apply to OSS and Commercial):
+
+- **[Secrets management](secrets.md)** — configure HMAC secrets and JWKS signing keys
+- **[TLS](tls.md)** — enable TLS termination or configure a reverse proxy
+- **[Monitoring](monitoring/index.md)** — set up Prometheus metrics, OpenTelemetry tracing, and health checks
+- **[Security hardening](security-hardening.md)** — production security checklist, including admin plane authentication
+- **[Benchmarks](benchmarks.md)** — performance baselines and load testing
+
+## Commercial-only features
+
+The OSS edition is single-node SQLite. Horizontal scale, SQL backends, distributed caching, edge deployment, and multi-tenancy
+require the [Commercial edition](../index.md#editions):
+
+- **[PostgreSQL](database/postgresql.md)**, **[MySQL](database/mysql.md)**, **[CockroachDB](database/cockroachdb.md)** —
+ production-grade SQL backends
+- **[Caching](cache/index.md)** — in-memory and Redis caching for sub-millisecond verification
+- **[Edge proxy](deploy/edge-proxy.md)** — deploy data plane at the edge
+- **[Multi-tenancy](multi-tenancy.md)** — serve multiple tenants from a single cluster
+
+## Architecture
+
+Talos separates administrative operations (issuing, revoking) from verification:
+
+- **Admin plane** — manages key lifecycle. Runs behind your internal network.
+- **Data plane** — verifies credentials at the edge. Horizontally scalable with caching.
+
+You can run both planes in a single process (`talos serve`) or split them for production (`talos serve admin`,
+`talos serve check`). See [Separate planes](deploy/separate-planes.md) for details.
diff --git a/docs/talos/operate/install.md b/docs/talos/operate/install.md
new file mode 100644
index 000000000..e893fec2d
--- /dev/null
+++ b/docs/talos/operate/install.md
@@ -0,0 +1,69 @@
+---
+title: Install
+description: Build Talos from source or download a pre-built binary
+---
+
+# Install
+
+
+
+## Build from source
+
+Talos requires Go 1.23 or later.
+
+### OSS edition
+
+```bash
+git clone https://github.com/ory/talos.git
+cd talos
+go build -o .bin/talos .
+```
+
+The binary is at `.bin/talos`. SQLite is the only supported database backend in the OSS edition.
+
+### Commercial edition
+
+The Commercial edition adds PostgreSQL, MySQL, CockroachDB, caching, multi-tenancy, and the admin UI:
+
+```bash
+go build -tags commercial -o .bin/talos-commercial .
+```
+
+## Verify the installation
+
+
+
+```bash
+./.bin/talos --version
+./.bin/talos help
+```
+
+## Run database migrations
+
+Before starting the server, run migrations to create the database schema:
+
+```bash
+# SQLite (OSS)
+./.bin/talos migrate up --database "sqlite:///path/to/talos.db"
+
+# PostgreSQL (Commercial)
+./.bin/talos-commercial migrate up --database "postgres://user:pass@localhost:5432/talos"
+
+# MySQL (Commercial)
+./.bin/talos-commercial migrate up --database "mysql://user:pass@tcp(localhost:3306)/talos"
+
+# CockroachDB (Commercial)
+./.bin/talos-commercial migrate up --database "cockroach://user@localhost:26257/talos"
+```
+
+## Start the server
+
+```bash
+./.bin/talos serve --config config.yaml
+```
+
+See [Configure](configure.md) for config file format and options.
+
+## Docker
+
+See [Docker deployment](deploy/docker.md) for running Talos in containers.
diff --git a/docs/talos/operate/monitoring/health-checks.md b/docs/talos/operate/monitoring/health-checks.md
new file mode 100644
index 000000000..b3fce3f67
--- /dev/null
+++ b/docs/talos/operate/monitoring/health-checks.md
@@ -0,0 +1,49 @@
+---
+title: Health checks
+---
+
+# Health checks
+
+Talos exposes three health endpoints on the main HTTP port.
+
+## Endpoints
+
+| Endpoint | Purpose | Use for |
+| --------------- | --------------- | ------------------------------------------ |
+| `/health/alive` | Liveness probe | Kubernetes `livenessProbe` |
+| `/health/ready` | Readiness probe | Kubernetes `readinessProbe`, load balancer |
+| `/health` | Combined health | Quick manual checks |
+
+## Kubernetes probes
+
+```yaml
+livenessProbe:
+ httpGet:
+ path: /health/alive
+ port: 4420
+ initialDelaySeconds: 5
+ periodSeconds: 10
+
+readinessProbe:
+ httpGet:
+ path: /health/ready
+ port: 4420
+ initialDelaySeconds: 5
+ periodSeconds: 10
+```
+
+## Load balancer
+
+Point your load balancer health check at `/health/ready`. This endpoint returns 200 when the server is ready to accept traffic and
+503 when it is not (e.g., during startup or shutdown).
+
+## Suppressing health logs
+
+To reduce log noise from frequent health checks:
+
+```yaml
+serve:
+ http:
+ request_log:
+ exclude_health_endpoints: true
+```
diff --git a/docs/talos/operate/monitoring/index.md b/docs/talos/operate/monitoring/index.md
new file mode 100644
index 000000000..f0a92dbda
--- /dev/null
+++ b/docs/talos/operate/monitoring/index.md
@@ -0,0 +1,11 @@
+---
+title: Monitoring
+---
+
+# Monitoring
+
+Talos provides built-in observability through Prometheus metrics, OpenTelemetry tracing, and health endpoints.
+
+- [Prometheus metrics](metrics.md) — request counts, latencies, and pool sizes
+- [OpenTelemetry tracing](tracing.md) — distributed request traces
+- [Health checks](health-checks.md) — liveness and readiness probes
diff --git a/docs/talos/operate/monitoring/metrics.md b/docs/talos/operate/monitoring/metrics.md
new file mode 100644
index 000000000..09116feed
--- /dev/null
+++ b/docs/talos/operate/monitoring/metrics.md
@@ -0,0 +1,67 @@
+---
+title: Prometheus metrics
+---
+
+# Prometheus metrics
+
+Talos exposes Prometheus metrics on a dedicated port (default: 4422).
+
+## Endpoint
+
+```
+GET http://localhost:4422/metrics
+```
+
+## HTTP metrics
+
+| Metric | Type | Labels | Description |
+| ------------------------------- | --------- | ---------------------------- | --------------------- |
+| `http_requests_total` | Counter | `method`, `code`, `endpoint` | Total HTTP requests |
+| `http_request_duration_seconds` | Histogram | `method`, `code`, `endpoint` | Request latency |
+| `http_request_size_bytes` | Histogram | `method`, `code` | Request payload size |
+| `http_response_size_bytes` | Histogram | `method`, `code` | Response payload size |
+| `http_requests_in_flight` | Gauge | -- | Concurrent requests |
+
+### Labels
+
+| Label | Description | Used by |
+| ---------- | --------------------------------------------------------------- | ------------------------------------------------------ |
+| `method` | HTTP method (lowercase) | All except `http_requests_in_flight` |
+| `code` | HTTP status code | All except `http_requests_in_flight` |
+| `endpoint` | Route template (e.g., `/v2alpha1/admin/issuedApiKeys/{key_id}`) | `http_requests_total`, `http_request_duration_seconds` |
+
+## Configuration
+
+```yaml
+serve:
+ metrics:
+ host: "0.0.0.0"
+ port: 4422
+```
+
+## Proxy metrics (Commercial)
+
+The edge proxy exposes additional metrics under the `talos_proxy_` namespace.
+
+| Metric | Type | Labels | Description |
+| -------------------------------------- | --------- | -------- | ------------------------------ |
+| `talos_proxy_cache_hits_total` | Counter | -- | Total number of cache hits |
+| `talos_proxy_cache_misses_total` | Counter | -- | Total number of cache misses |
+| `talos_proxy_upstream_requests_total` | Counter | `status` | Requests forwarded to upstream |
+| `talos_proxy_upstream_latency_seconds` | Histogram | -- | Upstream request latency |
+| `talos_proxy_request_duration_seconds` | Histogram | `cached` | Total request duration |
+
+### Labels
+
+| Label | Description | Used by |
+| -------- | ----------------------------------------------------------- | -------------------------------------- |
+| `status` | HTTP status code of upstream response | `talos_proxy_upstream_requests_total` |
+| `cached` | Whether the response was served from cache (`true`/`false`) | `talos_proxy_request_duration_seconds` |
+
+## Grafana
+
+Scrape the metrics endpoint with Prometheus and visualize with Grafana. Key panels:
+
+- Request rate: `rate(http_requests_total[5m])`
+- P99 latency: `histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))`
+- Error rate: `rate(http_requests_total{code=~"5.."}[5m])`
diff --git a/docs/talos/operate/monitoring/tracing.md b/docs/talos/operate/monitoring/tracing.md
new file mode 100644
index 000000000..43baf4881
--- /dev/null
+++ b/docs/talos/operate/monitoring/tracing.md
@@ -0,0 +1,40 @@
+---
+title: OpenTelemetry tracing
+---
+
+# OpenTelemetry tracing
+
+Talos supports distributed tracing via OpenTelemetry.
+
+## Configuration
+
+```yaml
+tracing:
+ enabled: true
+ service_name: "talos"
+ exporter: "otlp"
+ endpoint: "otel-collector:4317"
+ sample_rate: 0.01
+```
+
+## Exporters
+
+| Exporter | Description |
+| -------- | ------------------------------------ |
+| `otlp` | OpenTelemetry Protocol (recommended) |
+| `jaeger` | Jaeger native format |
+| `stdout` | Print traces to stderr (debugging) |
+
+## Environment variables
+
+```bash
+export TALOS_TRACING_ENABLED=true
+export TALOS_TRACING_EXPORTER=otlp
+export TALOS_TRACING_ENDPOINT=otel-collector:4317
+export TALOS_TRACING_SAMPLE_RATE=0.01
+```
+
+## Traced operations
+
+Talos traces database queries, HMAC operations, cache lookups, key verification paths, and HTTP request handling. Each trace
+includes the Network ID (for multi-tenant deployments) and relevant key identifiers.
diff --git a/docs/talos/operate/multi-tenancy.md b/docs/talos/operate/multi-tenancy.md
new file mode 100644
index 000000000..8f2634581
--- /dev/null
+++ b/docs/talos/operate/multi-tenancy.md
@@ -0,0 +1,135 @@
+---
+title: Multi-tenancy
+tags: [commercial]
+sidebar_custom_props:
+ badge: Commercial
+---
+
+# Multi-tenancy
+
+Talos supports multi-tenancy through Network IDs (NID) derived from the request hostname. Each tenant runs on its own hostname and
+has its own NID, configuration overlay, and isolated data.
+
+## How it works
+
+1. Each tenant is assigned a unique Network ID (UUID).
+2. The hostname middleware extracts the hostname from the incoming request, normalizes it, and resolves it to a configured tenant.
+3. The contextualizer attaches the NID and any per-tenant configuration overlay to the request context.
+4. All database operations are scoped to the NID via composite primary keys `(nid, key_id)`. Keys created in one tenant cannot be
+ accessed or verified in another.
+
+## Configuration
+
+```yaml
+multitenancy:
+ enabled: true
+ networks:
+ - hostname: "tenant1.talos.example.com"
+ id: "550e8400-e29b-41d4-a716-446655440001"
+ config_path: "/etc/talos/tenant1.yaml"
+ - hostname: "tenant2.talos.example.com"
+ id: "550e8400-e29b-41d4-a716-446655440002"
+ config_path: "/etc/talos/tenant2.yaml"
+```
+
+| Field | Required | Description |
+| ------------- | -------- | ------------------------------------------------------------------------------ |
+| `hostname` | Yes | Tenant hostname matched against the normalized request hostname (see below) |
+| `id` | Yes | Tenant UUID written to the `nid` column of every row created on this tenant |
+| `config_path` | No | Path to a YAML file containing per-tenant business-logic overrides (see below) |
+
+Hostnames must be unique after normalization. Talos refuses to start if two entries normalize to the same value.
+
+## Hostname source and normalization
+
+By default Talos uses `r.Host` (the HTTP `Host` header) for tenant routing. To prefer `X-Forwarded-Host`, set:
+
+```yaml
+serve:
+ http:
+ trust_forwarded_host: true
+```
+
+Set this **only** when Talos runs behind a reverse proxy that strips the client-supplied `X-Forwarded-Host` and rewrites it to the
+canonical edge hostname. Trusting the header in front of an unfiltered ingress lets external callers spoof tenant identity by
+sending a forged `X-Forwarded-Host`.
+
+Hostnames are normalized before lookup:
+
+- Lowercased (`Tenant1.Example.com` → `tenant1.example.com`)
+- Port stripped (`tenant1.example.com:8443` → `tenant1.example.com`)
+- IPv6 brackets stripped (`[2001:db8::1]:443` → `2001:db8::1`)
+- Rejected if the bare hostname exceeds 253 characters (DNS maximum), contains null bytes, or contains non-printable runes — these
+ requests are treated as if the hostname is unknown.
+
+## Unknown hostname behavior
+
+Requests whose normalized hostname does not match any configured network return HTTP `404` with `code: NOT_FOUND` and reason
+`network not found`. The middleware does not fall back to a default tenant. Configure a wildcard or catch-all hostname explicitly
+if you need one.
+
+## Per-tenant configuration overlays
+
+`config_path` points to a YAML file merged on top of the base server configuration at request time. Per-tenant overlays are
+**business-logic only**:
+
+| Allowed override prefixes | Purpose |
+| ------------------------- | ------------------------------------------ |
+| `talos.*` | Tenant-specific business logic |
+| `secrets.*` | Per-tenant HMAC and pagination secrets |
+| `credentials.*` | Per-tenant key prefixes, issuer, JWKS URLs |
+| `cache.*` | Per-tenant cache backend selection |
+
+Server-wide settings — `db.*`, `serve.*` (`http`, `grpc`, `tls`), `multitenancy.*`, `tracing.*` — are **always global** and cannot
+be overridden per tenant. Setting them in a tenant overlay has no effect.
+
+## Database isolation
+
+Both `api_keys` and `imported_api_keys` tables use composite primary keys `(nid, key_id)`. Every query includes the NID, ensuring
+complete data isolation at the SQL level. Cross-tenant queries are impossible from application code because the NID is read from
+the request context, never from request parameters or response bodies.
+
+## Defense-in-depth
+
+Token claims embed the NID at derivation time. During verification, the claim NID is validated against the context NID (from
+hostname). A mismatch returns `VERIFICATION_ERROR_NOT_FOUND`, preventing cross-tenant token replay.
+
+## Provisioning a new tenant
+
+1. **Generate a tenant UUID:** `uuidgen` (or `python -c 'import uuid; print(uuid.uuid4())'`).
+2. **Pick a hostname** that resolves to your Talos data plane (e.g., `tenant3.talos.example.com`) and add a DNS record or
+ load-balancer rule for it.
+3. **Create the tenant overlay** at `/etc/talos/tenant3.yaml` with any per-tenant business settings:
+
+ ```yaml
+ credentials:
+ issuer: "https://api.tenant3.example.com"
+ api_keys:
+ prefix:
+ current: "t3"
+ ```
+
+4. **Add the network entry** to the base config:
+
+ ```yaml
+ multitenancy:
+ networks:
+ - hostname: "tenant3.talos.example.com"
+ id: "550e8400-e29b-41d4-a716-446655440003"
+ config_path: "/etc/talos/tenant3.yaml"
+ ```
+
+5. **Reload or restart Talos.** The contextualizer picks up the new entry on the next request.
+6. **Verify the route** with a curl against the admin plane:
+
+ ```bash
+ curl -sf -X POST "https://tenant3.talos.example.com/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{"name":"smoketest","actor_id":"system"}' | jq
+ ```
+
+ The response should include the new tenant's prefix (`t3_v1_…`).
+
+To deprovision a tenant, remove the entry from `multitenancy.networks` and reload. Existing keys remain in the database under that
+NID; delete them with a tenant-scoped admin call before removing the entry, or run a SQL
+`DELETE FROM api_keys WHERE nid = ''` after the entry is gone.
diff --git a/docs/talos/operate/secrets.md b/docs/talos/operate/secrets.md
new file mode 100644
index 000000000..2f1b9264d
--- /dev/null
+++ b/docs/talos/operate/secrets.md
@@ -0,0 +1,111 @@
+---
+title: Secret management
+---
+
+# Secret management
+
+Talos uses two independent secret families:
+
+- `secrets.hmac.*` — keys API key checksums and derives the macaroon root key. **Required at startup**; Talos exits with
+ `project has no HMAC key configured` if `secrets.hmac.current` is unset.
+- `secrets.pagination.*` (preferred) or `secrets.default.*` (fallback) — encrypts opaque pagination tokens. Required to use list
+ endpoints.
+
+Each secret must be at least 32 characters. Use 64 random characters for new deployments.
+
+## Configuration
+
+```yaml
+secrets:
+ hmac:
+ current: "use-a-random-64-char-hmac-secret-for-api-key-checksum-validation"
+ retired:
+ - "previous-hmac-secret-rotated-out-on-2026-03-01-padded-to-64chars-"
+ pagination:
+ current: "use-a-random-64-char-pagination-token-secret-generated-at-deploy"
+ retired:
+ - "previous-pagination-token-secret-rotated-out-on-2026-03-01--64chars"
+```
+
+If `secrets.pagination.current` is empty, Talos falls back to `secrets.default.current`. Use `secrets.pagination.*` for new
+deployments; `secrets.default.*` is retained for backwards compatibility with earlier configurations.
+
+## Secret types
+
+| Secret | Purpose | Required |
+| ---------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------- |
+| `secrets.hmac.current` | API key checksum HMAC and macaroon root-key derivation | Yes (min 32 chars) |
+| `secrets.hmac.retired` | Older HMAC secrets accepted during verification only | No |
+| `secrets.pagination.current` | Pagination-token encryption (preferred over `secrets.default`) | One of pagination/default required for list endpoints |
+| `secrets.pagination.retired` | Older pagination secrets accepted during decryption only | No |
+| `secrets.default.current` | Pagination-token fallback when `secrets.pagination.current` unset | No (use `pagination.*`) |
+| `secrets.default.retired` | Older fallback secrets accepted during decryption only | No |
+
+The HMAC and pagination secret families are independent. Rotate them on independent schedules and never reuse the same value
+across families.
+
+## Macaroon root-key derivation
+
+Talos does not store a separate macaroon signing secret. The macaroon root key is derived deterministically from
+`secrets.hmac.current` using a domain-separated HMAC-SHA256:
+
+```
+macaroon_root_key = HMAC-SHA256(secrets.hmac.current, "talos/macaroon/v1/root-key")
+```
+
+The fixed domain string `talos/macaroon/v1/root-key` prevents the derived key from colliding with other uses of the HMAC secret
+(such as API key checksums). All admin and data plane processes configured with the same `secrets.hmac.current` derive the same
+macaroon root key, so any node can verify macaroons issued by any other node without out-of-band key distribution.
+
+Rotating `secrets.hmac.current` rotates both the API key checksum key and the macaroon root key at once. Verification falls back
+through `secrets.hmac.retired` for both purposes.
+
+## Pagination-token secret
+
+List endpoints (`ListIssuedAPIKeys`, `ListImportedAPIKeys`, `ListBatchVerifications`, …) return an opaque `next_page_token` that
+encrypts the cursor (key ID and tenant ID) with NaCl secretbox. The encryption key is derived from `secrets.pagination.current`
+(or `secrets.default.current` as a fallback).
+
+Page tokens are tenant-scoped: a token issued under tenant A returns `page token network mismatch` if replayed against tenant B.
+
+Rotating the pagination secret invalidates outstanding tokens unless the previous secret remains in the `retired` list. Keep the
+previous secret in `retired` for at least the longest paging session you expect (typically a few minutes).
+
+## Secret rotation
+
+1. Move the existing `current` value into the `retired` list.
+2. Set a new `current` value generated with a cryptographically secure RNG.
+3. Either restart Talos or wait for config hot-reload to pick up the change.
+
+```yaml
+secrets:
+ hmac:
+ current: "newly-rotated-hmac-secret-padded-to-64-random-chars--------"
+ retired:
+ - "previous-hmac-secret-still-trusted-during-verification-padded--"
+```
+
+During verification, Talos tries `current` first, then each entry in `retired` in order. New keys are always issued with
+`current`. Remove a value from `retired` only after every key issued with it has expired or been rotated.
+
+## Generating secrets
+
+```bash
+openssl rand -base64 48 | tr -d '\n+/=' | cut -c1-64
+```
+
+This emits a 64-character URL-safe value suitable for either secret family.
+
+## Environment variables
+
+```bash
+export TALOS_SECRETS_HMAC_CURRENT="64-char-hmac-secret-required-for-startup"
+export TALOS_SECRETS_HMAC_RETIRED="previous-hmac-secret-1,previous-hmac-secret-2"
+export TALOS_SECRETS_PAGINATION_CURRENT="64-char-pagination-token-secret"
+export TALOS_SECRETS_PAGINATION_RETIRED="previous-pagination-secret-1"
+# Legacy fallback; prefer TALOS_SECRETS_PAGINATION_CURRENT
+export TALOS_SECRETS_DEFAULT_CURRENT="64-char-fallback-pagination-secret"
+```
+
+Inject these from a secrets manager (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager, or Kubernetes `Secret`); never
+check secrets into version control.
diff --git a/docs/talos/operate/security-hardening.md b/docs/talos/operate/security-hardening.md
new file mode 100644
index 000000000..0f08c2686
--- /dev/null
+++ b/docs/talos/operate/security-hardening.md
@@ -0,0 +1,68 @@
+---
+title: Security hardening
+---
+
+# Security hardening
+
+## Network
+
+- **Restrict admin plane access** to internal networks only. The admin plane handles key issuance and revocation and should never
+ be exposed to the public internet.
+- **Use TLS** for all connections. Configure database `sslmode=verify-full` and serve HTTPS (or terminate TLS at the load
+ balancer).
+- **Separate admin and data planes** in production for independent security boundaries.
+
+## Secrets
+
+- **Configure both required secrets** before starting Talos: `secrets.default.current` (pagination tokens) and
+ `secrets.hmac.current` (API key checksums and macaroon root keys). Both must be at least 32 characters; aim for 64 random
+ characters.
+- **Generate secrets cryptographically**: `openssl rand -base64 48 | tr -d '\n+/=' | cut -c1-64`.
+- **Rotate secrets regularly** by promoting `current` to `retired` and setting a new `current`. Verification tries `current`
+ first, then every value in `retired`, so existing keys keep working through the rotation window.
+- **Never commit secrets** to version control. Inject them via environment variables (`TALOS_SECRETS_DEFAULT_CURRENT`,
+ `TALOS_SECRETS_HMAC_CURRENT`) or a secrets manager.
+
+## API keys
+
+- **Set TTL on all keys** to limit exposure from leaked credentials.
+- **Revoke compromised keys immediately** using `POST /v2alpha1/admin/apiKeys/{key_id}:revoke`. The same endpoint handles both
+ issued and imported keys.
+- **Limit scopes** on issued and imported keys to the minimum required. Talos stores scopes as metadata on the key and returns
+ them on verification; your application is responsible for enforcing them during request handling.
+- **Bind keys to caller IPs** with `ip_restriction.allowed_cidrs` to reduce blast radius if a key leaks. See
+ [IP restrictions](../integrate/ip-restrictions.mdx).
+
+## Caching
+
+- **Enable caching** to protect the database from verification floods (DoS).
+- **Set appropriate TTL** balancing latency of revocation propagation vs. database load.
+
+## Monitoring
+
+- **Monitor verification error rates** for anomalous patterns (credential stuffing, brute force).
+- **Enable tracing** to audit key usage and identify suspicious activity.
+- **Set up alerts** on `http_requests_total{code=~"4.."}` and `http_requests_total{code=~"5.."}`.
+
+## Admin plane authentication
+
+**Talos ships no built-in authentication for the admin plane.** Any caller that can reach the admin HTTP listener can issue,
+update, and revoke keys for any tenant. Treat the admin plane as a trusted internal service and put authentication in front of it.
+
+Recommended patterns:
+
+- **Identity-aware proxy (IAP)**: terminate authentication at a gateway (Google Cloud IAP, AWS ALB with Cognito, Cloudflare
+ Access, oauth2-proxy) and forward only authenticated requests to the admin plane. Pin the admin listener to a private network so
+ requests cannot bypass the gateway.
+- **mTLS at the load balancer**: require client certificates issued by an internal CA. Reject unauthenticated TLS handshakes at
+ the LB, then forward plain HTTP to the admin plane on a private network.
+- **Service mesh policy**: in Kubernetes, use Istio `AuthorizationPolicy` or Linkerd authorization policies to allow only specific
+ service accounts to call the admin plane.
+
+Whichever pattern you choose:
+
+- Bind the admin listener to a non-routable address (`127.0.0.1`, `10.x`, or a Kubernetes `ClusterIP`); never expose it to the
+ public internet.
+- Run the data plane on a separate listener so verification traffic does not need to traverse the admin auth path. See
+ [Separate admin and data planes](deploy/separate-planes.md).
+- Audit-log every admin call at the gateway. Talos itself does not record caller identity.
diff --git a/docs/talos/operate/tls.md b/docs/talos/operate/tls.md
new file mode 100644
index 000000000..5e108ed27
--- /dev/null
+++ b/docs/talos/operate/tls.md
@@ -0,0 +1,17 @@
+---
+title: TLS configuration
+---
+
+# TLS configuration
+
+Talos does not have built-in TLS support for its HTTP server. Use a reverse proxy (nginx, Envoy, Caddy) for TLS termination:
+
+```
+Client --[HTTPS]--> Load Balancer --[HTTP]--> Talos
+```
+
+For database connection encryption, see the TLS section in each database guide:
+
+- [PostgreSQL TLS](database/postgresql.md#tls--ssl)
+- [MySQL TLS](database/mysql.md#tls--ssl)
+- [CockroachDB TLS](database/cockroachdb.md#dsn-parameters-connection-pooling-and-tls)
diff --git a/docs/talos/operate/troubleshooting.md b/docs/talos/operate/troubleshooting.md
new file mode 100644
index 000000000..8fa97a203
--- /dev/null
+++ b/docs/talos/operate/troubleshooting.md
@@ -0,0 +1,82 @@
+---
+title: Troubleshooting
+---
+
+# Troubleshooting
+
+
+
+
+## Common issues
+
+### Connection refused on port 4420
+
+The server is not running or is bound to a different interface.
+
+
+
+```bash
+# Check if Talos is listening
+curl -sf "$TALOS_URL/health/alive"
+```
+
+Verify `serve.http.host` and `serve.http.port` in your config.
+
+### Migration failures
+
+```bash
+# Check migration status
+talos migrate status --database "sqlite:///path/to/db"
+```
+
+If a migration failed partway through, inspect the database schema and retry with `talos migrate up`.
+
+### Secret too short
+
+```
+Error: secret must be at least 32 characters
+```
+
+Set `secrets.default.current` to a string of at least 32 characters.
+
+### Key verification returns not found
+
+1. Verify the key was issued on the same Talos instance (or shared database)
+2. Check if the key has been revoked: `GET /v2alpha1/admin/issuedApiKeys/{key_id}`
+3. If using caching, try with `Cache-Control: no-cache` header
+4. For multi-tenant deployments, verify the request hostname matches the tenant where the key was issued
+
+### Invalid API key format
+
+The credential does not match the `prefix_v1_identifier_checksum` format. Check that the full secret (not the key_id) is being
+sent.
+
+## Debug logging
+
+Enable debug logs for more detail:
+
+```yaml
+log:
+ level: "debug"
+ format: "json"
+```
+
+Or via environment variable:
+
+```bash
+export TALOS_LOG_LEVEL=debug
+```
+
+## Health check debugging
+
+
+
+```bash
+# Liveness
+curl -s "$TALOS_URL/health/alive" | jq .
+
+# Readiness
+curl -s "$TALOS_URL/health/ready" | jq .
+```
+
+If readiness fails, the database connection may be down.
diff --git a/docs/talos/quickstart/docker-commercial.mdx b/docs/talos/quickstart/docker-commercial.mdx
new file mode 100644
index 000000000..d149f8f79
--- /dev/null
+++ b/docs/talos/quickstart/docker-commercial.mdx
@@ -0,0 +1,117 @@
+---
+title: Docker quickstart (Commercial)
+tags: [commercial]
+sidebar_custom_props:
+ badge: Commercial
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Docker quickstart (Commercial)
+
+Run the Commercial edition with PostgreSQL and Redis using Docker Compose.
+
+
+
+
+## Start the stack
+
+```bash
+docker compose -f docker-compose.commercial.yaml up -d
+```
+
+This starts Talos, PostgreSQL, and Redis. Migrations run automatically.
+
+## Issue a key
+
+
+
+
+
+
+```bash
+# Note: rate_limit_policy is only available via the HTTP API.
+RESPONSE=$(talos keys issue "commercial-test" \
+ --actor user_1 \
+ --scopes "read,write" \
+ --ttl 168h \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "commercial-test",
+ "actor_id": "user_1",
+ "scopes": ["read", "write"],
+ "ttl": "168h",
+ "rate_limit_policy": {
+ "quota": 1000,
+ "window": "60s"
+ }
+ }')
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+```
+
+
+
+
+## Verify with caching
+
+The first request hits the database; subsequent requests within the cache TTL are served from Redis:
+
+
+
+
+
+
+```bash
+talos keys verify "$API_SECRET" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\":\"$API_SECRET\"}" | jq .
+```
+
+
+
+
+## Stop the stack
+
+```bash
+docker compose -f docker-compose.commercial.yaml down
+```
+
+To remove all data volumes:
+
+```bash
+docker compose -f docker-compose.commercial.yaml down -v
+```
+
+## Prerequisites
+
+You need Docker and Docker Compose installed. See the [OSS quickstart](./index.mdx) to try the free edition first.
+
+## Next steps
+
+- [Quickstart (OSS)](./index.mdx) — simpler setup with SQLite
+- [Architecture](../concepts/architecture.md) — admin and data plane design
+- [Caching](../concepts/caching.md) — cache behavior and consistency model
diff --git a/docs/talos/quickstart/index.mdx b/docs/talos/quickstart/index.mdx
new file mode 100644
index 000000000..e5816af1b
--- /dev/null
+++ b/docs/talos/quickstart/index.mdx
@@ -0,0 +1,209 @@
+---
+title: Quickstart
+description: Issue and verify your first API key in 5 minutes
+---
+
+import Tabs from "@theme/Tabs"
+import TabItem from "@theme/TabItem"
+
+# Quickstart
+
+This guide walks you through issuing, verifying, and revoking an API key with Ory Talos using Docker Compose. You need Docker.
+Examples use the Talos CLI (with curl as an alternative).
+
+
+
+
+## Start the server
+
+```bash
+docker compose -f docker-compose.oss.yaml up --build -d
+```
+
+This starts Talos with SQLite, Jaeger for tracing, and the Admin UI (available at http://localhost:3001). Migrations run
+automatically.
+
+Wait for the server to become healthy:
+
+```bash
+# Wait for the health endpoint
+for i in $(seq 1 30); do
+ if curl -sf http://localhost:8080/health/alive > /dev/null 2>&1; then
+ echo "Server is ready"
+ break
+ fi
+ sleep 1
+done
+```
+
+The server listens on `http://localhost:8080`. Check it's running:
+
+
+
+```bash
+curl -sf "$TALOS_URL/health/alive" | head -c 200
+```
+
+## Issue an API key
+
+Create an API key through the admin plane:
+
+
+
+
+
+
+```bash
+RESPONSE=$(talos keys issue "My first key" \
+ --actor quickstart-user \
+ --scopes "read:*,write:*" \
+ --ttl 168h \
+ --format json \
+ -e "$TALOS_URL" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+```bash
+# Issue a key and capture the response
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "My first key",
+ "actor_id": "quickstart-user",
+ "scopes": ["read:*", "write:*"],
+ "ttl": "168h"
+ }')
+
+echo "$RESPONSE" | jq .
+
+# Save the secret and key ID for later steps
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+The response contains two parts:
+
+- `issued_api_key` / `id` — the key metadata (ID, name, actor, scopes, expiration).
+- `secret` — the full API key credential. This value is shown once. Store it securely.
+
+## Verify the key
+
+Send the secret to the data plane verify endpoint:
+
+
+
+
+
+
+```bash
+talos keys verify "$API_SECRET" -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+VERIFY_RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\":\"$API_SECRET\"}")
+
+echo "$VERIFY_RESPONSE" | jq .
+```
+
+
+
+
+The response confirms the key is active and returns the associated metadata (actor, scopes, expiration).
+
+## Revoke the key
+
+Revoke the key through the admin plane using its ID:
+
+
+
+
+
+
+```bash
+talos keys revoke "$KEY_ID" --reason superseded -e "$TALOS_URL"
+```
+
+
+
+
+```bash
+curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys/${KEY_ID}:revoke" \
+ -H "Content-Type: application/json" \
+ -d '{"reason":"REVOCATION_REASON_SUPERSEDED"}'
+echo ""
+echo "Key revoked"
+```
+
+
+
+
+Verify that the revoked key no longer passes verification:
+
+
+
+
+
+
+```bash
+talos keys verify "$API_SECRET" --no-cache -e "$TALOS_URL" || true
+echo "Revocation confirmed"
+```
+
+
+
+
+```bash
+REVOKE_CHECK=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -H "Cache-Control: no-cache" \
+ -d "{\"credential\":\"$API_SECRET\"}")
+
+echo "$REVOKE_CHECK" | jq .
+
+# Verify the key is no longer active
+if echo "$REVOKE_CHECK" | jq -e '.is_active == false' > /dev/null 2>&1; then
+ echo "Revocation confirmed"
+else
+ echo "ERROR: Key should have been revoked"
+ exit 1
+fi
+```
+
+
+
+
+Revocation is immediate. Even though the key is cryptographically valid, the server checks the revocation list on every
+verification request.
+
+## Stop the server
+
+```bash
+docker compose -f docker-compose.oss.yaml down
+```
+
+To remove all data volumes:
+
+```bash
+docker compose -f docker-compose.oss.yaml down -v
+```
+
+## Next steps
+
+- **[Integration guide](../integrate/index.md)** — detailed API walkthrough for all credential operations
+- **[Operations guide](../operate/index.md)** — install, configure, and deploy Talos in production
+- **[Architecture](../concepts/architecture.md)** — how the admin and data planes work
diff --git a/docs/talos/quickstart/preview.mdx b/docs/talos/quickstart/preview.mdx
new file mode 100644
index 000000000..2a863e3a2
--- /dev/null
+++ b/docs/talos/quickstart/preview.mdx
@@ -0,0 +1,357 @@
+---
+title: Early-access quickstart
+---
+
+```mdx-code-block
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
+```
+
+# Quickstart (early access)
+
+Talos is Ory's API key management service. This guide shows how to pull the public early-access commercial image, start a local
+Postgres-backed Talos instance, and run the headline flows for issued and imported API keys. You only need Docker for the bring-up
+steps below; the `curl` examples are the preview baseline, and the Talos CLI is shown as an optional alternative.
+
+## Set up credentials
+
+1. Download `keyfile.json` from the email you received.
+2. Authenticate with Google Cloud:
+ ```bash
+ gcloud auth activate-service-account --key-file=keyfile.json
+ gcloud auth configure-docker europe-docker.pkg.dev
+ ```
+
+## Pull the image
+
+```bash
+docker pull europe-docker.pkg.dev/ory-artifacts/ory-enterprise-talos/talos-oel:26.2.8
+```
+
+## Start Postgres
+
+```bash
+docker network create talos-preview
+docker run -d --name talos-postgres --network talos-preview \
+ -e POSTGRES_USER=talos -e POSTGRES_PASSWORD=talos -e POSTGRES_DB=talos \
+ -p 5432:5432 postgres:16-alpine
+```
+
+## Configure Talos
+
+Create `config.yaml` in your working directory:
+
+```yaml
+serve:
+ http: { host: "0.0.0.0", port: 8080 }
+ metrics: { host: "0.0.0.0", port: 4422 }
+
+credentials:
+ issuer: "http://localhost:8080"
+ api_keys:
+ default_ttl: "720h"
+ prefix: { current: "talos" }
+ derived_tokens:
+ default_ttl: "1h"
+ jwt:
+ signing_keys:
+ urls:
+ - "base64://eyAgImtleXMiOiBbICAgIHsgICAgICAiYWxnIjogIkVkRFNBIiwgICAgICAiY3J2IjogIkVkMjU1MTkiLCAgICAgICJkIjogIjl3VTNfV3p0dmx3TXg0SGlfN2dsSVduY09XNlVIR2I5amxDdDZEZkVGa2MiLCAgICAgICJraWQiOiAiZG9ja2VyLWRldi0wMDEiLCAgICAgICJrdHkiOiAiT0tQIiwgICAgICAidXNlIjogInNpZyIsICAgICAgIngiOiAiNGtTQTdtNU5jYnFDUC1mZk9fNGhQM2tsNHB0NGctLTNRQ21zQmwzb05lVSIgICAgfSAgXX0="
+ macaroon:
+ prefix: { current: "mc" }
+
+db:
+ dsn: "postgres://talos:talos@talos-postgres:5432/talos?sslmode=disable"
+
+secrets:
+ default: { current: "preview-default-secret-minimum-32-chars-long" }
+ hmac: { current: "preview-hmac-secret-minimum-32-chars-long" }
+ pagination: { current: "preview-pagination-secret-32-chars-min" }
+
+cache: { type: "memory", ttl: "5m" }
+multitenancy: { enabled: false }
+log: { level: "info", format: "json" }
+```
+
+:::caution
+
+This config embeds the development EdDSA JWK from `deployments/docker/config/config.yaml`. Replace it before any non-preview use
+because the private key is published in the source tree.
+
+:::
+
+## Run database migrations
+
+Initialize the Postgres schema before the first server start:
+
+```bash
+docker run --rm --network talos-preview \
+ europe-docker.pkg.dev/ory-artifacts/ory-enterprise-talos/talos-oel:26.2.8 \
+ migrate up --database "postgres://talos:talos@talos-postgres:5432/talos?sslmode=disable"
+```
+
+## Start Talos
+
+```bash
+docker run -d --name talos --network talos-preview \
+ -p 8080:8080 -p 4422:4422 \
+ -v "$PWD/config.yaml:/etc/talos/config.yaml:ro" \
+ europe-docker.pkg.dev/ory-artifacts/ory-enterprise-talos/talos-oel:26.2.8 \
+ serve --config /etc/talos/config.yaml
+```
+
+This starts a single-tenant Talos commercial server with in-memory cache.
+
+## Wait for the server to become ready
+
+```bash
+# Wait for the health endpoint
+for i in $(seq 1 30); do
+ if curl -sf http://localhost:8080/health/alive > /dev/null 2>&1; then
+ echo "Server is ready"
+ break
+ fi
+ sleep 1
+done
+```
+
+The bring-up commands above are for local preview users. The executable API examples below are tested in CI against the same
+published image, running on the `talos-preview` Docker network.
+
+
+
+
+Set the base URL for the local server:
+
+```bash
+export TALOS_URL="${TALOS_URL:-http://localhost:8080}"
+```
+
+## Issue an API key
+
+Create an issued key on the admin plane and save its secret for later steps. For the complete field reference, see the
+[IssueAPIKey API reference](../reference/api/admin-issue-api-key.api.mdx).
+
+
+
+
+
+
+```bash
+RESPONSE=$(docker run --rm --network talos-preview \
+ europe-docker.pkg.dev/ory-artifacts/ory-enterprise-talos/talos-oel:26.2.8 \
+ keys issue "preview-issued-key" \
+ --actor preview-user \
+ --scopes "read:profile,write:profile" \
+ --ttl 720h \
+ --format json \
+ -e "http://talos:8080" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/issuedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "name": "preview-issued-key",
+ "actor_id": "preview-user",
+ "scopes": ["read:profile", "write:profile"],
+ "ttl": "720h"
+ }')
+
+echo "$RESPONSE" | jq .
+
+export API_SECRET=$(echo "$RESPONSE" | jq -er '.secret')
+export KEY_ID=$(echo "$RESPONSE" | jq -er '.issued_api_key.key_id')
+```
+
+
+
+
+The response returns `issued_api_key` metadata plus `secret`, which is shown only once. Store the secret securely.
+
+## Verify the issued key
+
+Send the issued key secret to the unified verify endpoint. For the full response fields and error codes, see the
+[VerifyAPIKey API reference](../reference/api/admin-verify-api-key.api.mdx).
+
+
+
+
+
+
+```bash
+docker run --rm --network talos-preview \
+ europe-docker.pkg.dev/ory-artifacts/ory-enterprise-talos/talos-oel:26.2.8 \
+ keys verify "$API_SECRET" -e "http://talos:8080"
+```
+
+
+
+
+```bash
+VERIFY_RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\":\"$API_SECRET\"}")
+
+echo "$VERIFY_RESPONSE" | jq .
+```
+
+
+
+
+An active result includes `is_active: true` plus the key's actor, scopes, issuer, and expiration.
+
+## Derive a JWT from the issued key
+
+Mint a short-lived JWT from the issued key with a custom claim. For the full request and response schema, see the
+[DeriveToken API reference](../reference/api/admin-derive-token.api.mdx).
+
+
+
+
+
+
+```bash
+RESPONSE=$(docker run --rm --network talos-preview \
+ europe-docker.pkg.dev/ory-artifacts/ory-enterprise-talos/talos-oel:26.2.8 \
+ keys derive-token "$API_SECRET" \
+ --algorithm jwt \
+ --ttl 1h \
+ --claims '{"role":"preview-user","environment":"demo"}' \
+ --format json \
+ -e "http://talos:8080" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export JWT_TOKEN=$(echo "$RESPONSE" | jq -er '.token.token')
+```
+
+
+
+
+```bash
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:derive" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"credential\": \"$API_SECRET\",
+ \"algorithm\": \"TOKEN_ALGORITHM_JWT\",
+ \"ttl\": \"1h\",
+ \"custom_claims\": {\"role\": \"preview-user\", \"environment\": \"demo\"}
+ }")
+
+echo "$RESPONSE" | jq .
+
+export JWT_TOKEN=$(echo "$RESPONSE" | jq -er '.token.token')
+```
+
+
+
+
+The derived token inherits the parent key's permissions and returns as `token.token` with its own expiry metadata.
+
+## Import an existing API key
+
+Import a raw key string into Talos without rotating the credential. For the complete field reference, see the
+[ImportAPIKey API reference](../reference/api/admin-import-api-key.api.mdx).
+
+
+
+
+
+
+```bash
+export IMPORTED_RAW_KEY=sk_preview_demo_001
+
+RESPONSE=$(docker run --rm --network talos-preview \
+ europe-docker.pkg.dev/ory-artifacts/ory-enterprise-talos/talos-oel:26.2.8 \
+ keys imported import "preview-imported-key" \
+ --raw-key "$IMPORTED_RAW_KEY" \
+ --actor preview-import-user \
+ --scopes "payments:read,payments:write" \
+ --ttl 720h \
+ --format json \
+ -e "http://talos:8080" 2>/dev/null)
+
+echo "$RESPONSE" | jq .
+
+export IMPORTED_KEY_ID=$(echo "$RESPONSE" | jq -er '.imported_api_key.key_id')
+```
+
+
+
+
+```bash
+export IMPORTED_RAW_KEY=sk_preview_demo_001
+
+RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/importedApiKeys" \
+ -H "Content-Type: application/json" \
+ -d "{
+ \"raw_key\": \"$IMPORTED_RAW_KEY\",
+ \"name\": \"preview-imported-key\",
+ \"actor_id\": \"preview-import-user\",
+ \"scopes\": [\"payments:read\", \"payments:write\"],
+ \"ttl\": \"720h\"
+ }")
+
+echo "$RESPONSE" | jq .
+
+export IMPORTED_KEY_ID=$(echo "$RESPONSE" | jq -er '.imported_api_key.key_id')
+```
+
+
+
+
+Talos stores a cryptographic representation of the imported credential. The raw key is never returned after import.
+
+## Verify the imported key
+
+Imported keys use the same verify endpoint as issued keys. Talos detects the credential type automatically.
+
+
+
+
+
+
+```bash
+docker run --rm --network talos-preview \
+ europe-docker.pkg.dev/ory-artifacts/ory-enterprise-talos/talos-oel:26.2.8 \
+ keys verify "$IMPORTED_RAW_KEY" -e "http://talos:8080"
+```
+
+
+
+
+```bash
+VERIFY_RESPONSE=$(curl -s -X POST "$TALOS_URL/v2alpha1/admin/apiKeys:verify" \
+ -H "Content-Type: application/json" \
+ -d "{\"credential\":\"$IMPORTED_RAW_KEY\"}")
+
+echo "$VERIFY_RESPONSE" | jq .
+```
+
+
+
+
+## Stop the preview
+
+```bash
+docker rm -f talos talos-postgres
+docker network rm talos-preview
+```
+
+## Next steps
+
+- [Issue and verify API keys](../integrate/issue-and-verify.mdx) — issued-key lifecycle in depth
+- [Import existing keys](../integrate/import-keys.mdx) — batch import and hashing behavior
+- [Derive tokens](../integrate/derive-tokens.mdx) — JWT vs macaroon and JWKS usage
+- [Key lifecycle](../integrate/key-lifecycle.mdx) — rotate, update, and revoke credentials
+- [Architecture](../concepts/architecture.md) — admin and data plane separation
+- [Cache configuration](../operate/cache/index.md) — switch from memory cache to Redis
+- [Docker quickstart (Commercial)](./docker-commercial.mdx) — full repo-based compose stack
diff --git a/docs/talos/reference/api/admin-batch-import-api-keys.RequestSchema.json b/docs/talos/reference/api/admin-batch-import-api-keys.RequestSchema.json
new file mode 100644
index 000000000..cd642dad2
--- /dev/null
+++ b/docs/talos/reference/api/admin-batch-import-api-keys.RequestSchema.json
@@ -0,0 +1,102 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "BatchImportAPIKeysRequest imports multiple external API keys in one request.\nThe maximum batch size is 1000 keys.",
+ "properties": {
+ "requests": {
+ "items": {
+ "description": "Example:\n {\n \"raw_key\": \"sk_live_abc123xyz789\",\n \"name\": \"Stripe Production Key\",\n \"actor_id\": \"payment-processor\",\n \"scopes\": [\"read\", \"write\"],\n \"ttl\": \"8760h\", // 1 year (also accepts: 31536000s)\n \"metadata\": {\"source\": \"stripe\", \"environment\": \"production\"}\n }",
+ "properties": {
+ "actor_id": {
+ "description": "actor_id is the identifier of the entity that owns this imported key.\nRequired so every imported key is traceable to an actor for revocation and\naudit queries.",
+ "type": "string"
+ },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "metadata": {
+ "title": "Additional metadata (OPTIONAL)",
+ "type": "object"
+ },
+ "name": {
+ "title": "Human-readable name (REQUIRED)",
+ "type": "string"
+ },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "raw_key": {
+ "title": "The actual key string to import (REQUIRED)",
+ "type": "string"
+ },
+ "request_id": {
+ "title": "Client-controlled idempotency key (AIP-155)",
+ "type": "string"
+ },
+ "scopes": {
+ "items": { "type": "string" },
+ "title": "Scopes for the imported key (OPTIONAL)",
+ "type": "array"
+ },
+ "ttl": {
+ "description": "ttl sets the expiry as a duration from now.\nAccepted formats:\n - Extended: \"1y\" (365d), \"1mo\" (30d), \"1w\" (7d), \"1d\" (24h)\n - Standard Go: \"24h\", \"30m\", \"60s\", \"1h30m\"\n - Compound: \"1y6mo\", \"1d12h\", \"2w3d\"\nApproximations: 1y = 365 days, 1mo = 30 days.\nIf unset, the project default TTL applies. Maximum is ~10 years (315360000s).",
+ "type": "string"
+ },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "title": "ImportAPIKeyRequest imports an external HMAC-based API key",
+ "type": "object"
+ },
+ "title": "Keys to import",
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1BatchImportAPIKeysRequest"
+ }
+ }
+ },
+ "description": "BatchImportAPIKeysRequest imports multiple external API keys in one request.\nThe maximum batch size is 1000 keys.",
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-batch-import-api-keys.StatusCodes.json b/docs/talos/reference/api/admin-batch-import-api-keys.StatusCodes.json
new file mode 100644
index 000000000..723924461
--- /dev/null
+++ b/docs/talos/reference/api/admin-batch-import-api-keys.StatusCodes.json
@@ -0,0 +1,185 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "BatchImportAPIKeysResponse returns per-item results and summary counters.",
+ "properties": {
+ "failure_count": { "format": "int32", "type": "integer" },
+ "results": {
+ "items": {
+ "description": "BatchImportResult contains the result for one key in a batch import request.",
+ "properties": {
+ "error_code": {
+ "default": "BATCH_IMPORT_ERROR_UNSPECIFIED",
+ "description": "BatchImportErrorCode classifies per-item batch import failures.\n\n - BATCH_IMPORT_ERROR_UNSPECIFIED: No error (import succeeded)\n - BATCH_IMPORT_ERROR_INVALID_ARGUMENT: The key data is malformed or missing required fields\n - BATCH_IMPORT_ERROR_ALREADY_EXISTS: A key with this identifier already exists\n - BATCH_IMPORT_ERROR_FAILED_PRECONDITION: State conflict prevents the import\n - BATCH_IMPORT_ERROR_INTERNAL: Server error during import",
+ "enum": [
+ "BATCH_IMPORT_ERROR_UNSPECIFIED",
+ "BATCH_IMPORT_ERROR_INVALID_ARGUMENT",
+ "BATCH_IMPORT_ERROR_ALREADY_EXISTS",
+ "BATCH_IMPORT_ERROR_FAILED_PRECONDITION",
+ "BATCH_IMPORT_ERROR_INTERNAL"
+ ],
+ "type": "string",
+ "title": "v2alpha1BatchImportErrorCode"
+ },
+ "error_message": {
+ "title": "Human-readable failure reason",
+ "type": "string"
+ },
+ "imported_api_key": {
+ "description": "ImportedAPIKey represents an API key imported from an external system.\nThe raw key is hashed (SHA-512/256) and stored. The original key is never retained.",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "expire_time": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "title": "SHA-512/256 hash of credential",
+ "type": "string"
+ },
+ "last_used_time": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": {
+ "items": { "type": "string" },
+ "type": "array"
+ },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1ImportedAPIKey"
+ },
+ "index": {
+ "format": "int32",
+ "title": "Zero-based index in request.requests",
+ "type": "integer"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1BatchImportResult"
+ },
+ "type": "array"
+ },
+ "success_count": { "format": "int32", "type": "integer" }
+ },
+ "type": "object",
+ "title": "v2alpha1BatchImportAPIKeysResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "201": {
+ "content": { "application/json": { "schema": {} } },
+ "description": "Batch import completed. Check per-item results for individual status."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-batch-import-api-keys.api.mdx b/docs/talos/reference/api/admin-batch-import-api-keys.api.mdx
new file mode 100644
index 000000000..e7f021939
--- /dev/null
+++ b/docs/talos/reference/api/admin-batch-import-api-keys.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-batch-import-api-keys
+title: "Batch Import API Keys"
+description: "Imports up to 1000 external API keys in one request. Returns per-item"
+sidebar_label: "Batch Import API Keys"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Imports up to 1000 external API keys in one request. Returns per-item results. If at least one item succeeds, response is 200 OK.
+If all items fail, the endpoint returns a non-200 error.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-batch-verify-api-keys.RequestSchema.json b/docs/talos/reference/api/admin-batch-verify-api-keys.RequestSchema.json
new file mode 100644
index 000000000..7284320ed
--- /dev/null
+++ b/docs/talos/reference/api/admin-batch-verify-api-keys.RequestSchema.json
@@ -0,0 +1,30 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "requests": {
+ "items": {
+ "properties": {
+ "credential": {
+ "title": "API key or derived token (any format: sk_*, JWT, macaroon)",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1VerifyAPIKeyRequest"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1BatchVerifyAPIKeysRequest"
+ }
+ }
+ },
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-batch-verify-api-keys.StatusCodes.json b/docs/talos/reference/api/admin-batch-verify-api-keys.StatusCodes.json
new file mode 100644
index 000000000..b4a72779a
--- /dev/null
+++ b/docs/talos/reference/api/admin-batch-verify-api-keys.StatusCodes.json
@@ -0,0 +1,125 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "results": {
+ "items": {
+ "properties": {
+ "actor_id": { "type": "string" },
+ "error_code": {
+ "default": "VERIFICATION_ERROR_UNSPECIFIED",
+ "description": "- VERIFICATION_ERROR_UNSPECIFIED: No error (key is valid)\n - VERIFICATION_ERROR_INVALID_FORMAT: Credential format is invalid\n - VERIFICATION_ERROR_EXPIRED: Credential has expired\n - VERIFICATION_ERROR_REVOKED: Credential has been revoked\n - VERIFICATION_ERROR_NOT_FOUND: Credential not found in database\n - VERIFICATION_ERROR_SIGNATURE_INVALID: Cryptographic signature verification failed\n - VERIFICATION_ERROR_INTERNAL: Internal server error during verification\n - VERIFICATION_ERROR_IP_NOT_ALLOWED: Request IP is not in the key's allowed CIDR ranges\n - VERIFICATION_ERROR_RATE_LIMITED: Rate limit quota exhausted (commercial-only)",
+ "enum": [
+ "VERIFICATION_ERROR_UNSPECIFIED",
+ "VERIFICATION_ERROR_INVALID_FORMAT",
+ "VERIFICATION_ERROR_EXPIRED",
+ "VERIFICATION_ERROR_REVOKED",
+ "VERIFICATION_ERROR_NOT_FOUND",
+ "VERIFICATION_ERROR_SIGNATURE_INVALID",
+ "VERIFICATION_ERROR_INTERNAL",
+ "VERIFICATION_ERROR_IP_NOT_ALLOWED",
+ "VERIFICATION_ERROR_RATE_LIMITED"
+ ],
+ "title": "VerificationErrorCode provides type-safe error codes for verification failures",
+ "type": "string"
+ },
+ "error_message": {
+ "title": "Human-readable error message (only set if is_active=false)",
+ "type": "string"
+ },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "is_active": { "type": "boolean" },
+ "issuer": {
+ "description": "The configured token issuer for this project. For derived tokens (JWT/macaroon),\nthis matches the iss claim embedded in the verified token.",
+ "type": "string"
+ },
+ "key_id": { "type": "string" },
+ "metadata": { "type": "object" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "rate_limit_remaining": {
+ "description": "Approximate number of requests available before the rate limit is reached\n(commercial-only, only set when enforcement is active).",
+ "format": "int64",
+ "type": "string"
+ },
+ "rate_limit_reset_time": {
+ "description": "Time when the rate limiter returns to full capacity (all quota recovered).",
+ "format": "date-time",
+ "type": "string"
+ },
+ "scopes": {
+ "items": { "type": "string" },
+ "type": "array"
+ },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1VerifyAPIKeyResponse"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1BatchVerifyAPIKeysResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-batch-verify-api-keys.api.mdx b/docs/talos/reference/api/admin-batch-verify-api-keys.api.mdx
new file mode 100644
index 000000000..09f2630c5
--- /dev/null
+++ b/docs/talos/reference/api/admin-batch-verify-api-keys.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-batch-verify-api-keys
+title: "Batch Verify API Keys"
+description: "Verifies multiple credentials in a single request. Efficiently verifies up"
+sidebar_label: "Batch Verify API Keys"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Verifies multiple credentials in a single request. Efficiently verifies up to 100 credentials in parallel. Each credential is
+verified independently; partial failures are returned. Admin access only.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-delete-imported-api-key.ParamsDetails.json b/docs/talos/reference/api/admin-delete-imported-api-key.ParamsDetails.json
new file mode 100644
index 000000000..092cc3116
--- /dev/null
+++ b/docs/talos/reference/api/admin-delete-imported-api-key.ParamsDetails.json
@@ -0,0 +1,11 @@
+{
+ "parameters": [
+ {
+ "description": "SHA512/256 hash of the imported key (REQUIRED)",
+ "in": "path",
+ "name": "key_id",
+ "required": true,
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-delete-imported-api-key.RequestSchema.json b/docs/talos/reference/api/admin-delete-imported-api-key.RequestSchema.json
new file mode 100644
index 000000000..e9fcb6db7
--- /dev/null
+++ b/docs/talos/reference/api/admin-delete-imported-api-key.RequestSchema.json
@@ -0,0 +1 @@
+{ "title": "Body" }
diff --git a/docs/talos/reference/api/admin-delete-imported-api-key.StatusCodes.json b/docs/talos/reference/api/admin-delete-imported-api-key.StatusCodes.json
new file mode 100644
index 000000000..cd80ba989
--- /dev/null
+++ b/docs/talos/reference/api/admin-delete-imported-api-key.StatusCodes.json
@@ -0,0 +1,36 @@
+{
+ "responses": {
+ "200": {
+ "content": { "application/json": { "schema": { "type": "object" } } },
+ "description": "A successful response."
+ },
+ "204": {
+ "content": { "application/json": { "schema": {} } },
+ "description": "Imported key deleted successfully."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-delete-imported-api-key.api.mdx b/docs/talos/reference/api/admin-delete-imported-api-key.api.mdx
new file mode 100644
index 000000000..6ca7bfa1a
--- /dev/null
+++ b/docs/talos/reference/api/admin-delete-imported-api-key.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-delete-imported-api-key
+title: "Delete Imported API Key"
+description: "Permanently deletes an imported key (hard delete). The key is removed from"
+sidebar_label: "Delete Imported API Key"
+hide_title: true
+hide_table_of_contents: true
+api: eJzNVu9u2zYQf5XbAQPsgLbbbN0HDQVmNMHmdsO8JEU/1EHBSCeLDUWq5MmJYQjYQ+wJ9yTDUUpiJ92AfBsggKTI+/e74++4w4JiHkzDxjvMcEmh1o4c2y0UZIkpgnZg6sYHpgKuaQujSodi2B1P4aKi9NtECFT7DRVQBl+vHFcEhWZ9pSNN4X0kOKONv6b5cvGOtlD6ANGX3Gsy3sEoUO7rmlxBxXiKCn1DQcvWosAM50Vt3Ekyuxj86VWhwkYHXRNTiJh93D0K6vyX+auXx7PjVz9ApWMFvgTx7TCos9M/3i/OTk/GqNCIVKO5QoVO14QZXtP2kylQYaAvrQlUYMahJYUxr6jWmO2Qt42cjByMW2PXXcrh2HgXKcr+8YsXMuTeMTmWqW4aa/IU4exzFF93T/X5q8+UM3Zdpx7FNYfY5jnFWLYW7kxNsVN4/OL755j6iu7FPjh9ros9c3ab7BRU6tbys8JqgqSVTQ9K7guSsfSh1owZGsffHaO6i944pjWF3hhrY5OUYarTRBeFETvaLvfVduqRmZ96dU+TpB7BrJANW/nRBM/+qi3nbosPx3QIOq1rilGvn6kzNPk5a27jV9PpoHV021AuWFMIPuxnVdTqtdQ3ig6TvwlUkGOjbcRLhbcTwfJc142l/hZY7daY4dqjQquvyGKGP8si+jbkCd2UZRit3IpXfQpveYX9sqz7qVtxbg05hhWuDVft1TT39cyH7Yy19XHS707WXo6PRaJsXT5UzeFVHeV8C4Od6Zt+VJDDUa9jOl8u3qSZksJbnEAP6niAYyfOmBI+KfkoBMheQz59gsd8uZimIPhfSUM8GYyMh7Ont5S3TKPxj0n1N6/BGdvbXHEgboODsubpqfhSjlbYR3hAJBl8e7PC5JsgwV0PoIgtg3Fs3WiFJ8N9OhAUqd4dERjMOWNXrkPhkpq48sKDvdVEelxhhrPNsbZNpV/OtAQ7u9M6b8w72sbZrueuLhFb6aViDwvv97CFC8mkcLiGyqyrSUMhXUmXE8QEL+T3+EKtnV5TLTURKWxMTlNYMFTaFZZiYlchiX0Ra0rKt7mlDEyMrXFriTYq2FAw5VbWXFENmsH6G7CayeVbBQUFs5HdWPnAE2ukwbC/Jhdh9PbDBWhXwG8618F7N1ZpGaTPiIxOfCXpddKm5suFhBgbaxiMYw984+8iiJkcm8DR0ZNyOjqCv//8CxK8cN+UYpbI8T4wGElgpCB41ixjandqSPMQCg3OK3j74d35OPmbIBgYc3CBbHne+zUYj2TLyeBq0twfT210D+bK20K64APnPGR3vlygwg2F2Of9rm6EzhofudaJqoeO1xcp3DcCAa9vtgfVs8f8/7PXw0DCQjGzxmrjJM422NSE0tX5+ACBwpRduSOH1wcVZkPzv1RY+cgit9uJX++D7Tr5/aWlsMXs46XCjQ5GXwny8g4xUeYFZqW2kf4DutHZ8K4Yw7OfK18N9K5fOcnYRttWVqjkIfPwnOkuO4UV6YJC8rffnOc5Nbwn9qShH/DRyemvpxen2HX/AJB1mfo=
+sidebar_class_name: "delete api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Permanently deletes an imported key (hard delete). The key is removed from the database. Use RevokeAPIKey for soft deletion
+(recommended).
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-derive-token.RequestSchema.json b/docs/talos/reference/api/admin-derive-token.RequestSchema.json
new file mode 100644
index 000000000..0fecc6098
--- /dev/null
+++ b/docs/talos/reference/api/admin-derive-token.RequestSchema.json
@@ -0,0 +1,38 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "algorithm": {
+ "default": "TOKEN_ALGORITHM_UNSPECIFIED",
+ "description": "- TOKEN_ALGORITHM_JWT: JWT with EdDSA (self-contained, signed)\n - TOKEN_ALGORITHM_MACAROON: Macaroon with HMAC (self-contained, caveat-based)",
+ "enum": [
+ "TOKEN_ALGORITHM_UNSPECIFIED",
+ "TOKEN_ALGORITHM_JWT",
+ "TOKEN_ALGORITHM_MACAROON"
+ ],
+ "title": "TokenAlgorithm specifies the cryptographic algorithm used for derived tokens\nNote: API keys (root tokens) are always opaque; this enum is only for DeriveToken",
+ "type": "string"
+ },
+ "credential": {
+ "title": "The API key secret (issued or imported) to derive a token from",
+ "type": "string"
+ },
+ "custom_claims": { "type": "object" },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "ttl": {
+ "description": "ttl sets the expiry as a duration from now.\nAccepted formats:\n - Extended: \"1y\" (365d), \"1mo\" (30d), \"1w\" (7d), \"1d\" (24h)\n - Standard Go: \"24h\", \"30m\", \"60s\", \"1h30m\"\n - Compound: \"1y6mo\", \"1d12h\", \"2w3d\"\nApproximations: 1y = 365 days, 1mo = 30 days.\nIf unset, the project default TTL applies. Maximum is ~10 years (315360000s).",
+ "type": "string"
+ }
+ },
+ "title": "Token derivation messages",
+ "type": "object"
+ }
+ }
+ },
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-derive-token.StatusCodes.json b/docs/talos/reference/api/admin-derive-token.StatusCodes.json
new file mode 100644
index 000000000..a575b397b
--- /dev/null
+++ b/docs/talos/reference/api/admin-derive-token.StatusCodes.json
@@ -0,0 +1,51 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "token": {
+ "properties": {
+ "claims": { "type": "object" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "token": { "type": "string" }
+ },
+ "title": "Token represents a short-lived derived token (JWT or Macaroon)",
+ "type": "object"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1DeriveTokenResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-derive-token.api.mdx b/docs/talos/reference/api/admin-derive-token.api.mdx
new file mode 100644
index 000000000..d2d4b74c4
--- /dev/null
+++ b/docs/talos/reference/api/admin-derive-token.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-derive-token
+title: "Derive Token"
+description: "Mints a short-lived JWT or Macaroon token from an API key. Works with both"
+sidebar_label: "Derive Token"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Mints a short-lived JWT or Macaroon token from an API key. Works with both issued and imported keys. The derived token inherits
+the permissions of the parent API key.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-get-imported-api-key.ParamsDetails.json b/docs/talos/reference/api/admin-get-imported-api-key.ParamsDetails.json
new file mode 100644
index 000000000..092cc3116
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-imported-api-key.ParamsDetails.json
@@ -0,0 +1,11 @@
+{
+ "parameters": [
+ {
+ "description": "SHA512/256 hash of the imported key (REQUIRED)",
+ "in": "path",
+ "name": "key_id",
+ "required": true,
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-get-imported-api-key.RequestSchema.json b/docs/talos/reference/api/admin-get-imported-api-key.RequestSchema.json
new file mode 100644
index 000000000..e9fcb6db7
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-imported-api-key.RequestSchema.json
@@ -0,0 +1 @@
+{ "title": "Body" }
diff --git a/docs/talos/reference/api/admin-get-imported-api-key.StatusCodes.json b/docs/talos/reference/api/admin-get-imported-api-key.StatusCodes.json
new file mode 100644
index 000000000..04385063b
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-imported-api-key.StatusCodes.json
@@ -0,0 +1,125 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "ImportedAPIKey represents an API key imported from an external system.\nThe raw key is hashed (SHA-512/256) and stored. The original key is never retained.",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "title": "SHA-512/256 hash of credential",
+ "type": "string"
+ },
+ "last_used_time": { "format": "date-time", "type": "string" },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1ImportedAPIKey"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-get-imported-api-key.api.mdx b/docs/talos/reference/api/admin-get-imported-api-key.api.mdx
new file mode 100644
index 000000000..2085b100c
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-imported-api-key.api.mdx
@@ -0,0 +1,37 @@
+---
+id: admin-get-imported-api-key
+title: "Get Imported API Key"
+description: "Retrieves details about a specific imported key. Returns metadata about"
+sidebar_label: "Get Imported API Key"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "get api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Retrieves details about a specific imported key. Returns metadata about the imported key. The original raw key is never returned.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-get-issued-api-key.ParamsDetails.json b/docs/talos/reference/api/admin-get-issued-api-key.ParamsDetails.json
new file mode 100644
index 000000000..ab6488057
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-issued-api-key.ParamsDetails.json
@@ -0,0 +1,11 @@
+{
+ "parameters": [
+ {
+ "description": "UUID of the issued key, taken from the path\n(`/v2alpha1/admin/issuedApiKeys/{key_id}`). REQUIRED.",
+ "in": "path",
+ "name": "key_id",
+ "required": true,
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-get-issued-api-key.RequestSchema.json b/docs/talos/reference/api/admin-get-issued-api-key.RequestSchema.json
new file mode 100644
index 000000000..e9fcb6db7
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-issued-api-key.RequestSchema.json
@@ -0,0 +1 @@
+{ "title": "Body" }
diff --git a/docs/talos/reference/api/admin-get-issued-api-key.StatusCodes.json b/docs/talos/reference/api/admin-get-issued-api-key.StatusCodes.json
new file mode 100644
index 000000000..e0def4fa1
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-issued-api-key.StatusCodes.json
@@ -0,0 +1,125 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "IssuedAPIKey represents an API key issued (generated) by Talos.\nRoot keys are opaque v1 format tokens stored in the database.\nDerived tokens (JWT/Macaroon) are created via DeriveToken and are stateless (not stored).",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "description": "Server-generated UUID identifier for the issued key. Used as the path\nparameter on every admin endpoint that operates on this key\n(`/v2alpha1/admin/issuedApiKeys/{key_id}`). Stable for the lifetime of\nthe key; rotation produces a new key_id.",
+ "type": "string"
+ },
+ "last_used_time": { "format": "date-time", "type": "string" },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IssuedAPIKey"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-get-issued-api-key.api.mdx b/docs/talos/reference/api/admin-get-issued-api-key.api.mdx
new file mode 100644
index 000000000..72ad173df
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-issued-api-key.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-get-issued-api-key
+title: "Get Issued API Key"
+description: "Retrieves details about a specific issued API key including its status,"
+sidebar_label: "Get Issued API Key"
+hide_title: true
+hide_table_of_contents: true
+api: eJzNWf1u2zgSf5U5AgfYheyk7W5RaLHAeR03q0238dlJe4uqyNLSyOKGIlWSciIEBu4h7gnvSQ5DyrFju3vtP4dDgcYmh8OZ33xwZvzAcrSZEbUTWrGYzdAZgSu0kKPjQlrgC9044GBrzEQhMhDWNpjDaJrALbYgVCabXKglCGfBOu4aG6XKZrpGGwHe18Jw4h4BVzk0li/RkwnrRGaHcFUiWMwMOhAWFK7QgEHXGIX5kEVM1xgYJDmL2SivhDpHl3gpRtPkAlsWsZobXqFDY1n88WFPqevr5Ax0Aa7EjfS32Ebg+C0qKIyu/FbNXZmq3u8nqxdc1iV/fsLpspNwZFSLC2ztycMttjciX//eH8Js8vfrZDY5IzEF3UQsWMQUr5DFLFCyiBn83AiDOYudaTBiNiux4ix+YK6tidI6I9SSrdefiNjWWlm0tP/i9JT+ZFo5VI4+8rqWIvOAnPxhSb+HHX5PFd8FCQzWBi0qZ4GrrfkCHr0lKoIZ8z4sWrjiUtthqmZaOyKzwA2CrvnnBmH1HAptKu7A6VtUZHRtMAehPIw5d3zBLQ5TdYZGrDDf0PV++XB18ivPuNFa9T3LzCBdCivBIVBfEa13FdonR0GJ1kJPadfd1Ce8a0OO4UTAiWdOGwL7ENOIhUtunCCrPLAgPItZzh0O/Gp0eMg77rceEvWNQfqaBQscGGQ6225DjoVQaCGZDgiwHHiWkapkbaOlJZh3bDVM1YeSsJFS32F+k4ncWB8zWg2wql0bgVaSLP25QetscO1kaqHiLispRrkDidw60ApTNU7OZmC4WqIHu0ZTCecwH8KE2O3dVCFXdBkkU9jREnpcSn9LR94fpuopiQXy2hacBkMetXE+srKoam1cCElYoaEc473b6/JDqvIjTlQ9caKtkxBD7yfN4g/MyEFJ2KzE7NYecZpd9Q6NdYAzBykIugK2wFlwJXdejI6eLm0sgiuF7cw2b2pS0sJCuxKS6eo76OFwOYwgZc9Ph/7fyeuU9b0CyXT1arv/4vT0eZwvXsfxycsXKfPgFtCZ+xH5net7Su9i74NFOKzs0djoFrgxvGXr7YL2AJKPCydpYZMUn7gwceiy3AF8czQrNIPHxAI+DYsclROFQOO9+2lKHsK1DwO7k48fMztoBfQ4tODTMqDKay2UCwYIrwRaotog/23JfO74QuKjVFIUSGEOukgVLdxi+wMY7YJz1kbnTYbkFArvIPAZHssJklt301jMvzGXVOg45dIds3VGWW9emCP2JBBupKiEu6m1FFl7aJgZd/iWKKaeAMLuAgPqxAA8AwgMDrNQqhIFl/M5VDrHKMDd0QoLQgX9hFZceoemxOFjcYGU22xTYQ6LNlVNbZ1BXsGSO7zjrYXeRK10G8FY6iYvJDcYAbps2PdSILHOsELlhl6ITFcVmkxw2cniH64Nnd1RxkJjfZGiBhVW2rSgDcwwFxYWPLtFlVPV4uOz1ndovIQekPPxbAS9c3JjkcEYpQRCEEZyqY1wZdX3kIx1VUtBit4JV0JueOEGAl0xKJ2reS0GJIyXZVAiz9HYwfPTw6T0udHuyFPulwleEkk11YICotim+k3012jgTqhc3xHrR08Tyr367piXNUr4smIT5vR9zyPC1X6Djvt3veCNdDGkbCNAylJ16Uo0sOJS5PR/g9aLk0yu3vjykei7SmawaB3alEVhKWuModUtt2OyBr0OsQnrG3B80HZLm2D2Kgy9kSqtOuFieHVqofccKqEah/0IXr46DSulbkw/gtevvusWct72j0T3V+TLvWjzMYorHd64myeK7Ot1nI5Sz0rkSM874oBM7CsGvHchVGF7bpiqS6oILDq4o9phh6VBbrUi1Kaz5H3ydnI+ufmQXP18Nht9eDdM1S/zy3c+6LOSHroYCoEyhzvu65IKja809tjdkBhDeONJOzd9/jJVwkKjAqMcrPZGCV9JgDthcJDpquZObHLwQihuWlLWaUCVaeoxjibYAyECkt5FKd1N3l+OR1fJ5bub2WQ0v3x3c/1uPp2MkzfJ5IxFBw3Qhtks4POItnWmyVxDmWF7I4QbKetZqhd91pi9GcP3L16fDlPl3zOhwsMf3i3KiBZlMdjhUkh9Z30agQEcCnzEQDH4TmhARVLsa55NBhBqnz2LGKqmYvHH/wrG4f7F5Leb8eWv09nlr8l8cpRk9OZN8jYJS+OfR+/Ov8Bqfj2dzOaTsy9sH9GSfdq395EA27MYuUToPskPvrbyiVhoXZ/6Dik/vxpdXc/3cNrg+UWCnY3R+Cp5P3m6Rtpf7BNO/jGlbvJrlL7Adh7kpRxe59/e36yEFQshhWsPVX6fzJOfkrfJ1W9/GisX2L5/5AI5NfRq2QhbUuJvFlJk0MukoMRueYH90En6pqRr+Hs2FInkxWF7mKppOOqJqZDmkIuiQHogKNEVYtkYX6rVBgtx77PFStiGy06GrEt9P1HQkeIWbEklMmUdyysE7x8nvt+xlgLQttZhBf/+579gC4yv+f34A+9rbRtqNXiBrt1E6pexiuGq62y5hflkPJtc7XnNFzHe23w8vLc+vf7pbTL+Sl/Zmunravzd4cqaTjw1/Ahs41vVopGwmVcMmafr/OgbZhZP659M50+9WCj38sXWg4VyuEQTLvMjqidhzvNchNJzust2vV9m/S2wO5zAfBkd/xQtmmKk2mP5o0JLs61v42nqbBPHR2BW0Ci8rzEjR0JjtNlFm9jyJQ28GPEQ2dig7664tOQX9wPCcs6rWmIYi0mulixmS82oLVmgZDE7py9WNybz6PpuHHqpSl1XrN07qu3oa1GFjyp1IawhZUvhymYxzHR1ok174qj+HnRBv9RE3qcTRaMyWD4d2/Uyd7+pXIbj8DeCDJ6F48PRNBn7TxHlguQMAp79DokHksPP8W4iWoL4R8iGB0iMpsnQi++OjQ5Jho59vyOb3GPWOOyR3E4UnvVffgQlZLgydWE6CUXlhhMSpeilbOnHl5tGNoa/3lFxi8Z4NuuAGp2YGqGcVL2U0ickZzHRUV91ju4C2yTv9fuHtCOab+2S+oUvEAeP2qUOKx1xJ74SMlVrRiPHCl2pabq6ROeHqa5kMfu61tmPPgt9WL1emm6OGEYnpViWgxqNj2uVdTPgjCaAnamg4oovfXcH9C6IDIeQOCi5ymXXixSNlLtHqEvP2kxi7NGnDo/ejShMklr67kqs/NxL34HkDlXWRuCHSrRrS23cQO5PmHyV9jiqDKNrKqhu/RDN5z7/CNDwmmpkYcHWUjgQymlwd3qjgY2JbADPnh145rNn/r0JVeHjlNvGfhL2qBj0PO5RGD3QXxIDo25w1qmCnfAR/PLhYh7mSLvDtE4ElMU8yNVd7ivFTtTdspbe1B2YSy2pYd1JXFvrjqYJi9gKjQ1233gN5cRaW1dxn++7mfg5Oki2vyCE6f1eF/T4cvw//hzRZXJKVie15MLXm42R/iXzgfNxC0HEvHUpRnaDh0Us7sZmnyJWauvo1MMDTYGvjVyvaflzg6Zl8cdPEVtxI6jiCb9tCEufcxYXXFr8E/R6s+53hz78T34COQrN5plUZGjfeLOYuvtbbLc/kaw/rSMWpiJex7A5yjKs3c6xgzriSfI6n1yx9fo/sPZXxA==
+sidebar_class_name: "get api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Retrieves details about a specific issued API key including its status, scopes, expiration, and usage statistics. The secret is
+never returned.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-get-jwks.RequestSchema.json b/docs/talos/reference/api/admin-get-jwks.RequestSchema.json
new file mode 100644
index 000000000..e9fcb6db7
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-jwks.RequestSchema.json
@@ -0,0 +1 @@
+{ "title": "Body" }
diff --git a/docs/talos/reference/api/admin-get-jwks.StatusCodes.json b/docs/talos/reference/api/admin-get-jwks.StatusCodes.json
new file mode 100644
index 000000000..d27627396
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-jwks.StatusCodes.json
@@ -0,0 +1,42 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "jwks": { "title": "JSON Web Key Set", "type": "object" }
+ },
+ "type": "object",
+ "title": "v2alpha1GetJWKSResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-get-jwks.api.mdx b/docs/talos/reference/api/admin-get-jwks.api.mdx
new file mode 100644
index 000000000..ca0847429
--- /dev/null
+++ b/docs/talos/reference/api/admin-get-jwks.api.mdx
@@ -0,0 +1,34 @@
+---
+id: admin-get-jwks
+title: "Get JWKS"
+description: "Returns the JSON Web Key Set for token verification. Provides the public"
+sidebar_label: "Get JWKS"
+hide_title: true
+hide_table_of_contents: true
+api: eJzlVm1r3EYQ/ivTgcKdke+S9CUgCPQwiTmHNMZ2yAfLhL3VSNp4tavujs4+joP+iP7C/pIyK519dkqh9GM/7Yt23p6ZeUZbLCnqYDo23mGOF8R9cBG4ITi7/PgrfKYVvKcNXBJD5QOwvyUHawqmMlqJ1AzOg1+bkgaprl9Zowt3S5sIjqikEtgPEhs4+3w1qIhgYuyphNUGuDERIoW10TQTaxFUILBelVQWrgq+Be1dZeo+JJMwqYylfD7PoGHuYtr5ACsV6ecf8/kcPl0s43QG77y1/i45Vrizz+8vIbJypQolTC7encDrn16+ns4wQ9/RoHpZYo6LsjXulFgkMMNAsfMuUsR8i69evJBFe8fkWLaq6+yIxfxrFBi3GHVDrZJdF0Q3m0H6691tWtmwJczxOcaYIW86+eJXX0kz7nbPb7IH4fUrZbtGvRw9vRjdxJ0IPc3rAmKvNcVY9Rb28cwwvatUb/k/xKR9SbJWPrSKMUfj+IdXj5EYx1RTGIyxMjZJGaY2bVRZGrGj7Pmh2l32zMwvg7rtXm3kYFz9jwB1wbNf9dXCbfDxmQpBpXNLMar6X+oMnb5kxX38W5gd9I7uO9JMJVAIPhyiLWpVHTG/RtFh9EmgkhwbZSPeZHh/LFheqrazEvP1Fq1yNeZYe8zQqhVZzPFUDtH3QSd0284HhknhCi6GFN5zgcORnPalcXXK4f6yaofvrmBtDTmGAmvDTb+aad/OfdjMWVkfj4evx7WX51ORqHqnoR7KbaL5HkZ7s5NhzUDD0SA2W5wvT9JuOgKxFYuCRgZfMrmD/A3o2TdILM6Xs+QpH/ahmJuO92/vSfdME/GJTZV0ffcGnLGDETEjPAZVy7O3YryaFFgTg2jK4fu7ApMHScFuwEJYI9LAfMIUT0grgq8qaxwlD3zPGXwR9wXX2QcVYqPs0kkEE4lwdnZ3GzMoUOwUCFBgMiX+nAfj2LrJUGsT3/N0OiCTXHbGFm6HuxupT2688FGdiKFT3GCO833bz5XAMy8pmDWVQptzoZdZ6tcMjau8lPbTCv0YNnAl2QUTQUFj6ua4o5B612kSfmSjQT+kA1rlVE2t1MkDRy8ZGuVKO3J+1Vt7KGJNRXqjLeWJ5Y2rQcZBNgIqZ26oBcVg/R1YxeT0JoMUinyNjQ98bCWu/biYyOhQroQPSqvgvZtm6Rho7W9FRiV+k/y4q4Zgcb6UEGNnDYNx7IHv/D6CmMuzYzg6+qb6jo7gz9//gIQtPIyFmEsEj4HBJI2vDIJnxbKKG5TB0I5jKDQ6n6WKmiZ/D0fn6ALZ6nLwazQeyVbHo6tJ8/A8DeADmBtvSwrxgJwes7s4X2KGawpxyPu+aIT3Oh+5VYnTnWpF7nRsDXxGaAcz4X/7azAOAqG3eWeVcQJhH2wahKklrx/RzTAVTsLxoS0xw8fGvMmw8ZFFarsVrz4Fu9vJ9W89hQ3m1zcZrlUwaiUpvb7ZZdiQKimkgXBLG5kzWlMnnLBWtk8z7fm8fsIfp2+vcLf7C0hBdG0=
+sidebar_class_name: "get api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Returns the JSON Web Key Set for token verification. Provides the public keys needed to verify JWT tokens issued by this service.
+Keys are loaded from configuration (file://, https://, or base64:// URIs). Follows the JWKS standard (RFC 7517).
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-import-api-key.RequestSchema.json b/docs/talos/reference/api/admin-import-api-key.RequestSchema.json
new file mode 100644
index 000000000..89924c251
--- /dev/null
+++ b/docs/talos/reference/api/admin-import-api-key.RequestSchema.json
@@ -0,0 +1,91 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "Example:\n {\n \"raw_key\": \"sk_live_abc123xyz789\",\n \"name\": \"Stripe Production Key\",\n \"actor_id\": \"payment-processor\",\n \"scopes\": [\"read\", \"write\"],\n \"ttl\": \"8760h\", // 1 year (also accepts: 31536000s)\n \"metadata\": {\"source\": \"stripe\", \"environment\": \"production\"}\n }",
+ "properties": {
+ "actor_id": {
+ "description": "actor_id is the identifier of the entity that owns this imported key.\nRequired so every imported key is traceable to an actor for revocation and\naudit queries.",
+ "type": "string"
+ },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "metadata": {
+ "title": "Additional metadata (OPTIONAL)",
+ "type": "object"
+ },
+ "name": {
+ "title": "Human-readable name (REQUIRED)",
+ "type": "string"
+ },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "raw_key": {
+ "title": "The actual key string to import (REQUIRED)",
+ "type": "string"
+ },
+ "request_id": {
+ "title": "Client-controlled idempotency key (AIP-155)",
+ "type": "string"
+ },
+ "scopes": {
+ "items": { "type": "string" },
+ "title": "Scopes for the imported key (OPTIONAL)",
+ "type": "array"
+ },
+ "ttl": {
+ "description": "ttl sets the expiry as a duration from now.\nAccepted formats:\n - Extended: \"1y\" (365d), \"1mo\" (30d), \"1w\" (7d), \"1d\" (24h)\n - Standard Go: \"24h\", \"30m\", \"60s\", \"1h30m\"\n - Compound: \"1y6mo\", \"1d12h\", \"2w3d\"\nApproximations: 1y = 365 days, 1mo = 30 days.\nIf unset, the project default TTL applies. Maximum is ~10 years (315360000s).",
+ "type": "string"
+ },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "title": "ImportAPIKeyRequest imports an external HMAC-based API key",
+ "type": "object"
+ }
+ }
+ },
+ "description": "Example:\n {\n \"raw_key\": \"sk_live_abc123xyz789\",\n \"name\": \"Stripe Production Key\",\n \"actor_id\": \"payment-processor\",\n \"scopes\": [\"read\", \"write\"],\n \"ttl\": \"8760h\", // 1 year (also accepts: 31536000s)\n \"metadata\": {\"source\": \"stripe\", \"environment\": \"production\"}\n }",
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-import-api-key.StatusCodes.json b/docs/talos/reference/api/admin-import-api-key.StatusCodes.json
new file mode 100644
index 000000000..bcac8f1cd
--- /dev/null
+++ b/docs/talos/reference/api/admin-import-api-key.StatusCodes.json
@@ -0,0 +1,135 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "imported_api_key": {
+ "description": "ImportedAPIKey represents an API key imported from an external system.\nThe raw key is hashed (SHA-512/256) and stored. The original key is never retained.",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "title": "SHA-512/256 hash of credential",
+ "type": "string"
+ },
+ "last_used_time": { "format": "date-time", "type": "string" },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1ImportedAPIKey"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1ImportAPIKeyResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "201": {
+ "content": { "application/json": { "schema": {} } },
+ "description": "API key imported successfully."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-import-api-key.api.mdx b/docs/talos/reference/api/admin-import-api-key.api.mdx
new file mode 100644
index 000000000..949fa5427
--- /dev/null
+++ b/docs/talos/reference/api/admin-import-api-key.api.mdx
@@ -0,0 +1,39 @@
+---
+id: admin-import-api-key
+title: "Import API Key"
+description: "Imports an external API key into the system. Allows importing keys from"
+sidebar_label: "Import API Key"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Imports an external API key into the system. Allows importing keys from legacy systems or external providers. The raw key is
+hashed with SHA-512/256 and only the hash is stored — the raw key is never retained. Imported keys support token derivation
+(JWT/Macaroon) like issued keys.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-issue-api-key.RequestSchema.json b/docs/talos/reference/api/admin-issue-api-key.RequestSchema.json
new file mode 100644
index 000000000..104d67e4a
--- /dev/null
+++ b/docs/talos/reference/api/admin-issue-api-key.RequestSchema.json
@@ -0,0 +1,72 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "actor_id": { "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "request_id": {
+ "title": "Client-controlled idempotency key (AIP-155)",
+ "type": "string"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "ttl": {
+ "description": "ttl sets the expiry as a duration from now.\nAccepted formats:\n - Extended: \"1y\" (365d), \"1mo\" (30d), \"1w\" (7d), \"1d\" (24h)\n - Standard Go: \"24h\", \"30m\", \"60s\", \"1h30m\"\n - Compound: \"1y6mo\", \"1d12h\", \"2w3d\"\nApproximations: 1y = 365 days, 1mo = 30 days.\nIf unset, the project default TTL applies. Maximum is ~10 years (315360000s).",
+ "type": "string"
+ },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IssueAPIKeyRequest"
+ }
+ }
+ },
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-issue-api-key.StatusCodes.json b/docs/talos/reference/api/admin-issue-api-key.StatusCodes.json
new file mode 100644
index 000000000..c5a226f0b
--- /dev/null
+++ b/docs/talos/reference/api/admin-issue-api-key.StatusCodes.json
@@ -0,0 +1,139 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "issued_api_key": {
+ "description": "IssuedAPIKey represents an API key issued (generated) by Talos.\nRoot keys are opaque v1 format tokens stored in the database.\nDerived tokens (JWT/Macaroon) are created via DeriveToken and are stateless (not stored).",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "description": "Server-generated UUID identifier for the issued key. Used as the path\nparameter on every admin endpoint that operates on this key\n(`/v2alpha1/admin/issuedApiKeys/{key_id}`). Stable for the lifetime of\nthe key; rotation produces a new key_id.",
+ "type": "string"
+ },
+ "last_used_time": { "format": "date-time", "type": "string" },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IssuedAPIKey"
+ },
+ "secret": {
+ "title": "Only returned on creation",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IssueAPIKeyResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "201": {
+ "content": { "application/json": { "schema": {} } },
+ "description": "API key issued successfully."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-issue-api-key.api.mdx b/docs/talos/reference/api/admin-issue-api-key.api.mdx
new file mode 100644
index 000000000..b6a5a1095
--- /dev/null
+++ b/docs/talos/reference/api/admin-issue-api-key.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-issue-api-key
+title: "Issue API Key"
+description: "Creates a new API key for a given actor. The secret is returned only once"
+sidebar_label: "Issue API Key"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Creates a new API key for a given actor. The secret is returned only once in the response and cannot be retrieved later. Keys can
+be scoped with specific permissions and have optional expiration.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-list-imported-api-keys.ParamsDetails.json b/docs/talos/reference/api/admin-list-imported-api-keys.ParamsDetails.json
new file mode 100644
index 000000000..76d4d28b3
--- /dev/null
+++ b/docs/talos/reference/api/admin-list-imported-api-keys.ParamsDetails.json
@@ -0,0 +1,22 @@
+{
+ "parameters": [
+ {
+ "description": "Number of items per page (default: 50, max: 1000)",
+ "in": "query",
+ "name": "page_size",
+ "schema": { "format": "int32", "type": "integer" }
+ },
+ {
+ "description": "Cursor token for pagination (OPTIONAL)",
+ "in": "query",
+ "name": "page_token",
+ "schema": { "type": "string" }
+ },
+ {
+ "description": "filter supports AIP-160 filter expressions:\n actor_id=\"user_123\"\n status=KEY_STATUS_ACTIVE\n actor_id=\"user_123\" AND status=KEY_STATUS_ACTIVE",
+ "in": "query",
+ "name": "filter",
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-list-imported-api-keys.RequestSchema.json b/docs/talos/reference/api/admin-list-imported-api-keys.RequestSchema.json
new file mode 100644
index 000000000..e9fcb6db7
--- /dev/null
+++ b/docs/talos/reference/api/admin-list-imported-api-keys.RequestSchema.json
@@ -0,0 +1 @@
+{ "title": "Body" }
diff --git a/docs/talos/reference/api/admin-list-imported-api-keys.StatusCodes.json b/docs/talos/reference/api/admin-list-imported-api-keys.StatusCodes.json
new file mode 100644
index 000000000..52b664487
--- /dev/null
+++ b/docs/talos/reference/api/admin-list-imported-api-keys.StatusCodes.json
@@ -0,0 +1,145 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "imported_api_keys": {
+ "items": {
+ "description": "ImportedAPIKey represents an API key imported from an external system.\nThe raw key is hashed (SHA-512/256) and stored. The original key is never retained.",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "title": "SHA-512/256 hash of credential",
+ "type": "string"
+ },
+ "last_used_time": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": {
+ "items": { "type": "string" },
+ "type": "array"
+ },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1ImportedAPIKey"
+ },
+ "title": "List of imported keys",
+ "type": "array"
+ },
+ "next_page_token": {
+ "title": "Token for fetching the next page (empty if no more results)",
+ "type": "string"
+ }
+ },
+ "title": "ListImportedAPIKeysResponse returns paginated list of imported keys",
+ "type": "object"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-list-imported-api-keys.api.mdx b/docs/talos/reference/api/admin-list-imported-api-keys.api.mdx
new file mode 100644
index 000000000..81af39280
--- /dev/null
+++ b/docs/talos/reference/api/admin-list-imported-api-keys.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-list-imported-api-keys
+title: "List Imported API Keys"
+description: "Lists all imported keys with filtering. Returns imported keys only (not"
+sidebar_label: "List Imported API Keys"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "get api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Lists all imported keys with filtering. Returns imported keys only (not issued keys). Supports pagination and AIP-160 filter
+expressions.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-list-issued-api-keys.ParamsDetails.json b/docs/talos/reference/api/admin-list-issued-api-keys.ParamsDetails.json
new file mode 100644
index 000000000..4a5e5fb84
--- /dev/null
+++ b/docs/talos/reference/api/admin-list-issued-api-keys.ParamsDetails.json
@@ -0,0 +1,22 @@
+{
+ "parameters": [
+ {
+ "description": "Number of items per page (default: 50, max: 1000)",
+ "in": "query",
+ "name": "page_size",
+ "schema": { "format": "int32", "type": "integer" }
+ },
+ {
+ "description": "Cursor token for pagination",
+ "in": "query",
+ "name": "page_token",
+ "schema": { "type": "string" }
+ },
+ {
+ "description": "filter supports AIP-160 filter expressions:\n actor_id=\"user_123\"\n status=KEY_STATUS_ACTIVE\n actor_id=\"user_123\" AND status=KEY_STATUS_ACTIVE",
+ "in": "query",
+ "name": "filter",
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-list-issued-api-keys.RequestSchema.json b/docs/talos/reference/api/admin-list-issued-api-keys.RequestSchema.json
new file mode 100644
index 000000000..e9fcb6db7
--- /dev/null
+++ b/docs/talos/reference/api/admin-list-issued-api-keys.RequestSchema.json
@@ -0,0 +1 @@
+{ "title": "Body" }
diff --git a/docs/talos/reference/api/admin-list-issued-api-keys.StatusCodes.json b/docs/talos/reference/api/admin-list-issued-api-keys.StatusCodes.json
new file mode 100644
index 000000000..533d4a330
--- /dev/null
+++ b/docs/talos/reference/api/admin-list-issued-api-keys.StatusCodes.json
@@ -0,0 +1,141 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "issued_api_keys": {
+ "items": {
+ "description": "IssuedAPIKey represents an API key issued (generated) by Talos.\nRoot keys are opaque v1 format tokens stored in the database.\nDerived tokens (JWT/Macaroon) are created via DeriveToken and are stateless (not stored).",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "description": "Server-generated UUID identifier for the issued key. Used as the path\nparameter on every admin endpoint that operates on this key\n(`/v2alpha1/admin/issuedApiKeys/{key_id}`). Stable for the lifetime of\nthe key; rotation produces a new key_id.",
+ "type": "string"
+ },
+ "last_used_time": {
+ "format": "date-time",
+ "type": "string"
+ },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": {
+ "items": { "type": "string" },
+ "type": "array"
+ },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IssuedAPIKey"
+ },
+ "type": "array"
+ },
+ "next_page_token": { "type": "string" }
+ },
+ "type": "object",
+ "title": "v2alpha1ListIssuedAPIKeysResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-list-issued-api-keys.api.mdx b/docs/talos/reference/api/admin-list-issued-api-keys.api.mdx
new file mode 100644
index 000000000..803470832
--- /dev/null
+++ b/docs/talos/reference/api/admin-list-issued-api-keys.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-list-issued-api-keys
+title: "List Issued API Keys"
+description: "Lists issued API keys with optional filtering. Supports cursor-based"
+sidebar_label: "List Issued API Keys"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "get api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Lists issued API keys with optional filtering. Supports cursor-based pagination and AIP-160 filter expressions. Returns only
+issued (generated) API keys; use ListImportedAPIKeys for imported keys.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-revoke-api-key.ParamsDetails.json b/docs/talos/reference/api/admin-revoke-api-key.ParamsDetails.json
new file mode 100644
index 000000000..ff4e18118
--- /dev/null
+++ b/docs/talos/reference/api/admin-revoke-api-key.ParamsDetails.json
@@ -0,0 +1,11 @@
+{
+ "parameters": [
+ {
+ "description": "Identifier of the key to revoke, taken from the path\n(`POST /v2alpha1/admin/apiKeys/{key_id}:revoke`). For issued keys this is\nthe UUID; for imported keys this is the SHA-512/256 hash. REQUIRED.",
+ "in": "path",
+ "name": "key_id",
+ "required": true,
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-revoke-api-key.RequestSchema.json b/docs/talos/reference/api/admin-revoke-api-key.RequestSchema.json
new file mode 100644
index 000000000..faff6de10
--- /dev/null
+++ b/docs/talos/reference/api/admin-revoke-api-key.RequestSchema.json
@@ -0,0 +1,34 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "description": {
+ "description": "Optional free-text explanation. Only allowed when reason is PRIVILEGE_WITHDRAWN.",
+ "type": "string"
+ },
+ "reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ }
+ },
+ "type": "object",
+ "title": "StaticCredentialsAdminRevokeAPIKeyBody"
+ }
+ }
+ },
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-revoke-api-key.StatusCodes.json b/docs/talos/reference/api/admin-revoke-api-key.StatusCodes.json
new file mode 100644
index 000000000..d3cec6dad
--- /dev/null
+++ b/docs/talos/reference/api/admin-revoke-api-key.StatusCodes.json
@@ -0,0 +1,36 @@
+{
+ "responses": {
+ "200": {
+ "content": { "application/json": { "schema": { "type": "object" } } },
+ "description": "A successful response."
+ },
+ "204": {
+ "content": { "application/json": { "schema": {} } },
+ "description": "API key revoked successfully."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-revoke-api-key.api.mdx b/docs/talos/reference/api/admin-revoke-api-key.api.mdx
new file mode 100644
index 000000000..354b45824
--- /dev/null
+++ b/docs/talos/reference/api/admin-revoke-api-key.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-revoke-api-key
+title: "Revoke API Key"
+description: "Immediately revokes an API key (issued or imported). Once revoked, the key"
+sidebar_label: "Revoke API Key"
+hide_title: true
+hide_table_of_contents: true
+api: eJydV41u2zYQfpUbgQ1OIDtttg6DigLzEqdR08aenTQYqiKlpZPFhSI18pTYCAzsIfaEe5KBpOw4doq2AwxIFI/3fx8/37McbWZETUIrFrOkqjAXnFAuwOCtvkELXEF/lMANLqAjrG0wB21AVLU2hPleD4Yqw1Y6j4BKdLKpyrgCpUFqNUMDU4TGYg6FNsAbKlGRyLgz24OLUljQNRq/BmFBGIO3aKyYSuylahyUO70WuHHWiAu1VpcLgroxtbZoeyxia11JzmLWzyvRquiPkjNcsIjV3PAKCY1l8Yf77SzkzrtCoAFdrAIC0m2QERC/QQWF0ZXfrTmVqep8Gg0nF3Bwe8hlXfLnB9zZPeC1OMOFPbi/wcW1yJdxUPJprwcnLo8hoz4ycnkQNlVO6eVlcvzSx7dK9SMhb3hy2u++eH54cPjiZyi5LXswHvx+mYwHxy4LwsXifGMRU7xCFrPgA4uYwb8aYTBnMZkGI2azEivO4ntGi9pJWjJCzdhy+TEIo6XfdL5wEplWhIrcK69r2Zbx4E/rkne/oao2rhAk0LrVoxxvp3zoX7iEwiB2CecEOK8lV22LDJVcAJdS32EOdyUqMMhtaJbROHmfvB28HlxfJRenx+P+1bkLfysQFwa3K9sFbySxmI0H74dH/YtkeH49HvQnw/Pry/PJaHCUnCSDYxZteemaKEQ7DtZro29FjhYsmSajxmDumyQItT5aEMrWLtswXcD45AheHP7yrJeqSzcQQsFUUwm+W4CrHCzKoruhpZD6zvZSlSrowq7DT4Qfg+/5rlZyEYPStE6dUNvqWcRQNRWLP3wxGbv7Z4M/ro+G70bj4btkMnhSpH9ykrxNwqej0/7568+omlyOBuPJ4Pgz209EyT5uFzliJEi6D6sh3K4YWy7Xh/T0T8xo49CEOInsyKCffy7tDnL4EVgul7sDNO9qI2ZCcTly0HIe5m3q5Z20rbWyYRAOnz37pjF67K63/rgt+2CbLENri0bCylTP2T189tO3mHpKdwv9Lb5vWJILb2I9S/8bGDKdo3sW2lTcDaVQ9OPhwwQLRThDE4wRF9KfEoSVf+F5LgJ4jDbVLqMtM78GdbsI9/mGqI0mPW2KvvJVbMW4MdyvK7SWz75Rp6kz12eNfbKSChqF8xozh/dojDabBXVq+cxdWbu96qZh3nW5nPCqlhguNsnVjMVsplnEJJ+iZDF77RZWNybz2fW3C3RSlVIaSjinlIVlUYVXlVImBSqClM0Elc20l+nqQJvFAXGpbTfsdmfaie+5E0WjsrZrwux0MppDq793FJ4RZLAfzvb6o+TIv0Wu4ZJjCMnca9Nw75xoQT9+Be2h94f9t6PT/vMHwGjx4ktY5bSJAq4j90NjvM7eLgKMkp5PBe1ggYundXWvlfk6AOm0vn+d9H1QnVIAsBh+CEmIwvflyvZgjllD2Nl76cP57hUoIaE9bZAao6CoqDdw2Sw6KQu1cQHE8P1dynwaXOloGSrupEdGKJKqk7KWg8VOMAQdCuIVKyFTtWSOLFRIpXa0q9aWPNOiksXsK2kRi5iDi/ED4xjMfTvvUoY15q/u9S/cX0vHiAr9BPcwC7hwXezIBIdSzMpujcbDkaO21tcJsnWhoOKKz7By82DR3IoMe5AQlFzlEgM1cwC5eUSKArNFJjH2lE+omadzEdyiEcXCranECjiB1HcgOaHKFhHkaMSt27WlNtSV4hZzIH2DykLnzdWFZwzveMaN1mov8kufSneGe6z21OGiRE/jhQVbS0EgFGmgO72KwMZOrAv7+zt9ub8P//79T8tQ1tzaxv5iWAfW/juIwGji5J4tWw4I04aCrfMRvLk6m+x5f30K2tuidQFlMQl+tcY9a2ld3aRYjiBvpLnUMnek/gFvH6rbHyUsYv5vha/7qiPZcvkfK5qLgw==
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Immediately revokes an API key (issued or imported). Once revoked, the key can no longer be used for authentication. This
+operation is irreversible. Revoked keys are retained for audit purposes.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-rotate-issued-api-key.ParamsDetails.json b/docs/talos/reference/api/admin-rotate-issued-api-key.ParamsDetails.json
new file mode 100644
index 000000000..f832c1b78
--- /dev/null
+++ b/docs/talos/reference/api/admin-rotate-issued-api-key.ParamsDetails.json
@@ -0,0 +1,11 @@
+{
+ "parameters": [
+ {
+ "description": "key_id is the ID of the existing API key to rotate",
+ "in": "path",
+ "name": "key_id",
+ "required": true,
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-rotate-issued-api-key.RequestSchema.json b/docs/talos/reference/api/admin-rotate-issued-api-key.RequestSchema.json
new file mode 100644
index 000000000..7e0b94dc4
--- /dev/null
+++ b/docs/talos/reference/api/admin-rotate-issued-api-key.RequestSchema.json
@@ -0,0 +1,77 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "metadata": {
+ "title": "metadata for the new API key (inherits from old key if not provided)",
+ "type": "object"
+ },
+ "name": {
+ "title": "name for the new API key (inherits from old key if not provided)",
+ "type": "string"
+ },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "scopes": {
+ "items": { "type": "string" },
+ "title": "scopes for the new API key (inherits from old key if not provided)",
+ "type": "array"
+ },
+ "update_mask": {
+ "title": "update_mask disambiguates \"not provided\" from \"set to empty\" (AIP-134)",
+ "type": "string"
+ },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "StaticCredentialsAdminRotateIssuedAPIKeyBody"
+ }
+ }
+ },
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-rotate-issued-api-key.StatusCodes.json b/docs/talos/reference/api/admin-rotate-issued-api-key.StatusCodes.json
new file mode 100644
index 000000000..56f9fa53c
--- /dev/null
+++ b/docs/talos/reference/api/admin-rotate-issued-api-key.StatusCodes.json
@@ -0,0 +1,229 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "issued_api_key": {
+ "description": "IssuedAPIKey represents an API key issued (generated) by Talos.\nRoot keys are opaque v1 format tokens stored in the database.\nDerived tokens (JWT/Macaroon) are created via DeriveToken and are stateless (not stored).",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "description": "Server-generated UUID identifier for the issued key. Used as the path\nparameter on every admin endpoint that operates on this key\n(`/v2alpha1/admin/issuedApiKeys/{key_id}`). Stable for the lifetime of\nthe key; rotation produces a new key_id.",
+ "type": "string"
+ },
+ "last_used_time": { "format": "date-time", "type": "string" },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IssuedAPIKey"
+ },
+ "old_issued_api_key": {
+ "description": "IssuedAPIKey represents an API key issued (generated) by Talos.\nRoot keys are opaque v1 format tokens stored in the database.\nDerived tokens (JWT/Macaroon) are created via DeriveToken and are stateless (not stored).",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "description": "Server-generated UUID identifier for the issued key. Used as the path\nparameter on every admin endpoint that operates on this key\n(`/v2alpha1/admin/issuedApiKeys/{key_id}`). Stable for the lifetime of\nthe key; rotation produces a new key_id.",
+ "type": "string"
+ },
+ "last_used_time": { "format": "date-time", "type": "string" },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IssuedAPIKey"
+ },
+ "secret": {
+ "title": "secret is the new API key secret (only returned once, never retrievable again)",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RotateIssuedAPIKeyResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "201": {
+ "content": { "application/json": { "schema": {} } },
+ "description": "API key rotated successfully. New key issued, old key revoked."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-rotate-issued-api-key.api.mdx b/docs/talos/reference/api/admin-rotate-issued-api-key.api.mdx
new file mode 100644
index 000000000..e318846ae
--- /dev/null
+++ b/docs/talos/reference/api/admin-rotate-issued-api-key.api.mdx
@@ -0,0 +1,45 @@
+---
+id: admin-rotate-issued-api-key
+title: "Rotate Issued API Key"
+description: "Generates a new secret for an issued API key. Creates a new API key with a"
+sidebar_label: "Rotate Issued API Key"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Generates a new secret for an issued API key. Creates a new API key with a new key_id and secret, and immediately revokes the old
+key. This is the recommended way to update scopes, metadata, or rotate credentials.
+
+For zero-downtime rotation, use this workflow instead:
+
+1. IssueAPIKey with new credentials
+2. Deploy new secret to all services
+3. Verify new secret works everywhere
+4. RevokeAPIKey to remove the old key
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-update-imported-api-key.ParamsDetails.json b/docs/talos/reference/api/admin-update-imported-api-key.ParamsDetails.json
new file mode 100644
index 000000000..5881cc93c
--- /dev/null
+++ b/docs/talos/reference/api/admin-update-imported-api-key.ParamsDetails.json
@@ -0,0 +1,11 @@
+{
+ "parameters": [
+ {
+ "description": "SHA512/256 hash of the imported key (REQUIRED, path param)",
+ "in": "path",
+ "name": "key_id",
+ "required": true,
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-update-imported-api-key.RequestSchema.json b/docs/talos/reference/api/admin-update-imported-api-key.RequestSchema.json
new file mode 100644
index 000000000..699ee88f6
--- /dev/null
+++ b/docs/talos/reference/api/admin-update-imported-api-key.RequestSchema.json
@@ -0,0 +1,56 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "update_mask": {
+ "title": "AIP-134 partial update mask",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "StaticCredentialsAdminUpdateImportedAPIKeyBody"
+ }
+ }
+ },
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-update-imported-api-key.StatusCodes.json b/docs/talos/reference/api/admin-update-imported-api-key.StatusCodes.json
new file mode 100644
index 000000000..04385063b
--- /dev/null
+++ b/docs/talos/reference/api/admin-update-imported-api-key.StatusCodes.json
@@ -0,0 +1,125 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "ImportedAPIKey represents an API key imported from an external system.\nThe raw key is hashed (SHA-512/256) and stored. The original key is never retained.",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "title": "SHA-512/256 hash of credential",
+ "type": "string"
+ },
+ "last_used_time": { "format": "date-time", "type": "string" },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1ImportedAPIKey"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-update-imported-api-key.api.mdx b/docs/talos/reference/api/admin-update-imported-api-key.api.mdx
new file mode 100644
index 000000000..afc393f48
--- /dev/null
+++ b/docs/talos/reference/api/admin-update-imported-api-key.api.mdx
@@ -0,0 +1,37 @@
+---
+id: admin-update-imported-api-key
+title: "Update Imported API Key"
+description: "Updates metadata, scopes, or rate limits of an imported key. Supports"
+sidebar_label: "Update Imported API Key"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "patch api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Updates metadata, scopes, or rate limits of an imported key. Supports partial updates via update_mask (AIP-134).
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-update-issued-api-key.ParamsDetails.json b/docs/talos/reference/api/admin-update-issued-api-key.ParamsDetails.json
new file mode 100644
index 000000000..258b04452
--- /dev/null
+++ b/docs/talos/reference/api/admin-update-issued-api-key.ParamsDetails.json
@@ -0,0 +1,11 @@
+{
+ "parameters": [
+ {
+ "description": "UUID of the issued key to update, taken from the path\n(`PATCH /v2alpha1/admin/issuedApiKeys/{key_id}`). REQUIRED.",
+ "in": "path",
+ "name": "key_id",
+ "required": true,
+ "schema": { "type": "string" }
+ }
+ ]
+}
diff --git a/docs/talos/reference/api/admin-update-issued-api-key.RequestSchema.json b/docs/talos/reference/api/admin-update-issued-api-key.RequestSchema.json
new file mode 100644
index 000000000..42ac28014
--- /dev/null
+++ b/docs/talos/reference/api/admin-update-issued-api-key.RequestSchema.json
@@ -0,0 +1,53 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "update_mask": { "type": "string" }
+ },
+ "type": "object",
+ "title": "StaticCredentialsAdminUpdateIssuedAPIKeyBody"
+ }
+ }
+ },
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-update-issued-api-key.StatusCodes.json b/docs/talos/reference/api/admin-update-issued-api-key.StatusCodes.json
new file mode 100644
index 000000000..e0def4fa1
--- /dev/null
+++ b/docs/talos/reference/api/admin-update-issued-api-key.StatusCodes.json
@@ -0,0 +1,125 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "IssuedAPIKey represents an API key issued (generated) by Talos.\nRoot keys are opaque v1 format tokens stored in the database.\nDerived tokens (JWT/Macaroon) are created via DeriveToken and are stateless (not stored).",
+ "properties": {
+ "actor_id": { "type": "string" },
+ "create_time": { "format": "date-time", "type": "string" },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "ip_restriction": {
+ "description": "IPRestriction defines IP-based access controls for an API key.\nWhen allowed_cidrs is non-empty, only requests from IPs matching at least one\nCIDR range are permitted. Empty allowed_cidrs means no IP restriction (all IPs allowed).\nIP restrictions apply to root API key and imported key verification only;\nderived tokens (JWT/macaroon) are stateless and not subject to IP checks.",
+ "properties": {
+ "allowed_cidrs": {
+ "description": "allowed_cidrs is a list of CIDR ranges that are allowed to use this key.\nSupports both IPv4 (e.g., \"10.0.0.0/8\") and IPv6 (e.g., \"2001:db8::/32\").\nIf empty, all IPs are allowed (no restriction).",
+ "items": { "type": "string" },
+ "type": "array"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IPRestriction"
+ },
+ "key_id": {
+ "description": "Server-generated UUID identifier for the issued key. Used as the path\nparameter on every admin endpoint that operates on this key\n(`/v2alpha1/admin/issuedApiKeys/{key_id}`). Stable for the lifetime of\nthe key; rotation produces a new key_id.",
+ "type": "string"
+ },
+ "last_used_time": { "format": "date-time", "type": "string" },
+ "metadata": { "type": "object" },
+ "name": { "type": "string" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "revocation_description": {
+ "description": "revocation_description provides free-form context for a revocation.\nOnly set when revocation_reason is PRIVILEGE_WITHDRAWN.\nJSON API change: field was formerly revocation_reason_text. Field number 13\nis unchanged so the change is wire-compatible for binary proto encoding.",
+ "type": "string"
+ },
+ "revocation_reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "status": {
+ "default": "KEY_STATUS_UNSPECIFIED",
+ "enum": [
+ "KEY_STATUS_UNSPECIFIED",
+ "KEY_STATUS_ACTIVE",
+ "KEY_STATUS_REVOKED",
+ "KEY_STATUS_EXPIRED"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyStatus"
+ },
+ "update_time": { "format": "date-time", "type": "string" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1IssuedAPIKey"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-update-issued-api-key.api.mdx b/docs/talos/reference/api/admin-update-issued-api-key.api.mdx
new file mode 100644
index 000000000..189903de5
--- /dev/null
+++ b/docs/talos/reference/api/admin-update-issued-api-key.api.mdx
@@ -0,0 +1,38 @@
+---
+id: admin-update-issued-api-key
+title: "Update Issued API Key"
+description: "Updates metadata, scopes, or rate limits of an issued key without rotating"
+sidebar_label: "Update Issued API Key"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "patch api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Updates metadata, scopes, or rate limits of an issued key without rotating the secret. Use RotateIssuedAPIKey to change the
+secret.
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/admin-verify-api-key.RequestSchema.json b/docs/talos/reference/api/admin-verify-api-key.RequestSchema.json
new file mode 100644
index 000000000..d1e2a98d5
--- /dev/null
+++ b/docs/talos/reference/api/admin-verify-api-key.RequestSchema.json
@@ -0,0 +1,21 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "credential": {
+ "title": "API key or derived token (any format: sk_*, JWT, macaroon)",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1VerifyAPIKeyRequest"
+ }
+ }
+ },
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/admin-verify-api-key.StatusCodes.json b/docs/talos/reference/api/admin-verify-api-key.StatusCodes.json
new file mode 100644
index 000000000..4b415eba5
--- /dev/null
+++ b/docs/talos/reference/api/admin-verify-api-key.StatusCodes.json
@@ -0,0 +1,113 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "actor_id": { "type": "string" },
+ "error_code": {
+ "default": "VERIFICATION_ERROR_UNSPECIFIED",
+ "description": "- VERIFICATION_ERROR_UNSPECIFIED: No error (key is valid)\n - VERIFICATION_ERROR_INVALID_FORMAT: Credential format is invalid\n - VERIFICATION_ERROR_EXPIRED: Credential has expired\n - VERIFICATION_ERROR_REVOKED: Credential has been revoked\n - VERIFICATION_ERROR_NOT_FOUND: Credential not found in database\n - VERIFICATION_ERROR_SIGNATURE_INVALID: Cryptographic signature verification failed\n - VERIFICATION_ERROR_INTERNAL: Internal server error during verification\n - VERIFICATION_ERROR_IP_NOT_ALLOWED: Request IP is not in the key's allowed CIDR ranges\n - VERIFICATION_ERROR_RATE_LIMITED: Rate limit quota exhausted (commercial-only)",
+ "enum": [
+ "VERIFICATION_ERROR_UNSPECIFIED",
+ "VERIFICATION_ERROR_INVALID_FORMAT",
+ "VERIFICATION_ERROR_EXPIRED",
+ "VERIFICATION_ERROR_REVOKED",
+ "VERIFICATION_ERROR_NOT_FOUND",
+ "VERIFICATION_ERROR_SIGNATURE_INVALID",
+ "VERIFICATION_ERROR_INTERNAL",
+ "VERIFICATION_ERROR_IP_NOT_ALLOWED",
+ "VERIFICATION_ERROR_RATE_LIMITED"
+ ],
+ "title": "VerificationErrorCode provides type-safe error codes for verification failures",
+ "type": "string"
+ },
+ "error_message": {
+ "title": "Human-readable error message (only set if is_active=false)",
+ "type": "string"
+ },
+ "expire_time": { "format": "date-time", "type": "string" },
+ "is_active": { "type": "boolean" },
+ "issuer": {
+ "description": "The configured token issuer for this project. For derived tokens (JWT/macaroon),\nthis matches the iss claim embedded in the verified token.",
+ "type": "string"
+ },
+ "key_id": { "type": "string" },
+ "metadata": { "type": "object" },
+ "rate_limit_policy": {
+ "description": "RateLimitPolicy describes the rate limit policy for an API key.\n\nIn OSS mode, this policy is informational and meant to be consumed by\nupstream gateways (Envoy, Cloudflare, etc.) for enforcement.\nIn commercial mode, Talos enforces rate limits using in-memory or Redis backends,\nboth powered by the GCRA (Generic Cell Rate Algorithm).\n\nCompliant with draft-ietf-httpapi-ratelimit-headers-10.",
+ "properties": {
+ "quota": {
+ "description": "quota is the number of requests allowed per window.",
+ "format": "int64",
+ "type": "string"
+ },
+ "unit": {
+ "title": "unit describes the quota unit type.\nDefault: \"requests\"\nOther valid values per IETF spec: \"content-bytes\", \"concurrent-requests\"",
+ "type": "string"
+ },
+ "window": {
+ "description": "window is the time window for the quota.\nCommon values: 60s (1 minute), 3600s (1 hour), 86400s (1 day).",
+ "type": "string"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1RateLimitPolicy"
+ },
+ "rate_limit_remaining": {
+ "description": "Approximate number of requests available before the rate limit is reached\n(commercial-only, only set when enforcement is active).",
+ "format": "int64",
+ "type": "string"
+ },
+ "rate_limit_reset_time": {
+ "description": "Time when the rate limiter returns to full capacity (all quota recovered).",
+ "format": "date-time",
+ "type": "string"
+ },
+ "scopes": { "items": { "type": "string" }, "type": "array" },
+ "visibility": {
+ "default": "KEY_VISIBILITY_UNSPECIFIED",
+ "description": "KeyVisibility distinguishes public (client-safe) keys from secret (server-only) keys.\nPublic keys use a different configurable prefix for visual distinction.\nBoth types share the same scope/permission system — visibility is about exposure safety.\n\n - KEY_VISIBILITY_UNSPECIFIED: Treated as SECRET",
+ "enum": [
+ "KEY_VISIBILITY_UNSPECIFIED",
+ "KEY_VISIBILITY_SECRET",
+ "KEY_VISIBILITY_PUBLIC"
+ ],
+ "type": "string",
+ "title": "v2alpha1KeyVisibility"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1VerifyAPIKeyResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/admin-verify-api-key.api.mdx b/docs/talos/reference/api/admin-verify-api-key.api.mdx
new file mode 100644
index 000000000..d40a372fe
--- /dev/null
+++ b/docs/talos/reference/api/admin-verify-api-key.api.mdx
@@ -0,0 +1,45 @@
+---
+id: admin-verify-api-key
+title: "Verify API Key"
+description: "Verifies a single API key or derived token. Validates the credential's"
+sidebar_label: "Verify API Key"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Verifies a single API key or derived token. Validates the credential's signature, expiration, and revocation status. Works with
+any credential type (issued keys, imported keys, JWT, macaroon). The verification result includes decoded claims and metadata —
+admin access only.
+
+Cache Control (HTTP Headers):
+
+- Cache-Control: no-cache - Bypasses cache read, forces fresh DB lookup
+- Cache-Control: no-store - Bypasses cache read AND write (never cached)
+- Pragma: no-cache - Same as Cache-Control: no-cache (HTTP/1.0)
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/ory-talos-api.info.mdx b/docs/talos/reference/api/ory-talos-api.info.mdx
new file mode 100644
index 000000000..8d75faadb
--- /dev/null
+++ b/docs/talos/reference/api/ory-talos-api.info.mdx
@@ -0,0 +1,40 @@
+---
+id: ory-talos-api
+title: "Ory Talos API"
+description:
+ "Ory Talos is a high-performance static credential management service. It handles the full credential lifecycle: issuing keys,
+ verifying them at low latency, deriving short-lived tokens (JWT and Macaroon), and revoking access."
+sidebar_label: "Ory Talos API"
+hide_title: true
+custom_edit_url: null
+---
+
+import ApiLogo from "@theme/ApiLogo"
+import Heading from "@theme/Heading"
+import SchemaTabs from "@theme/SchemaTabs"
+import TabItem from "@theme/TabItem"
+import Export from "@theme/ApiExplorer/Export"
+
+
+
+
+
+Ory Talos is a high-performance static credential management service. It handles the full credential lifecycle: issuing keys,
+verifying them at low latency, deriving short-lived tokens (JWT and Macaroon), and revoking access.
+
+The API is split into two services:
+
+- **StaticCredentials** — admin operations: key lifecycle (issue, rotate, revoke, import, derive tokens, JWKS) and verification
+- **SelfService** — self-service revocation for credential holders
+
+### Quick Links
+
+- [**Admin Plane**](./admin-issue-api-key) — Key lifecycle management (issue, rotate, revoke, import, derive tokens, JWKS)
+- [**Data Plane**](./admin-verify-api-key) — High-performance verification (single, batch, self-revoke)
+
+```mdx-code-block
+import DocCardList from '@theme/DocCardList';
+import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
+
+
+```
diff --git a/docs/talos/reference/api/revoke-api-key.RequestSchema.json b/docs/talos/reference/api/revoke-api-key.RequestSchema.json
new file mode 100644
index 000000000..6f51da83e
--- /dev/null
+++ b/docs/talos/reference/api/revoke-api-key.RequestSchema.json
@@ -0,0 +1,36 @@
+{
+ "title": "Body",
+ "body": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "SelfRevokeAPIKeyRequest allows an API key holder to revoke their own key\nby providing the full key secret as proof of possession.",
+ "properties": {
+ "credential": {
+ "title": "Full API key secret or imported key (REQUIRED)",
+ "type": "string"
+ },
+ "reason": {
+ "default": "REVOCATION_REASON_UNSPECIFIED",
+ "description": "RevocationReason provides structured revocation reasons inspired by RFC 5280.\nUsed in both admin and self-revocation flows.\n\n - REVOCATION_REASON_PRIVILEGE_WITHDRAWN: Admin-only: not allowed in self-revocation",
+ "enum": [
+ "REVOCATION_REASON_UNSPECIFIED",
+ "REVOCATION_REASON_KEY_COMPROMISE",
+ "REVOCATION_REASON_AFFILIATION_CHANGED",
+ "REVOCATION_REASON_SUPERSEDED",
+ "REVOCATION_REASON_PRIVILEGE_WITHDRAWN"
+ ],
+ "type": "string",
+ "title": "v2alpha1RevocationReason"
+ }
+ },
+ "type": "object",
+ "title": "v2alpha1SelfRevokeAPIKeyRequest"
+ }
+ }
+ },
+ "description": "SelfRevokeAPIKeyRequest allows an API key holder to revoke their own key\nby providing the full key secret as proof of possession.",
+ "required": true,
+ "x-originalParamName": "body"
+ }
+}
diff --git a/docs/talos/reference/api/revoke-api-key.StatusCodes.json b/docs/talos/reference/api/revoke-api-key.StatusCodes.json
new file mode 100644
index 000000000..72c1ff7d8
--- /dev/null
+++ b/docs/talos/reference/api/revoke-api-key.StatusCodes.json
@@ -0,0 +1,40 @@
+{
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "description": "SelfRevokeAPIKeyResponse is returned on successful self-revocation.\n\nEmpty on success",
+ "type": "object",
+ "title": "v2alpha1SelfRevokeAPIKeyResponse"
+ }
+ }
+ },
+ "description": "A successful response."
+ },
+ "default": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "code": { "format": "int32", "type": "integer" },
+ "details": {
+ "items": {
+ "additionalProperties": {},
+ "properties": { "@type": { "type": "string" } },
+ "type": "object",
+ "title": "protobufAny"
+ },
+ "type": "array"
+ },
+ "message": { "type": "string" }
+ },
+ "type": "object",
+ "title": "rpcStatus"
+ }
+ }
+ },
+ "description": "An unexpected error response."
+ }
+ }
+}
diff --git a/docs/talos/reference/api/revoke-api-key.api.mdx b/docs/talos/reference/api/revoke-api-key.api.mdx
new file mode 100644
index 000000000..f40f8fd9a
--- /dev/null
+++ b/docs/talos/reference/api/revoke-api-key.api.mdx
@@ -0,0 +1,40 @@
+---
+id: revoke-api-key
+title: "Revoke API Key"
+description: "Allows an API key holder to revoke their own key. The caller must provide"
+sidebar_label: "Revoke API Key"
+hide_title: true
+hide_table_of_contents: true
+api: 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
+sidebar_class_name: "post api-method"
+info_path: reference/api/ory-talos-api
+custom_edit_url: null
+---
+
+import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"
+import ParamsDetails from "@theme/ParamsDetails"
+import RequestSchema from "@theme/RequestSchema"
+import StatusCodes from "@theme/StatusCodes"
+import OperationTabs from "@theme/OperationTabs"
+import TabItem from "@theme/TabItem"
+import Heading from "@theme/Heading"
+import Translate from "@docusaurus/Translate"
+
+
+
+
+
+Allows an API key holder to revoke their own key. The caller must provide the full API key secret as proof of possession. Supports
+issued API keys and imported keys. JWT and macaroon tokens cannot be self-revoked (they are stateless).
+
+The PRIVILEGE_WITHDRAWN reason is not allowed for self-revocation (admin-only).
+
+
+ Request
+
+
+
+
+
+
+
diff --git a/docs/talos/reference/api/sidebar.ts b/docs/talos/reference/api/sidebar.ts
new file mode 100644
index 000000000..e68874395
--- /dev/null
+++ b/docs/talos/reference/api/sidebar.ts
@@ -0,0 +1,126 @@
+import type { SidebarsConfig } from "@docusaurus/plugin-content-docs"
+
+const sidebar: SidebarsConfig = {
+ apisidebar: [
+ {
+ type: "doc",
+ id: "reference/api/ory-talos-api",
+ },
+ {
+ type: "category",
+ label: "StaticCredentials",
+ items: [
+ {
+ type: "doc",
+ id: "reference/api/admin-revoke-api-key",
+ label: "Revoke API Key",
+ className: "api-method post",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-batch-verify-api-keys",
+ label: "Batch Verify API Keys",
+ className: "api-method post",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-derive-token",
+ label: "Derive Token",
+ className: "api-method post",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-verify-api-key",
+ label: "Verify API Key",
+ className: "api-method post",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-get-jwks",
+ label: "Get JWKS",
+ className: "api-method get",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-list-imported-api-keys",
+ label: "List Imported API Keys",
+ className: "api-method get",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-import-api-key",
+ label: "Import API Key",
+ className: "api-method post",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-delete-imported-api-key",
+ label: "Delete Imported API Key",
+ className: "api-method delete",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-get-imported-api-key",
+ label: "Get Imported API Key",
+ className: "api-method get",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-update-imported-api-key",
+ label: "Update Imported API Key",
+ className: "api-method patch",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-batch-import-api-keys",
+ label: "Batch Import API Keys",
+ className: "api-method post",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-list-issued-api-keys",
+ label: "List Issued API Keys",
+ className: "api-method get",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-issue-api-key",
+ label: "Issue API Key",
+ className: "api-method post",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-get-issued-api-key",
+ label: "Get Issued API Key",
+ className: "api-method get",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-update-issued-api-key",
+ label: "Update Issued API Key",
+ className: "api-method patch",
+ },
+ {
+ type: "doc",
+ id: "reference/api/admin-rotate-issued-api-key",
+ label: "Rotate Issued API Key",
+ className: "api-method post",
+ },
+ ],
+ },
+ {
+ type: "category",
+ label: "SelfService",
+ items: [
+ {
+ type: "doc",
+ id: "reference/api/revoke-api-key",
+ label: "Revoke API Key",
+ className: "api-method post",
+ },
+ ],
+ },
+ ],
+}
+
+export default sidebar.apisidebar
diff --git a/docs/talos/reference/cli/.gitkeep b/docs/talos/reference/cli/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs/talos/reference/cli/talos-jwk-generate-ecdsa.md b/docs/talos/reference/cli/talos-jwk-generate-ecdsa.md
new file mode 100644
index 000000000..22a85fd24
--- /dev/null
+++ b/docs/talos/reference/cli/talos-jwk-generate-ecdsa.md
@@ -0,0 +1,60 @@
+---
+id: talos-jwk-generate-ecdsa
+title: talos jwk generate ecdsa
+description: talos jwk generate ecdsa
+---
+
+
+
+## talos jwk generate ecdsa
+
+Generate an ECDSA key pair
+
+### Synopsis
+
+Generate an ECDSA key pair using the specified elliptic curve. Key size is determined by the curve: P-256 (256-bit), P-384
+(384-bit), P-521 (521-bit). Default curve: P-256.
+
+```
+talos jwk generate ecdsa [flags]
+```
+
+### Examples
+
+```
+ # Generate P-256 key (default)
+ talos jwk generate ecdsa -o ecdsa-key.json
+
+ # Generate P-384 key with custom key ID
+ talos jwk generate ecdsa --curve P-384 --kid prod-ec-key -o ecdsa-p384.json
+
+ # Generate P-521 key
+ talos jwk generate ecdsa --curve P-521 -o ecdsa-p521.json
+```
+
+### Options
+
+```
+ --curve string Elliptic curve (P-256, P-384, P-521) (default "P-256")
+ -h, --help help for ecdsa
+ --jwks Output as JWKS (JSON Web Key Set)
+ --kid string Key ID (JWK Thumbprint used if not provided)
+ -o, --output string Output file (writes to stdout if not specified)
+ --public-only Output public key only
+ --use string Key usage: 'sig' for signing, 'enc' for encryption (default: sig)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos jwk generate](talos-jwk-generate.md) Generate a new JWK key
diff --git a/docs/talos/reference/cli/talos-jwk-generate-eddsa.md b/docs/talos/reference/cli/talos-jwk-generate-eddsa.md
new file mode 100644
index 000000000..a5833a3c5
--- /dev/null
+++ b/docs/talos/reference/cli/talos-jwk-generate-eddsa.md
@@ -0,0 +1,61 @@
+---
+id: talos-jwk-generate-eddsa
+title: talos jwk generate eddsa
+description: talos jwk generate eddsa
+---
+
+
+
+## talos jwk generate eddsa
+
+Generate an EdDSA (Ed25519) key pair
+
+### Synopsis
+
+Generate an EdDSA key pair using the Ed25519 curve. Ed25519 uses a fixed 256-bit key size.
+
+```
+talos jwk generate eddsa [flags]
+```
+
+### Examples
+
+```
+ # Generate with auto-generated key ID
+ talos jwk generate eddsa -o signing-key.json
+
+ # Generate with custom key ID
+ talos jwk generate eddsa --kid prod-key-1 -o signing-key.json
+
+ # Generate public key only
+ talos jwk generate eddsa --public-only -o public-key.json
+
+ # Generate as JWKS format
+ talos jwk generate eddsa --jwks -o keys.jwks.json
+```
+
+### Options
+
+```
+ -h, --help help for eddsa
+ --jwks Output as JWKS (JSON Web Key Set)
+ --kid string Key ID (JWK Thumbprint used if not provided)
+ -o, --output string Output file (writes to stdout if not specified)
+ --public-only Output public key only
+ --use string Key usage: 'sig' for signing, 'enc' for encryption (default: sig)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos jwk generate](talos-jwk-generate.md) Generate a new JWK key
diff --git a/docs/talos/reference/cli/talos-jwk-generate-hmac.md b/docs/talos/reference/cli/talos-jwk-generate-hmac.md
new file mode 100644
index 000000000..edfe70d2a
--- /dev/null
+++ b/docs/talos/reference/cli/talos-jwk-generate-hmac.md
@@ -0,0 +1,59 @@
+---
+id: talos-jwk-generate-hmac
+title: talos jwk generate hmac
+description: talos jwk generate hmac
+---
+
+
+
+## talos jwk generate hmac
+
+Generate an HMAC secret key
+
+### Synopsis
+
+Generate a symmetric HMAC secret key. Default size is 512 bits. Minimum is 256 bits. Algorithm is determined by key size:
+256→HS256, 384→HS384, ≥512→HS512.
+
+```
+talos jwk generate hmac [flags]
+```
+
+### Examples
+
+```
+ # Generate 512-bit HMAC secret (default)
+ talos jwk generate hmac -o hmac-secret.json
+
+ # Generate 256-bit HMAC secret
+ talos jwk generate hmac --bits 256 -o hmac-256.json
+
+ # Generate with custom key ID
+ talos jwk generate hmac --kid signing-secret-1 -o hmac-key.json
+```
+
+### Options
+
+```
+ --bits int Key size in bits (default 512, minimum 256) (default 512)
+ -h, --help help for hmac
+ --jwks Output as JWKS (JSON Web Key Set)
+ --kid string Key ID (JWK Thumbprint used if not provided)
+ -o, --output string Output file (writes to stdout if not specified)
+ --use string Key usage: 'sig' for signing, 'enc' for encryption (default: sig)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos jwk generate](talos-jwk-generate.md) Generate a new JWK key
diff --git a/docs/talos/reference/cli/talos-jwk-generate-rsa.md b/docs/talos/reference/cli/talos-jwk-generate-rsa.md
new file mode 100644
index 000000000..f39c2c963
--- /dev/null
+++ b/docs/talos/reference/cli/talos-jwk-generate-rsa.md
@@ -0,0 +1,63 @@
+---
+id: talos-jwk-generate-rsa
+title: talos jwk generate rsa
+description: talos jwk generate rsa
+---
+
+
+
+## talos jwk generate rsa
+
+Generate an RSA key pair
+
+### Synopsis
+
+Generate an RSA key pair with the specified key size. Default is 2048 bits. Minimum is 2048 bits.
+
+```
+talos jwk generate rsa [flags]
+```
+
+### Examples
+
+```
+ # Generate RSA key (default: 2048 bits)
+ talos jwk generate rsa -o rsa-key.json
+
+ # Generate 4096-bit RSA key
+ talos jwk generate rsa --bits 4096 -o rsa-4096.json
+
+ # Generate with custom algorithm
+ talos jwk generate rsa --alg RS512 -o rsa-rs512.json
+
+ # Generate public key only
+ talos jwk generate rsa --public-only -o rsa-public.json
+```
+
+### Options
+
+```
+ --alg string Algorithm override (e.g. RS384, RS512, PS256)
+ --bits int Key size in bits (minimum 2048) (default 2048)
+ -h, --help help for rsa
+ --jwks Output as JWKS (JSON Web Key Set)
+ --kid string Key ID (JWK Thumbprint used if not provided)
+ -o, --output string Output file (writes to stdout if not specified)
+ --public-only Output public key only
+ --use string Key usage: 'sig' for signing, 'enc' for encryption (default: sig)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos jwk generate](talos-jwk-generate.md) Generate a new JWK key
diff --git a/docs/talos/reference/cli/talos-jwk-generate.md b/docs/talos/reference/cli/talos-jwk-generate.md
new file mode 100644
index 000000000..111309f8b
--- /dev/null
+++ b/docs/talos/reference/cli/talos-jwk-generate.md
@@ -0,0 +1,40 @@
+---
+id: talos-jwk-generate
+title: talos jwk generate
+description: talos jwk generate
+---
+
+
+
+## talos jwk generate
+
+Generate a new JWK key
+
+### Synopsis
+
+Generate a new cryptographic key in JWK format for signing or encryption.
+
+### Options
+
+```
+ -h, --help help for generate
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos jwk](talos-jwk.md) Generate JSON Web Keys (JWK/JWKS)
+- [talos jwk generate ecdsa](talos-jwk-generate-ecdsa.md) - Generate an ECDSA key pair
+- [talos jwk generate eddsa](talos-jwk-generate-eddsa.md) - Generate an EdDSA (Ed25519) key pair
+- [talos jwk generate hmac](talos-jwk-generate-hmac.md) - Generate an HMAC secret key
+- [talos jwk generate rsa](talos-jwk-generate-rsa.md) - Generate an RSA key pair
diff --git a/docs/talos/reference/cli/talos-jwk-get.md b/docs/talos/reference/cli/talos-jwk-get.md
new file mode 100644
index 000000000..0594c8ec6
--- /dev/null
+++ b/docs/talos/reference/cli/talos-jwk-get.md
@@ -0,0 +1,54 @@
+---
+id: talos-jwk-get
+title: talos jwk get
+description: talos jwk get
+---
+
+
+
+## talos jwk get
+
+Fetch the server's JSON Web Key Set (JWKS)
+
+### Synopsis
+
+Fetch the public signing keys used to verify derived JWT tokens.
+
+The JWKS is served at GET /v2alpha1/admin/derivedKeys/jwks.json and includes the active signing key plus any retired keys still
+inside the verification window.
+
+Clients verifying derived tokens should cache the response for 5 to 15 minutes and refetch when they encounter a token with an
+unknown 'kid'. Polling more aggressively does not shorten the practical revocation window — that window is bounded by the longest
+issued token TTL, not by the JWKS cache.
+
+```
+talos jwk get [flags]
+```
+
+### Examples
+
+```
+ # Pretty-print the JWKS served by a local Talos
+ talos jwk get -e http://localhost:4420 | jq .
+```
+
+### Options
+
+```
+ -h, --help help for get
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos jwk](talos-jwk.md) Generate JSON Web Keys (JWK/JWKS)
diff --git a/docs/talos/reference/cli/talos-jwk.md b/docs/talos/reference/cli/talos-jwk.md
new file mode 100644
index 000000000..8d2741ead
--- /dev/null
+++ b/docs/talos/reference/cli/talos-jwk.md
@@ -0,0 +1,39 @@
+---
+id: talos-jwk
+title: talos jwk
+description: talos jwk
+---
+
+
+
+## talos jwk
+
+Generate JSON Web Keys (JWK/JWKS)
+
+### Synopsis
+
+Generate cryptographic keys in JSON Web Key (JWK) format. Supports EdDSA (Ed25519), ECDSA (P-256, P-384, P-521), RSA, and HMAC
+algorithms.
+
+### Options
+
+```
+ -h, --help help for jwk
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos](talos.md) Multi-tenant API key management service
+- [talos jwk generate](talos-jwk-generate.md) - Generate a new JWK key
+- [talos jwk get](talos-jwk-get.md) - Fetch the server's JSON Web Key Set (JWKS)
diff --git a/docs/talos/reference/cli/talos-keys-batch-verify.md b/docs/talos/reference/cli/talos-keys-batch-verify.md
new file mode 100644
index 000000000..057472c09
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-batch-verify.md
@@ -0,0 +1,39 @@
+---
+id: talos-keys-batch-verify
+title: talos keys batch-verify
+description: talos keys batch-verify
+---
+
+
+
+## talos keys batch-verify
+
+Verify multiple credentials in a single request
+
+```
+talos keys batch-verify [credentials...] [flags]
+```
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for batch-verify
+ --no-cache Bypass verification cache (sends Cache-Control: no-cache header)
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys](talos-keys.md) Manage API keys
diff --git a/docs/talos/reference/cli/talos-keys-derive-token.md b/docs/talos/reference/cli/talos-keys-derive-token.md
new file mode 100644
index 000000000..9d9190eb0
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-derive-token.md
@@ -0,0 +1,45 @@
+---
+id: talos-keys-derive-token
+title: talos keys derive-token
+description: talos keys derive-token
+---
+
+
+
+## talos keys derive-token
+
+Derive a short-lived JWT or macaroon from an existing API key
+
+### Synopsis
+
+Derives a short-lived JWT or macaroon token from an existing opaque API key.
+
+```
+talos keys derive-token [api-key-token] [flags]
+```
+
+### Options
+
+```
+ --algorithm string Algorithm for derived token (jwt or macaroon) (default "jwt")
+ --claims string Custom claims as JSON (e.g., '{"user_ip":"192.168.1.1","request_id":"abc123"}'). Reserved claims like iss, sub, exp cannot be overridden.
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for derive-token
+ -q, --quiet Be quiet with output printing.
+ --ttl string Token time-to-live duration (default "1h")
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys](talos-keys.md) Manage API keys
diff --git a/docs/talos/reference/cli/talos-keys-imported-batch-import.md b/docs/talos/reference/cli/talos-keys-imported-batch-import.md
new file mode 100644
index 000000000..5c0af749d
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-imported-batch-import.md
@@ -0,0 +1,43 @@
+---
+id: talos-keys-imported-batch-import
+title: talos keys imported batch-import
+description: talos keys imported batch-import
+---
+
+
+
+## talos keys imported batch-import
+
+Batch import API keys from a JSON file
+
+### Synopsis
+
+Batch import API keys from a JSON file. Each request is limited to 1000 keys; the server rejects batches that exceed this limit.
+
+```
+talos keys imported batch-import --file keys.json [flags]
+```
+
+### Options
+
+```
+ --file string Path to JSON file with key array, or '-' for stdin
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for batch-import
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys imported](talos-keys-imported.md) Manage imported API keys
diff --git a/docs/talos/reference/cli/talos-keys-imported-delete.md b/docs/talos/reference/cli/talos-keys-imported-delete.md
new file mode 100644
index 000000000..6d9c3f22e
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-imported-delete.md
@@ -0,0 +1,38 @@
+---
+id: talos-keys-imported-delete
+title: talos keys imported delete
+description: talos keys imported delete
+---
+
+
+
+## talos keys imported delete
+
+Permanently delete an imported API key
+
+```
+talos keys imported delete [key-id] [flags]
+```
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for delete
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys imported](talos-keys-imported.md) Manage imported API keys
diff --git a/docs/talos/reference/cli/talos-keys-imported-get.md b/docs/talos/reference/cli/talos-keys-imported-get.md
new file mode 100644
index 000000000..cf66b0366
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-imported-get.md
@@ -0,0 +1,38 @@
+---
+id: talos-keys-imported-get
+title: talos keys imported get
+description: talos keys imported get
+---
+
+
+
+## talos keys imported get
+
+Get details of an imported API key
+
+```
+talos keys imported get [key-id] [flags]
+```
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for get
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys imported](talos-keys-imported.md) Manage imported API keys
diff --git a/docs/talos/reference/cli/talos-keys-imported-import.md b/docs/talos/reference/cli/talos-keys-imported-import.md
new file mode 100644
index 000000000..96795e4f1
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-imported-import.md
@@ -0,0 +1,46 @@
+---
+id: talos-keys-imported-import
+title: talos keys imported import
+description: talos keys imported import
+---
+
+
+
+## talos keys imported import
+
+Import an external API key
+
+```
+talos keys imported import [name] [flags]
+```
+
+### Options
+
+```
+ --actor string Actor ID (required)
+ --allowed-cidrs string Comma-separated CIDR ranges for IP restriction (e.g., '10.0.0.0/8,192.168.0.0/16')
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for import
+ --metadata string JSON metadata for the imported key
+ -q, --quiet Be quiet with output printing.
+ --rate-limit-quota int Maximum requests allowed per window (0 = no limit)
+ --rate-limit-window string Rate limit window duration (e.g., 60s, 5m)
+ --raw-key string The raw key string to import (required)
+ --scopes string Comma-separated list of scopes
+ --ttl string Time-to-live duration (e.g., '24h', '8760h')
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys imported](talos-keys-imported.md) Manage imported API keys
diff --git a/docs/talos/reference/cli/talos-keys-imported-list.md b/docs/talos/reference/cli/talos-keys-imported-list.md
new file mode 100644
index 000000000..bf1a42fb0
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-imported-list.md
@@ -0,0 +1,42 @@
+---
+id: talos-keys-imported-list
+title: talos keys imported list
+description: talos keys imported list
+---
+
+
+
+## talos keys imported list
+
+List imported API keys
+
+```
+talos keys imported list [flags]
+```
+
+### Options
+
+```
+ --actor string Filter by actor ID
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for list
+ --page-size int32 Number of items per page (default: 50, max: 1000)
+ --page-token string Cursor token for pagination
+ -q, --quiet Be quiet with output printing.
+ --status string Filter by status (KEY_STATUS_ACTIVE, KEY_STATUS_REVOKED, KEY_STATUS_EXPIRED)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys imported](talos-keys-imported.md) Manage imported API keys
diff --git a/docs/talos/reference/cli/talos-keys-imported-revoke.md b/docs/talos/reference/cli/talos-keys-imported-revoke.md
new file mode 100644
index 000000000..aa287cdaf
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-imported-revoke.md
@@ -0,0 +1,40 @@
+---
+id: talos-keys-imported-revoke
+title: talos keys imported revoke
+description: talos keys imported revoke
+---
+
+
+
+## talos keys imported revoke
+
+Revoke an imported API key
+
+```
+talos keys imported revoke [key-id] [flags]
+```
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for revoke
+ -q, --quiet Be quiet with output printing.
+ --reason string Reason for revocation (key_compromise, affiliation_changed, superseded, privilege_withdrawn)
+ --reason-text string Human-readable reason text
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys imported](talos-keys-imported.md) Manage imported API keys
diff --git a/docs/talos/reference/cli/talos-keys-imported.md b/docs/talos/reference/cli/talos-keys-imported.md
new file mode 100644
index 000000000..274a5b864
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-imported.md
@@ -0,0 +1,44 @@
+---
+id: talos-keys-imported
+title: talos keys imported
+description: talos keys imported
+---
+
+
+
+## talos keys imported
+
+Manage imported API keys
+
+### Synopsis
+
+Import, list, get, revoke, and delete externally-created API keys.
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for imported
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys](talos-keys.md) Manage API keys
+- [talos keys imported batch-import](talos-keys-imported-batch-import.md) - Batch import API keys from a JSON file
+- [talos keys imported delete](talos-keys-imported-delete.md) - Permanently delete an imported API key
+- [talos keys imported get](talos-keys-imported-get.md) - Get details of an imported API key
+- [talos keys imported import](talos-keys-imported-import.md) - Import an external API key
+- [talos keys imported list](talos-keys-imported-list.md) - List imported API keys
+- [talos keys imported revoke](talos-keys-imported-revoke.md) - Revoke an imported API key
diff --git a/docs/talos/reference/cli/talos-keys-issue.md b/docs/talos/reference/cli/talos-keys-issue.md
new file mode 100644
index 000000000..b2ad52f08
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-issue.md
@@ -0,0 +1,45 @@
+---
+id: talos-keys-issue
+title: talos keys issue
+description: talos keys issue
+---
+
+
+
+## talos keys issue
+
+Issue a new API key
+
+```
+talos keys issue [name] [flags]
+```
+
+### Options
+
+```
+ --actor string Actor ID (required)
+ --allowed-cidrs string Comma-separated CIDR ranges for IP restriction (e.g., '10.0.0.0/8,192.168.0.0/16')
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for issue
+ --metadata string JSON metadata for the API key
+ -q, --quiet Be quiet with output printing.
+ --rate-limit-quota int Maximum requests allowed per window (0 = no limit)
+ --rate-limit-window string Rate limit window duration (e.g., 60s, 5m)
+ --scopes string Comma-separated list of scopes
+ --ttl duration Time-to-live duration (e.g., '24h', '168h') (default 24h0m0s)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys](talos-keys.md) Manage API keys
diff --git a/docs/talos/reference/cli/talos-keys-issued-get.md b/docs/talos/reference/cli/talos-keys-issued-get.md
new file mode 100644
index 000000000..dcd11f3d6
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-issued-get.md
@@ -0,0 +1,38 @@
+---
+id: talos-keys-issued-get
+title: talos keys issued get
+description: talos keys issued get
+---
+
+
+
+## talos keys issued get
+
+Get details of an issued API key
+
+```
+talos keys issued get [key-id] [flags]
+```
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for get
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys issued](talos-keys-issued.md) Manage issued API keys
diff --git a/docs/talos/reference/cli/talos-keys-issued-issue.md b/docs/talos/reference/cli/talos-keys-issued-issue.md
new file mode 100644
index 000000000..adb2a91d8
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-issued-issue.md
@@ -0,0 +1,45 @@
+---
+id: talos-keys-issued-issue
+title: talos keys issued issue
+description: talos keys issued issue
+---
+
+
+
+## talos keys issued issue
+
+Issue a new API key
+
+```
+talos keys issued issue [name] [flags]
+```
+
+### Options
+
+```
+ --actor string Actor ID (required)
+ --allowed-cidrs string Comma-separated CIDR ranges for IP restriction (e.g., '10.0.0.0/8,192.168.0.0/16')
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for issue
+ --metadata string JSON metadata for the API key
+ -q, --quiet Be quiet with output printing.
+ --rate-limit-quota int Maximum requests allowed per window (0 = no limit)
+ --rate-limit-window string Rate limit window duration (e.g., 60s, 5m)
+ --scopes string Comma-separated list of scopes
+ --ttl duration Time-to-live duration (e.g., '24h', '168h') (default 24h0m0s)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys issued](talos-keys-issued.md) Manage issued API keys
diff --git a/docs/talos/reference/cli/talos-keys-issued-list.md b/docs/talos/reference/cli/talos-keys-issued-list.md
new file mode 100644
index 000000000..5a42b0b86
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-issued-list.md
@@ -0,0 +1,42 @@
+---
+id: talos-keys-issued-list
+title: talos keys issued list
+description: talos keys issued list
+---
+
+
+
+## talos keys issued list
+
+List issued API keys
+
+```
+talos keys issued list [flags]
+```
+
+### Options
+
+```
+ --actor string Filter by actor ID
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for list
+ --page-size int32 Number of items per page (default: 50, max: 1000)
+ --page-token string Cursor token for pagination
+ -q, --quiet Be quiet with output printing.
+ --status string Filter by status (KEY_STATUS_ACTIVE, KEY_STATUS_REVOKED, KEY_STATUS_EXPIRED)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys issued](talos-keys-issued.md) Manage issued API keys
diff --git a/docs/talos/reference/cli/talos-keys-issued-rotate.md b/docs/talos/reference/cli/talos-keys-issued-rotate.md
new file mode 100644
index 000000000..cf4b20c11
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-issued-rotate.md
@@ -0,0 +1,41 @@
+---
+id: talos-keys-issued-rotate
+title: talos keys issued rotate
+description: talos keys issued rotate
+---
+
+
+
+## talos keys issued rotate
+
+Rotate an issued API key (revokes old key, creates new one)
+
+```
+talos keys issued rotate [key-id] [flags]
+```
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for rotate
+ --metadata string JSON metadata for the rotated key
+ --name string New name for the rotated API key
+ -q, --quiet Be quiet with output printing.
+ --scopes string Comma-separated list of scopes for the rotated key
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys issued](talos-keys-issued.md) Manage issued API keys
diff --git a/docs/talos/reference/cli/talos-keys-issued-update.md b/docs/talos/reference/cli/talos-keys-issued-update.md
new file mode 100644
index 000000000..88f1cde2c
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-issued-update.md
@@ -0,0 +1,44 @@
+---
+id: talos-keys-issued-update
+title: talos keys issued update
+description: talos keys issued update
+---
+
+
+
+## talos keys issued update
+
+Update an issued API key
+
+```
+talos keys issued update [key-id] [flags]
+```
+
+### Options
+
+```
+ --allowed-cidrs string Comma-separated CIDR ranges for IP restriction (empty string removes restrictions)
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for update
+ --metadata string JSON metadata for the API key
+ --name string New name for the API key
+ -q, --quiet Be quiet with output printing.
+ --rate-limit-quota int Maximum requests allowed per window (0 = no limit)
+ --rate-limit-window string Rate limit window duration (e.g., 60s, 5m)
+ --scopes string Comma-separated list of scopes
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys issued](talos-keys-issued.md) Manage issued API keys
diff --git a/docs/talos/reference/cli/talos-keys-issued.md b/docs/talos/reference/cli/talos-keys-issued.md
new file mode 100644
index 000000000..2e9ea3ccc
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-issued.md
@@ -0,0 +1,43 @@
+---
+id: talos-keys-issued
+title: talos keys issued
+description: talos keys issued
+---
+
+
+
+## talos keys issued
+
+Manage issued API keys
+
+### Synopsis
+
+Get, list, update, and rotate issued API keys.
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for issued
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys](talos-keys.md) Manage API keys
+- [talos keys issued get](talos-keys-issued-get.md) - Get details of an issued API key
+- [talos keys issued issue](talos-keys-issued-issue.md) - Issue a new API key
+- [talos keys issued list](talos-keys-issued-list.md) - List issued API keys
+- [talos keys issued rotate](talos-keys-issued-rotate.md) - Rotate an issued API key (revokes old key, creates new one)
+- [talos keys issued update](talos-keys-issued-update.md) - Update an issued API key
diff --git a/docs/talos/reference/cli/talos-keys-revoke.md b/docs/talos/reference/cli/talos-keys-revoke.md
new file mode 100644
index 000000000..e06478e93
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-revoke.md
@@ -0,0 +1,39 @@
+---
+id: talos-keys-revoke
+title: talos keys revoke
+description: talos keys revoke
+---
+
+
+
+## talos keys revoke
+
+Revoke an API key
+
+```
+talos keys revoke [key-id] [flags]
+```
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for revoke
+ -q, --quiet Be quiet with output printing.
+ --reason string Reason for revocation
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys](talos-keys.md) Manage API keys
diff --git a/docs/talos/reference/cli/talos-keys-self-revoke.md b/docs/talos/reference/cli/talos-keys-self-revoke.md
new file mode 100644
index 000000000..f83e05644
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-self-revoke.md
@@ -0,0 +1,43 @@
+---
+id: talos-keys-self-revoke
+title: talos keys self-revoke
+description: talos keys self-revoke
+---
+
+
+
+## talos keys self-revoke
+
+Revoke an API key using the credential itself as proof
+
+### Synopsis
+
+Self-revokes an API key by presenting the full credential as proof of ownership. Does not require admin access.
+
+```
+talos keys self-revoke [credential] [flags]
+```
+
+### Options
+
+```
+ -h, --help help for self-revoke
+ --reason string Reason for revocation
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -q, --quiet Be quiet with output printing.
+```
+
+### See also
+
+- [talos keys](talos-keys.md) Manage API keys
diff --git a/docs/talos/reference/cli/talos-keys-verify.md b/docs/talos/reference/cli/talos-keys-verify.md
new file mode 100644
index 000000000..d08d1450a
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys-verify.md
@@ -0,0 +1,43 @@
+---
+id: talos-keys-verify
+title: talos keys verify
+description: talos keys verify
+---
+
+
+
+## talos keys verify
+
+Verify a credential (API key or token)
+
+### Synopsis
+
+Verifies a credential against the server. Checks if the credential is active, not expired, and not revoked.
+
+```
+talos keys verify [credential] [flags]
+```
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for verify
+ --no-cache Bypass verification cache (sends Cache-Control: no-cache header)
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos keys](talos-keys.md) Manage API keys
diff --git a/docs/talos/reference/cli/talos-keys.md b/docs/talos/reference/cli/talos-keys.md
new file mode 100644
index 000000000..41e99e052
--- /dev/null
+++ b/docs/talos/reference/cli/talos-keys.md
@@ -0,0 +1,46 @@
+---
+id: talos-keys
+title: talos keys
+description: talos keys
+---
+
+
+
+## talos keys
+
+Manage API keys
+
+### Synopsis
+
+Create, list, get, revoke, and rotate API keys.
+
+### Options
+
+```
+ --format string Set the output format. One of table, json, yaml, json-pretty, jsonpath and jsonpointer. (default "table")
+ -h, --help help for keys
+ -q, --quiet Be quiet with output printing.
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos](talos.md) Multi-tenant API key management service
+- [talos keys batch-verify](talos-keys-batch-verify.md) - Verify multiple credentials in a single request
+- [talos keys derive-token](talos-keys-derive-token.md) - Derive a short-lived JWT or macaroon from an existing API key
+- [talos keys imported](talos-keys-imported.md) - Manage imported API keys
+- [talos keys issue](talos-keys-issue.md) - Issue a new API key
+- [talos keys issued](talos-keys-issued.md) - Manage issued API keys
+- [talos keys revoke](talos-keys-revoke.md) - Revoke an API key
+- [talos keys self-revoke](talos-keys-self-revoke.md) - Revoke an API key using the credential itself as proof
+- [talos keys verify](talos-keys-verify.md) - Verify a credential (API key or token)
diff --git a/docs/talos/reference/cli/talos-migrate-down.md b/docs/talos/reference/cli/talos-migrate-down.md
new file mode 100644
index 000000000..ca0205740
--- /dev/null
+++ b/docs/talos/reference/cli/talos-migrate-down.md
@@ -0,0 +1,54 @@
+---
+id: talos-migrate-down
+title: talos migrate down
+description: talos migrate down
+---
+
+
+
+## talos migrate down
+
+Rollback migrations
+
+### Synopsis
+
+Roll back the last N migrations (default: 1).
+
+This is useful for reverting recent migrations in development. In production, use this carefully and ensure you have backups.
+
+```
+talos migrate down [flags]
+```
+
+### Examples
+
+```
+ # Roll back last migration
+ talos migrate down
+
+ # Roll back last 3 migrations
+ talos migrate down --steps 3
+```
+
+### Options
+
+```
+ --database string database DSN (overrides DB_DSN)
+ -h, --help help for down
+ --steps int number of migrations to roll back (default 1)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos migrate](talos-migrate.md) Database migration tools
diff --git a/docs/talos/reference/cli/talos-migrate-force.md b/docs/talos/reference/cli/talos-migrate-force.md
new file mode 100644
index 000000000..df67f5292
--- /dev/null
+++ b/docs/talos/reference/cli/talos-migrate-force.md
@@ -0,0 +1,56 @@
+---
+id: talos-migrate-force
+title: talos migrate force
+description: talos migrate force
+---
+
+
+
+## talos migrate force
+
+Force set migration version (use with caution)
+
+### Synopsis
+
+Force the migration version to a specific value.
+
+This is useful when:
+
+- A migration failed and left the database in a dirty state
+- You need to manually fix the database state
+- You want to mark a migration as applied without running it
+
+WARNING: This command should be used carefully as it can lead to inconsistent database state if used incorrectly.
+
+```
+talos migrate force VERSION [flags]
+```
+
+### Examples
+
+```
+ # Mark database as clean at version 5
+ talos migrate force 5
+```
+
+### Options
+
+```
+ --database string database DSN (overrides DB_DSN)
+ -h, --help help for force
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos migrate](talos-migrate.md) Database migration tools
diff --git a/docs/talos/reference/cli/talos-migrate-status.md b/docs/talos/reference/cli/talos-migrate-status.md
new file mode 100644
index 000000000..1c550f44e
--- /dev/null
+++ b/docs/talos/reference/cli/talos-migrate-status.md
@@ -0,0 +1,47 @@
+---
+id: talos-migrate-status
+title: talos migrate status
+description: talos migrate status
+---
+
+
+
+## talos migrate status
+
+Show migration status
+
+### Synopsis
+
+Display the current database migration status.
+
+Shows:
+
+- Current migration version
+- Whether the database is in a dirty state
+- Database connection info
+
+```
+talos migrate status [flags]
+```
+
+### Options
+
+```
+ --database string database DSN (overrides DB_DSN)
+ -h, --help help for status
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos migrate](talos-migrate.md) Database migration tools
diff --git a/docs/talos/reference/cli/talos-migrate-up.md b/docs/talos/reference/cli/talos-migrate-up.md
new file mode 100644
index 000000000..346dceaee
--- /dev/null
+++ b/docs/talos/reference/cli/talos-migrate-up.md
@@ -0,0 +1,63 @@
+---
+id: talos-migrate-up
+title: talos migrate up
+description: talos migrate up
+---
+
+
+
+## talos migrate up
+
+Run all pending migrations
+
+### Synopsis
+
+Apply all pending migrations to the database.
+
+The database connection string can be provided via:
+
+- DB_DSN environment variable
+- --database flag (overrides DB_DSN)
+
+```
+talos migrate up [flags]
+```
+
+### Examples
+
+```
+ # SQLite
+ talos migrate up --database "sqlite3://./data/talos.db"
+
+ # PostgreSQL (commercial)
+ export DB_DSN="postgres://user:pass@localhost:5432/talos?sslmode=disable"
+ talos migrate up
+
+ # MySQL (commercial)
+ talos migrate up --database "mysql://user:pass@tcp(localhost:3306)/talos"
+
+ # CockroachDB (commercial)
+ talos migrate up --database "cockroach://user:pass@localhost:5432/talos?sslmode=disable"
+```
+
+### Options
+
+```
+ --database string database DSN (overrides DB_DSN)
+ -h, --help help for up
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos migrate](talos-migrate.md) Database migration tools
diff --git a/docs/talos/reference/cli/talos-migrate.md b/docs/talos/reference/cli/talos-migrate.md
new file mode 100644
index 000000000..4a580a2cb
--- /dev/null
+++ b/docs/talos/reference/cli/talos-migrate.md
@@ -0,0 +1,40 @@
+---
+id: talos-migrate
+title: talos migrate
+description: talos migrate
+---
+
+
+
+## talos migrate
+
+Database migration tools
+
+### Synopsis
+
+Run database migrations for the API Key service
+
+### Options
+
+```
+ -h, --help help for migrate
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos](talos.md) Multi-tenant API key management service
+- [talos migrate down](talos-migrate-down.md) - Rollback migrations
+- [talos migrate force](talos-migrate-force.md) - Force set migration version (use with caution)
+- [talos migrate status](talos-migrate-status.md) - Show migration status
+- [talos migrate up](talos-migrate-up.md) - Run all pending migrations
diff --git a/docs/talos/reference/cli/talos-proxy.md b/docs/talos/reference/cli/talos-proxy.md
new file mode 100644
index 000000000..73dc1fa99
--- /dev/null
+++ b/docs/talos/reference/cli/talos-proxy.md
@@ -0,0 +1,62 @@
+---
+id: talos-proxy
+title: talos proxy
+description: talos proxy
+---
+
+
+
+## talos proxy
+
+Start the edge proxy for caching verification requests
+
+### Synopsis
+
+Start an edge proxy that caches verification responses from an upstream Talos server.
+
+The proxy caches successful verification responses to reduce latency and load on the upstream server. Only active (valid)
+verification responses are cached.
+
+Cache bypass: Clients can bypass the cache by sending Cache-Control: no-cache header.
+
+The proxy exposes health endpoints: /health/alive - Always returns 200 OK /health/ready - Returns 200 OK if upstream is reachable
+
+```
+talos proxy [flags]
+```
+
+### Examples
+
+```
+ talos proxy --upstream http://talos:8080
+ talos proxy --upstream http://talos:8080 --listen :9090 --cache-ttl 5m
+ talos proxy --upstream http://talos:8080 --trust-x-forwarded-host
+```
+
+### Options
+
+```
+ --allowed-hosts strings Allowlist of valid Host/X-Forwarded-Host values (if set, requests with other hosts are rejected with 403)
+ --cache-max-size int Maximum cache size in bytes (default 104857600)
+ --cache-num-counters int Number of frequency counters for cache admission (default 10000)
+ --cache-ttl duration Cache entry TTL (default 1m0s)
+ -h, --help help for proxy
+ --listen string Listen address for the proxy (default ":8080")
+ --trust-x-forwarded-host Trust X-Forwarded-Host header for multi-tenant cache isolation (use when behind a trusted load balancer)
+ --upstream string Upstream Talos server URL (required)
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos](talos.md) Multi-tenant API key management service
diff --git a/docs/talos/reference/cli/talos-serve-admin.md b/docs/talos/reference/cli/talos-serve-admin.md
new file mode 100644
index 000000000..fdecf3922
--- /dev/null
+++ b/docs/talos/reference/cli/talos-serve-admin.md
@@ -0,0 +1,57 @@
+---
+id: talos-serve-admin
+title: talos serve admin
+description: talos serve admin
+---
+
+
+
+## talos serve admin
+
+Start the admin plane server (management only)
+
+### Synopsis
+
+Starts the admin plane server for API key and network management.
+
+This mode runs only the management endpoints for administrative operations. It's designed for internal tools, CI/CD, and
+administrative access.
+
+Features:
+
+- Full read/write database access
+- API key creation, rotation, revocation
+- Network management
+- Signing key management
+- Typically behind admin firewall
+
+```
+talos serve admin [flags]
+```
+
+### Examples
+
+```
+ talos serve admin
+```
+
+### Options
+
+```
+ -h, --help help for admin
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos serve](talos-serve.md) Start the Ory Talos server (all-in-one mode)
diff --git a/docs/talos/reference/cli/talos-serve-check.md b/docs/talos/reference/cli/talos-serve-check.md
new file mode 100644
index 000000000..6cf5e9192
--- /dev/null
+++ b/docs/talos/reference/cli/talos-serve-check.md
@@ -0,0 +1,51 @@
+---
+id: talos-serve-check
+title: talos serve check
+description: talos serve check
+---
+
+
+
+## talos serve check
+
+Start the data plane server (verification only)
+
+### Synopsis
+
+Starts the data plane server for API key and token verification.
+
+This mode runs only the verification endpoints with caching for optimal read performance. It's designed for edge deployments and
+high-throughput verification workloads.
+
+Cache configuration is read from the config file (cache.type, cache.ttl, etc.)
+
+```
+talos serve check [flags]
+```
+
+### Examples
+
+```
+ talos serve check
+```
+
+### Options
+
+```
+ -h, --help help for check
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos serve](talos-serve.md) Start the Ory Talos server (all-in-one mode)
diff --git a/docs/talos/reference/cli/talos-serve.md b/docs/talos/reference/cli/talos-serve.md
new file mode 100644
index 000000000..aab2d95c9
--- /dev/null
+++ b/docs/talos/reference/cli/talos-serve.md
@@ -0,0 +1,55 @@
+---
+id: talos-serve
+title: talos serve
+description: talos serve
+---
+
+
+
+## talos serve
+
+Start the Ory Talos server (all-in-one mode)
+
+### Synopsis
+
+Starts the HTTP server for the API key service in all-in-one mode.
+
+This mode runs both admin plane (management) and data plane (verification) in a single process.
+
+For production deployments with high-throughput verification workloads, consider using:
+
+- `serve check` for data plane only (verification with caching)
+- `serve admin` for admin plane only (management operations)
+
+```
+talos serve [flags]
+```
+
+### Examples
+
+```
+ talos serve
+```
+
+### Options
+
+```
+ -h, --help help for serve
+```
+
+### Options inherited from parent commands
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+```
+
+### See also
+
+- [talos](talos.md) Multi-tenant API key management service
+- [talos serve admin](talos-serve-admin.md) - Start the admin plane server (management only)
+- [talos serve check](talos-serve-check.md) - Start the data plane server (verification only)
diff --git a/docs/talos/reference/cli/talos.md b/docs/talos/reference/cli/talos.md
new file mode 100644
index 000000000..b04675b90
--- /dev/null
+++ b/docs/talos/reference/cli/talos.md
@@ -0,0 +1,37 @@
+---
+id: talos
+title: talos
+description: talos
+---
+
+
+
+## talos
+
+Multi-tenant API key management service
+
+### Synopsis
+
+Ory Talos manages the full lifecycle of API credentials: issuing keys, verifying them at low latency, deriving short-lived JWT or
+macaroon tokens, and revoking access. It exposes a separate admin plane (issue, rotate, revoke, derive) and data plane (verify,
+self-revoke) so each can be scaled and secured independently.
+
+### Options
+
+```
+ --config string config file (default is $HOME/.talos.yaml or ./config.yaml)
+ -e, --endpoint string HTTP server base URL including scheme, e.g. http://host:port (for client commands) (default "http://localhost:4420")
+ -h, --help help for talos
+```
+
+### See also
+
+- [talos jwk](talos-jwk.md) - Generate JSON Web Keys (JWK/JWKS)
+- [talos keys](talos-keys.md) - Manage API keys
+- [talos migrate](talos-migrate.md) - Database migration tools
+- [talos proxy](talos-proxy.md) - Start the edge proxy for caching verification requests
+- [talos serve](talos-serve.md) - Start the Ory Talos server (all-in-one mode)
diff --git a/docs/talos/reference/config.mdx b/docs/talos/reference/config.mdx
new file mode 100644
index 000000000..68d6b0a23
--- /dev/null
+++ b/docs/talos/reference/config.mdx
@@ -0,0 +1,190 @@
+---
+title: Configuration reference
+description: Auto-generated configuration reference from JSON Schema
+---
+
+# Configuration reference
+
+This page is auto-generated from the [configuration schema](https://github.com/ory/talos/blob/main/spec/config.schema.json).
+
+Required top-level keys: `credentials`, `secrets`
+
+## Environment variables
+
+Every configuration key can be set via an environment variable. Talos uses the `TALOS_` prefix and converts dot-separated config
+paths to uppercase with underscores:
+
+```
+TALOS__
+```
+
+Replace dots (`.`) with underscores (`_`) and convert to uppercase. For example, `serve.http.port` becomes
+`TALOS_SERVE_HTTP_PORT`.
+
+### Array values
+
+For array-typed config keys (like `secrets.hmac.retired`), use comma separation or indexed variables:
+
+```bash
+# Comma-separated
+export TALOS_SECRETS_HMAC_RETIRED="old-secret-1,old-secret-2"
+
+# Or indexed
+export TALOS_SECRETS_HMAC_RETIRED_0="old-secret-1"
+export TALOS_SECRETS_HMAC_RETIRED_1="old-secret-2"
+```
+
+### Precedence
+
+Configuration sources are applied in this order (highest priority first):
+
+1. Environment variables
+2. Configuration file (`--config` flag)
+3. Default values
+
+Environment variables always override file-based configuration.
+
+### Required variables
+
+At minimum, these must be set (via env var or config file):
+
+| Variable | Description |
+| ------------------------------- | ------------------------------------------------- |
+| `TALOS_SECRETS_DEFAULT_CURRENT` | Default secret for HMAC operations (min 32 chars) |
+| `TALOS_CREDENTIALS_ISSUER` | Token issuer (`iss` claim) for derived tokens |
+
+## `cache` Commercial
+
+Cache configuration.
+
+| Key | Type | Default | Env Var | Description |
+| -------------------------------- | ------------------------- | -------------------- | -------------------------------------- | --------------------------------------------------------------------------------------------- |
+| `cache.memory.max_size` | integer | `104857600` | `TALOS_CACHE_MEMORY_MAX_SIZE` | Maximum memory usage in bytes. (restart required, Commercial) |
+| `cache.memory.num_counters` | integer | `10000` | `TALOS_CACHE_MEMORY_NUM_COUNTERS` | Number of counters for frequency estimation. (restart required, Commercial) |
+| `cache.redis.addrs` | string[] | `["localhost:6379"]` | `TALOS_CACHE_REDIS_ADDRS` | Redis server addresses (supports cluster/sentinel). (restart required, Commercial) |
+| `cache.redis.conn_max_idle_time` | string | `5m` | `TALOS_CACHE_REDIS_CONN_MAX_IDLE_TIME` | Maximum duration a connection may be idle before being closed. (restart required, Commercial) |
+| `cache.redis.conn_max_lifetime` | string | `30m` | `TALOS_CACHE_REDIS_CONN_MAX_LIFETIME` | Maximum duration a connection may be reused. (restart required, Commercial) |
+| `cache.redis.db` | integer | `0` | `TALOS_CACHE_REDIS_DB` | Redis database number. (restart required, Commercial) |
+| `cache.redis.min_idle_conns` | integer | `2` | `TALOS_CACHE_REDIS_MIN_IDLE_CONNS` | Minimum number of idle connections kept open. (restart required, Commercial) |
+| `cache.redis.password` | string | — | `TALOS_CACHE_REDIS_PASSWORD` | Redis password. (restart required, Commercial) |
+| `cache.redis.pool_size` | integer | `100` | `TALOS_CACHE_REDIS_POOL_SIZE` | Connection pool size (Commercial) |
+| `cache.redis.timeout` | string | `3s` | `TALOS_CACHE_REDIS_TIMEOUT` | Redis operation timeout (duration string) (Commercial) |
+| `cache.redis.tls.enabled` | boolean | `false` | `TALOS_CACHE_REDIS_TLS_ENABLED` | Enable TLS using the system certificate pool. (restart required, Commercial) |
+| `cache.ttl` | string | `5m` | `TALOS_CACHE_TTL` | Default cache TTL (duration string). (Commercial) |
+| `cache.type` | `memory`, `redis`, `noop` | `noop` | `TALOS_CACHE_TYPE` | Cache implementation type. (restart required, Commercial) |
+
+## `credentials`
+
+Credential configuration for API keys and derived tokens (JWT, macaroon).
+
+| Key | Type | Default | Env Var | Description |
+| ---------------------------------------------------- | -------- | -------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
+| `credentials.api_keys.default_ttl` | string | — | `TALOS_CREDENTIALS_API_KEYS_DEFAULT_TTL` | Default API key TTL (duration string). |
+| `credentials.api_keys.max_ttl` | string | `8760h` | `TALOS_CREDENTIALS_API_KEYS_MAX_TTL` | Maximum age for API keys with timestamps. |
+| `credentials.api_keys.prefix.current` | string | `ory_ak` | `TALOS_CREDENTIALS_API_KEYS_PREFIX_CURRENT` | Current prefix used for new API key generation. |
+| `credentials.api_keys.prefix.public_current` | string | — | `TALOS_CREDENTIALS_API_KEYS_PREFIX_PUBLIC_CURRENT` | Current prefix used for new PUBLIC API key generation. |
+| `credentials.api_keys.prefix.public_retired` | string[] | `[]` | `TALOS_CREDENTIALS_API_KEYS_PREFIX_PUBLIC_RETIRED` | Retired public prefixes accepted during verification for migration purposes. |
+| `credentials.api_keys.prefix.retired` | string[] | `[]` | `TALOS_CREDENTIALS_API_KEYS_PREFIX_RETIRED` | Retired prefixes accepted during verification for migration purposes. |
+| `credentials.clock_skew` | string | `5m` | `TALOS_CREDENTIALS_CLOCK_SKEW` | Maximum clock skew tolerance for timestamp and token validation. |
+| `credentials.derived_tokens.default_ttl` | string | `1h` | `TALOS_CREDENTIALS_DERIVED_TOKENS_DEFAULT_TTL` | Default derived token TTL applied to both JWT and macaroon tokens when no explicit TTL is provided in the request (duration string) |
+| `credentials.derived_tokens.jwt.signing_key_id` | string | — | `TALOS_CREDENTIALS_DERIVED_TOKENS_JWT_SIGNING_KEY_ID` | Optional JWK 'kid' hint used to select the active signing key. |
+| `credentials.derived_tokens.jwt.signing_keys.urls` | string[] | `[]` | `TALOS_CREDENTIALS_DERIVED_TOKENS_JWT_SIGNING_KEYS_URLS` | List of JWKS resources. |
+| `credentials.derived_tokens.macaroon.prefix.current` | string | `mc` | `TALOS_CREDENTIALS_DERIVED_TOKENS_MACAROON_PREFIX_CURRENT` | Current prefix used for new macaroon token generation. |
+| `credentials.derived_tokens.macaroon.prefix.retired` | string[] | `[]` | `TALOS_CREDENTIALS_DERIVED_TOKENS_MACAROON_PREFIX_RETIRED` | Retired prefixes accepted during macaroon verification for rotation purposes. |
+| `credentials.issuer` | string | — | `TALOS_CREDENTIALS_ISSUER` | Token issuer (iss claim) for derived tokens. (min 1 chars) |
+| `credentials.issuer_retired` | string[] | `[]` | `TALOS_CREDENTIALS_ISSUER_RETIRED` | Retired issuer URLs accepted during token verification. |
+
+## `db` (restart required)
+
+Database configuration.
+
+| Key | Type | Default | Env Var | Description |
+| -------- | ------ | ------- | -------------- | ----------------------------------------------------------------------------------------------------- |
+| `db.dsn` | string | — | `TALOS_DB_DSN` | Database connection string with scheme and optional query parameters. (restart required, min 1 chars) |
+
+## `last_used` (restart required)
+
+Configuration for batched last_used_at timestamp updates.
+
+| Key | Type | Default | Env Var | Description |
+| -------------------------- | ------- | ------- | -------------------------------- | ------------------------------------------------------------------------------- |
+| `last_used.flush_interval` | string | `30s` | `TALOS_LAST_USED_FLUSH_INTERVAL` | Maximum time between batch flushes (Go duration string, e.g. (restart required) |
+| `last_used.flush_size` | integer | `100` | `TALOS_LAST_USED_FLUSH_SIZE` | Number of updates per shard that triggers a batch flush. (restart required) |
+| `last_used.num_workers` | integer | `4` | `TALOS_LAST_USED_NUM_WORKERS` | Number of goroutines processing last-used batches. (restart required) |
+| `last_used.queue_size` | integer | `10000` | `TALOS_LAST_USED_QUEUE_SIZE` | Buffer size for the async last-used update queue. (restart required) |
+
+## `log` (restart required)
+
+Logging configuration.
+
+| Key | Type | Default | Env Var | Description |
+| ------------ | -------------------------------- | ------- | ------------------ | ------------------------------ |
+| `log.format` | `json`, `text` | `json` | `TALOS_LOG_FORMAT` | Log format. (restart required) |
+| `log.level` | `debug`, `info`, `warn`, `error` | `info` | `TALOS_LOG_LEVEL` | Log level. (restart required) |
+
+## `multitenancy` Commercial (restart required)
+
+Multi-tenancy configuration.
+
+| Key | Type | Default | Env Var | Description |
+| ----------------------- | -------- | ------- | ----------------------------- | ------------------------------------------------------------- |
+| `multitenancy.enabled` | boolean | `false` | `TALOS_MULTITENANCY_ENABLED` | Enable multi-tenancy support. (restart required, Commercial) |
+| `multitenancy.networks` | object[] | `[]` | `TALOS_MULTITENANCY_NETWORKS` | Network routing configuration. (restart required, Commercial) |
+
+## `rate_limit` Commercial
+
+Rate limit enforcement for API keys with a RateLimitPolicy.
+
+| Key | Type | Default | Env Var | Description |
+| -------------------- | ----------------- | -------- | -------------------------- | ----------------------------------------------- |
+| `rate_limit.backend` | `memory`, `redis` | `memory` | `TALOS_RATE_LIMIT_BACKEND` | Counter backend. (restart required, Commercial) |
+| `rate_limit.enabled` | boolean | `false` | `TALOS_RATE_LIMIT_ENABLED` | Enable rate limit enforcement. (Commercial) |
+
+## `secrets`
+
+Centralized secrets management.
+
+| Key | Type | Default | Env Var | Description |
+| ---------------------------- | -------- | ------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
+| `secrets.default.current` | string | — | `TALOS_SECRETS_DEFAULT_CURRENT` | Current default secret for all components without specific overrides (min 32 chars) |
+| `secrets.default.retired` | string[] | `[]` | `TALOS_SECRETS_DEFAULT_RETIRED` | Retired default secrets that remain valid for verification during rotation |
+| `secrets.hmac.current` | string | — | `TALOS_SECRETS_HMAC_CURRENT` | Current HMAC secret for new key generation and checksum verification (min 32 chars) |
+| `secrets.hmac.retired` | string[] | `[]` | `TALOS_SECRETS_HMAC_RETIRED` | Retired HMAC secrets that remain valid for verification during rotation |
+| `secrets.pagination.current` | string | — | `TALOS_SECRETS_PAGINATION_CURRENT` | Secret used to sign and encrypt pagination tokens. (min 32 chars) |
+| `secrets.pagination.retired` | string[] | `[]` | `TALOS_SECRETS_PAGINATION_RETIRED` | List of retired pagination secrets that should remain valid for decoding legacy page tokens during secret rotation. |
+
+## `serve`
+
+Server configuration for HTTP and metrics endpoints.
+
+| Key | Type | Default | Env Var | Description |
+| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `serve.http.client_ip_source` | `CLIENT_IP_SOURCE_UNSPECIFIED`, `CLIENT_IP_SOURCE_REMOTE_ADDR`, `CLIENT_IP_SOURCE_CF_CONNECTING_IP`, `CLIENT_IP_SOURCE_X_FORWARDED_FOR`, `CLIENT_IP_SOURCE_X_REAL_IP`, `CLIENT_IP_SOURCE_TRUE_CLIENT_IP` | `CLIENT_IP_SOURCE_UNSPECIFIED` | `TALOS_SERVE_HTTP_CLIENT_IP_SOURCE` | Determines which HTTP header or connection property is used to resolve the client IP for IP restriction checks. Must match your infrastructure topology. Default (unspecified) uses the TCP remote address. Hot-reloadable: read dynamically per request. |
+| `serve.http.cors.allow_credentials` | boolean | `false` | `TALOS_SERVE_HTTP_CORS_ALLOW_CREDENTIALS` | Indicates whether the request can include user credentials like cookies, HTTP authentication or client side SSL certificates. |
+| `serve.http.cors.allowed_headers` | string[] | `["Authorization","Content-Type"]` | `TALOS_SERVE_HTTP_CORS_ALLOWED_HEADERS` | A list of non simple headers the client is allowed to use with cross-domain requests. (min 1 chars) |
+| `serve.http.cors.allowed_methods` | string[] | `["GET","POST","PUT","PATCH","DELETE"]` | `TALOS_SERVE_HTTP_CORS_ALLOWED_METHODS` | A list of methods the client is allowed to use with cross-domain requests. |
+| `serve.http.cors.allowed_origins` | string[] | `["*"]` | `TALOS_SERVE_HTTP_CORS_ALLOWED_ORIGINS` | A list of origins a cross-domain request can be executed from. |
+| `serve.http.cors.debug` | boolean | `false` | `TALOS_SERVE_HTTP_CORS_DEBUG` | Set to true to debug server side CORS issues. |
+| `serve.http.cors.enabled` | boolean | `false` | `TALOS_SERVE_HTTP_CORS_ENABLED` | If set to true, CORS will be enabled and preflight-requests (OPTION) will be answered. |
+| `serve.http.cors.exposed_headers` | string[] | `["Content-Type"]` | `TALOS_SERVE_HTTP_CORS_EXPOSED_HEADERS` | Indicates which headers are safe to expose to the API of a CORS API specification (min 1 chars) |
+| `serve.http.cors.max_age` | number | `0` | `TALOS_SERVE_HTTP_CORS_MAX_AGE` | Indicates how long (in seconds) the results of a preflight request can be cached. |
+| `serve.http.host` | string | `0.0.0.0` | `TALOS_SERVE_HTTP_HOST` | The host (interface) that the endpoint listens on. (restart required) |
+| `serve.http.port` | integer | `4420` | `TALOS_SERVE_HTTP_PORT` | The port that the endpoint listens on. (restart required) |
+| `serve.http.request_log.exclude_health_endpoints` | boolean | `false` | `TALOS_SERVE_HTTP_REQUEST_LOG_EXCLUDE_HEALTH_ENDPOINTS` | Exclude /health/alive and /health/ready endpoints from request logs |
+| `serve.http.trust_forwarded_host` | boolean | `false` | `TALOS_SERVE_HTTP_TRUST_FORWARDED_HOST` | Trust the X-Forwarded-Host header for tenant routing. (restart required) |
+| `serve.metrics.host` | string | `0.0.0.0` | `TALOS_SERVE_METRICS_HOST` | The host (interface) that the metrics endpoint listens on. (restart required, Commercial) |
+| `serve.metrics.port` | integer | `4422` | `TALOS_SERVE_METRICS_PORT` | The port that the metrics endpoint listens on. (restart required, Commercial) |
+
+## `tracing` Commercial (restart required)
+
+OpenTelemetry tracing configuration.
+
+| Key | Type | Default | Env Var | Description |
+| ------------------------- | ------- | ------------- | ------------------------------- | ------------------------------------------------------------------------------ |
+| `tracing.enabled` | boolean | `false` | `TALOS_TRACING_ENABLED` | Enable tracing. (restart required, Commercial) |
+| `tracing.endpoint` | string | — | `TALOS_TRACING_ENDPOINT` | Trace collector endpoint. (restart required, Commercial) |
+| `tracing.environment` | string | `development` | `TALOS_TRACING_ENVIRONMENT` | Deployment environment tag in trace attributes. (restart required, Commercial) |
+| `tracing.exporter` | `otlp` | — | `TALOS_TRACING_EXPORTER` | Trace exporter type. (restart required, Commercial) |
+| `tracing.sample_rate` | number | `0.001` | `TALOS_TRACING_SAMPLE_RATE` | Sampling rate (0.0 to 1.0). (restart required, Commercial) |
+| `tracing.service_name` | string | `talos` | `TALOS_TRACING_SERVICE_NAME` | Service name reported to OpenTelemetry. (restart required, Commercial) |
+| `tracing.service_version` | string | `0.0.0` | `TALOS_TRACING_SERVICE_VERSION` | Service version reported to OpenTelemetry. (restart required, Commercial) |
diff --git a/docs/talos/reference/error-codes.md b/docs/talos/reference/error-codes.md
new file mode 100644
index 000000000..c9cc5094b
--- /dev/null
+++ b/docs/talos/reference/error-codes.md
@@ -0,0 +1,99 @@
+---
+title: Error codes
+description: HTTP and gRPC error codes returned by the Talos API
+---
+
+
+
+
+# Error codes
+
+Talos returns structured error responses following the [herodot](https://github.com/ory/herodot) error format. Every error
+response includes an `id`, HTTP status code, status text, and a human-readable message.
+
+## Error response format
+
+```json
+{
+ "error": {
+ "code": 400,
+ "status": "Bad Request",
+ "message": "The API key format is invalid.",
+ "reason": "Additional context about the error"
+ }
+}
+```
+
+## Application errors
+
+| Error ID | HTTP | gRPC | Description |
+| ----------------------------- | ---- | --------------------- | -------------------------------------------------------------------------- |
+| `bad_request` | 400 | `INVALID_ARGUMENT` | The request was malformed or contained invalid parameters |
+| `credential_required` | 400 | `INVALID_ARGUMENT` | A credential is required. |
+| `derived_token_not_revocable` | 400 | `INVALID_ARGUMENT` | Derived tokens cannot be revoked. |
+| `invalid_api_key_format` | 400 | `INVALID_ARGUMENT` | The API key format is invalid. |
+| `invalid_token_type` | 400 | `INVALID_ARGUMENT` | The token type is invalid. |
+| `unknown_credential` | 400 | `INVALID_ARGUMENT` | The credential type is not recognized. |
+| `api_key_expired` | 401 | `UNAUTHENTICATED` | The API key has expired. |
+| `api_key_revoked` | 401 | `UNAUTHENTICATED` | The API key has been revoked. |
+| `parent_key_invalid` | 401 | `UNAUTHENTICATED` | Parent key validation failed. |
+| `signature_invalid` | 401 | `UNAUTHENTICATED` | Signature verification failed. |
+| `unauthorized` | 401 | `UNAUTHENTICATED` | The request could not be authorized |
+| `forbidden` | 403 | `PERMISSION_DENIED` | The requested action was forbidden |
+| `ip_not_allowed` | 403 | `PERMISSION_DENIED` | The request IP is not allowed for this API key. |
+| `payment_required` | 403 | `PERMISSION_DENIED` | The feature is not available and requires payment. |
+| `api_key_not_found` | 404 | `NOT_FOUND` | The API key was not found. |
+| `not_found` | 404 | `NOT_FOUND` | The requested resource could not be found |
+| `api_key_exists` | 409 | `ALREADY_EXISTS` | An API key with this identifier already exists. |
+| `conflict` | 409 | `ALREADY_EXISTS` | The resource could not be created due to a conflict |
+| `failed_precondition` | 409 | `FAILED_PRECONDITION` | The operation cannot be completed due to a failed precondition. |
+| `too_many_requests` | 429 | `RESOURCE_EXHAUSTED` | The request was throttled due to resource exhaustion. |
+| `internal_server_error` | 500 | `INTERNAL` | An internal server error occurred, please contact the system administrator |
+| `service_unavailable` | 503 | `UNAVAILABLE` | The service is temporarily unavailable. |
+| `gateway_timeout` | 504 | `DEADLINE_EXCEEDED` | The operation timed out. |
+
+## Standard HTTP errors
+
+| Error ID | HTTP | Description |
+| -------------------------------- | ---- | ------------------------ |
+| Standard `bad_request` | 400 | Generic validation error |
+| Standard `unauthorized` | 401 | Authentication required |
+| Standard `forbidden` | 403 | Insufficient permissions |
+| Standard `not_found` | 404 | Resource not found |
+| Standard `conflict` | 409 | Resource conflict |
+| Standard `internal_server_error` | 500 | Unexpected server error |
+
+## Verification error codes
+
+The `VerifyAPIKey` response includes an `error_code` enum when verification fails:
+
+| Code | Meaning |
+| -------------------------------------- | -------------------------------------------------- |
+| `VERIFICATION_ERROR_UNSPECIFIED` | No error (key is valid) |
+| `VERIFICATION_ERROR_INVALID_FORMAT` | Credential format is invalid |
+| `VERIFICATION_ERROR_EXPIRED` | Credential has expired |
+| `VERIFICATION_ERROR_REVOKED` | Credential has been revoked |
+| `VERIFICATION_ERROR_NOT_FOUND` | Credential not found in database |
+| `VERIFICATION_ERROR_SIGNATURE_INVALID` | Cryptographic signature verification failed |
+| `VERIFICATION_ERROR_INTERNAL` | Internal server error during verification |
+| `VERIFICATION_ERROR_IP_NOT_ALLOWED` | Request IP is not in the key's allowed CIDR ranges |
+| `VERIFICATION_ERROR_RATE_LIMITED` | Rate limit quota exhausted (commercial-only) |
+
+## Batch import error codes
+
+The `BatchImportAPIKeys` response includes per-item error codes:
+
+| Code | Meaning |
+| ---------------------------------------- | ---------------------------------------------------- |
+| `BATCH_IMPORT_ERROR_UNSPECIFIED` | No error (import succeeded) |
+| `BATCH_IMPORT_ERROR_INVALID_ARGUMENT` | The key data is malformed or missing required fields |
+| `BATCH_IMPORT_ERROR_ALREADY_EXISTS` | A key with this identifier already exists |
+| `BATCH_IMPORT_ERROR_FAILED_PRECONDITION` | State conflict prevents the import |
+| `BATCH_IMPORT_ERROR_INTERNAL` | Server error during import |
+
+## Error handling recommendations
+
+- **4xx errors**: Fix the request and retry. Do not retry without changes.
+- **409 Conflict**: Check if the resource already exists or is in an incompatible state.
+- **5xx errors**: Retry with exponential backoff and jitter.
+- **503 Service Unavailable**: The server is temporarily overloaded. Retry after the `Retry-After` header value if present.
diff --git a/docs/talos/reference/events.md b/docs/talos/reference/events.md
new file mode 100644
index 000000000..53c89a63c
--- /dev/null
+++ b/docs/talos/reference/events.md
@@ -0,0 +1,76 @@
+---
+title: Audit events
+description: Structured audit events emitted by Talos via OpenTelemetry
+---
+
+
+
+
+# Audit events
+
+Talos emits structured audit events via OpenTelemetry span events for all significant lifecycle operations. Events are attached to
+the active OTEL span and forwarded to any configured OTEL collector. They are never persisted locally.
+
+Each event carries a set of structured attributes that provide context about the operation, the actor, and the affected resource.
+
+## Event types
+
+| Constant | Event Name | Description |
+| ----------------------------------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------- |
+| `EventAPIKeyCreated` | `APIKeyCreated` | EventAPIKeyCreated is emitted when an API key is created (issued or imported). |
+| Use the KeyType attribute to distinguish between the two origins. |
+| `EventAPIKeyUpdated` | `APIKeyUpdated` | EventAPIKeyUpdated is emitted when an API key's metadata is updated. |
+| `EventAPIKeyRevoked` | `APIKeyRevoked` | EventAPIKeyRevoked is emitted when an API key is revoked. |
+| `EventAPIKeyRotated` | `APIKeyRotated` | EventAPIKeyRotated is emitted when an API key is rotated. |
+| `EventAPIKeyVerified` | `APIKeyVerified` | EventAPIKeyVerified is emitted when an API key is successfully verified. |
+| `EventAPIKeyVerificationFailed` | `APIKeyVerificationFailed` | EventAPIKeyVerificationFailed is emitted when an API key verification fails. |
+| `EventAPIKeyImportFailed` | `APIKeyImportFailed` | EventAPIKeyImportFailed is emitted when an API key import fails. |
+| `EventTokenDerived` | `TokenDerived` | EventTokenDerived is emitted when a session token is derived from an API key. |
+| `EventAPIKeyDeleted` | `APIKeyDeleted` | EventAPIKeyDeleted is emitted when an issued API key is permanently deleted. |
+| `EventImportedAPIKeyDeleted` | `ImportedAPIKeyDeleted` | EventImportedAPIKeyDeleted is emitted when an imported API key is permanently deleted. |
+
+## Event attributes
+
+Each event carries the following OTEL span event attributes:
+
+| OTEL Key | Struct Field | Type | Required | Description |
+| -------------- | ------------ | ----------------- | -------- | --------------------------------------------------------------------------------------------- |
+| `` | `NetworkID` | uuid.UUID | Required | AttrNetworkID uses the shared semconv NID key so the analytics pipeline can route by project. |
+| `APIKeyID` | `KeyID` | string | Optional | Key identification (present for key-related events) |
+| `APIKeyPrefix` | `Prefix` | string | Optional | |
+| `KeyType` | `KeyType` | string | Optional | Key origin (present for created/rotated events) |
+| `Operation` | `Operation` | string | Optional | Operation context |
+| `Reason` | `Reason` | string | Optional | Failure reason or additional context |
+| `ActorID` | `ActorID` | string | Optional | Actor information (who performed the operation) |
+| `Expiry` | `Expiry` | \*time.Time | Optional | Key properties (present for create/rotate/update events) |
+| `Visibility` | `Visibility` | string | Optional | "public" or "secret" |
+| `metadata.` | `Metadata` | map[string]string | Optional | Additional context (varies by event type) |
+
+## Dynamic metadata attributes
+
+The `metadata.*` prefix supports arbitrary key-value pairs for event-specific context. Metadata keys are prefixed with `metadata.`
+in OTEL attributes. For example, a metadata entry `{"token_type": "jwt"}` becomes the OTEL attribute `metadata.token_type` with
+value `jwt`.
+
+Metadata is optional and varies by event type. Common metadata keys include:
+
+- `token_type` — Type of derived token (e.g., `jwt`, `macaroon`)
+- `previous_key_id` — ID of the key being replaced during rotation
+- `import_source` — Origin of an imported API key
+
+## Emitting events
+
+Events are constructed using the fluent builder pattern:
+
+```go
+emitter := events.NewOTELEmitter()
+events.New(events.EventAPIKeyCreated).
+ WithNetworkID(networkID).
+ WithKeyType("issued").
+ WithKeyID(keyID).
+ WithPrefix("talos").
+ WithActor(actorID).
+ Emit(ctx, emitter)
+```
+
+Events are attached to the active OpenTelemetry span. If no span is recording, the event is silently dropped.
diff --git a/docs/talos/reference/index.md b/docs/talos/reference/index.md
new file mode 100644
index 000000000..969be7c80
--- /dev/null
+++ b/docs/talos/reference/index.md
@@ -0,0 +1,26 @@
+---
+title: Reference
+description: API, configuration, and technical reference
+---
+
+# Reference
+
+Technical reference documentation for Ory Talos.
+
+## API
+
+- [API reference](api/ory-talos-api.info.mdx) — auto-generated from the OpenAPI specification
+
+## Configuration
+
+- [Configuration reference](config.mdx) — all configuration keys with types and defaults
+
+## Technical details
+
+- [Error codes](error-codes.md) — HTTP and gRPC error codes returned by the API
+- [Token format](token-format.md) — API key and session token structure
+- [Audit events](events.md) — emitted lifecycle and verification events
+
+## CLI
+
+- [`talos`](cli/talos.md) — root command and subcommand index
diff --git a/docs/talos/reference/token-format.md b/docs/talos/reference/token-format.md
new file mode 100644
index 000000000..4b2bf1217
--- /dev/null
+++ b/docs/talos/reference/token-format.md
@@ -0,0 +1,119 @@
+---
+title: Token format reference
+description: API key and derived token structure
+---
+
+# Token format
+
+Talos uses structured token formats that encode metadata for efficient routing and verification.
+
+## API key format
+
+Generated API keys follow a versioned format:
+
+```
+_v1__
+```
+
+Example:
+
+```
+prod_v1_5Z7Hn9K3mPqRtVwXyBcDeFgHiJkLmNoPqRsTuVwXyZ_AbC3XyZ789e
+```
+
+### Components
+
+| Component | Length | Description |
+| ------------ | ---------- | ---------------------------------------------------------------------------------------------------------- |
+| `prefix` | 1-16 chars | User-defined label (e.g., `prod`, `dev`, `test`). Set via `credentials.api_keys.prefix.current` in config. |
+| `v1` | 2 chars | Format version identifier |
+| `identifier` | ~64 chars | Base58-encoded `timestamp:uuid` payload |
+| `checksum` | ~44 chars | Full 32-byte HMAC-SHA256 over `prefix_v1_identifier_`, Base58-encoded |
+
+### Identifier encoding
+
+The identifier is a Base58 encoding of `timestamp:uuid`:
+
+- **Timestamp**: Unix epoch seconds (int64). Embedded at key creation time.
+- **UUID**: UUID v4 (36 chars with hyphens). Used as the `key_id` for database lookup.
+
+Base58 encoding uses the Bitcoin alphabet (`123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`), which excludes visually
+ambiguous characters (`0`, `O`, `I`, `l`).
+
+### Checksum verification
+
+The checksum is computed over the payload `prefix_v1_identifier_`:
+
+1. Compute HMAC-SHA256 using the current HMAC secret (`secrets.hmac.current`)
+2. Base58-encode the full 32-byte digest (no truncation)
+
+During verification, all configured secrets (current + retired) are tried in order. This supports secret rotation without
+invalidating existing keys.
+
+### Credential routing
+
+When a credential is submitted for verification, Talos identifies the credential type by format:
+
+| Format match | Credential type | Lookup method |
+| ----------------------------------- | ----------------- | ---------------------------------------- |
+| `_v1__` | Generated API key | UUID extracted from identifier |
+| JWT format (`eyJ...`) | Derived JWT | Claims extracted during verification |
+| Macaroon prefix (`_v1_...`) | Derived macaroon | Identifier extracted during verification |
+| None of the above | Imported key | SHA-512/256 hash with tenant scope |
+
+## Imported key format
+
+Imported keys have no format requirements. Any string credential can be imported. Talos stores a tenant-scoped hash:
+
+```
+SHA-512/256(network_id + 0x00 + raw_key)
+```
+
+The null byte separator prevents ambiguity between network ID and key content.
+
+## Derived token formats
+
+### JWT
+
+Derived tokens produced as JWTs follow the standard JWT format:
+
+```
+eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature
+```
+
+Claims include the parent key's `key_id`, `actor_id`, scopes, and expiration. The signing algorithm is determined by the `alg`
+field in the JWK (EdDSA or RS256).
+
+#### Signing key selection (`kid` hint)
+
+The data plane resolves the active signing key on every derive request. The `kid` header in the issued JWT identifies which JWK
+from the configured JWKS produced the signature.
+
+Resolution order:
+
+1. If `credentials.derived_tokens.jwt.signing_key_id` is set, Talos selects the JWK whose `kid` matches. If no JWK has that `kid`,
+ signing fails with `InternalError` and the requested `signing_key_id` appears in the error details.
+2. Otherwise, Talos prefers the first key with `"use": "sig"`.
+3. Otherwise, Talos returns the first key in the JWKS.
+
+Set `signing_key_id` explicitly in production so rotating signing material becomes a config change rather than a JWKS-ordering
+side effect. In multi-tenant deployments the JWKS resolves per tenant via the contextualizer; the `kid` hint is also per-tenant.
+
+### Macaroon
+
+Macaroon tokens use a configurable prefix:
+
+```
+_v1_
+```
+
+The prefix is configured via `credentials.derived_tokens.macaroon.prefix.current` (default: `mc`). The data section contains the
+macaroon identifier and signature.
+
+## ID formats
+
+| Context | Format | Length | Example |
+| ------------------ | ----------------------- | --------- | -------------------------------------------- |
+| Database storage | UUID v4 string | 36 chars | `550e8400-e29b-41d4-a716-446655440000` |
+| API key identifier | Base58-encoded | ~64 chars | `5Z7Hn9K3mPqRtVwXyBcDeFgHiJkLmNoPqRsTuVwXyZ` |
+| Imported key hash | Hex-encoded SHA-512/256 | 64 chars | `a1b2c3d4...` |
diff --git a/docusaurus.config.ts b/docusaurus.config.ts
index 295267dca..478e027d7 100644
--- a/docusaurus.config.ts
+++ b/docusaurus.config.ts
@@ -3,6 +3,7 @@
import type { Config } from "@docusaurus/types"
import type * as Preset from "@docusaurus/preset-classic"
+import type * as OpenApiPlugin from "docusaurus-plugin-openapi-docs"
import lightTheme from "./src/utils/prismLight.mjs"
import darkTheme from "./src/utils/prismDark.mjs"
@@ -175,6 +176,21 @@ const config: Config = {
disableVersioning: false,
include: ["**/*.md", "**/*.mdx", "**/*.jsx", "**/*.tsx"],
docRootComponent: "@theme/DocRoot",
+ docItemComponent: "@theme/ApiItem",
+ },
+ ],
+ [
+ "docusaurus-plugin-openapi-docs",
+ {
+ id: "openapi",
+ docsPluginId: "default",
+ config: {
+ talos: {
+ specPath: "docs/talos/reference/api.json",
+ outputDir: "docs/talos/reference/api",
+ sidebarOptions: { groupPathsBy: "tag" },
+ } satisfies OpenApiPlugin.Options,
+ },
},
],
"@docusaurus/plugin-content-pages",
@@ -231,6 +247,7 @@ const config: Config = {
],
"@docusaurus/theme-search-algolia",
"docusaurus-theme-redoc",
+ "docusaurus-theme-openapi-docs",
],
headTags: [],
}
diff --git a/package-lock.json b/package-lock.json
index e1720c126..5c0d06a3c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,6 +30,8 @@
"classnames": "2.5.1",
"clsx": "2.1.0",
"debug": "4.3.4",
+ "docusaurus-plugin-openapi-docs": "4.7.1",
+ "docusaurus-theme-openapi-docs": "4.7.1",
"file-loader": "6.2.0",
"json-loader": "0.5.7",
"json-schema-faker": "0.5.8",
@@ -4383,6 +4385,13 @@
"integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==",
"license": "MIT"
},
+ "node_modules/@faker-js/faker": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-5.5.3.tgz",
+ "integrity": "sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw==",
+ "deprecated": "Please update to a newer version.",
+ "license": "MIT"
+ },
"node_modules/@hapi/hoek": {
"version": "9.3.0",
"license": "BSD-3-Clause"
@@ -4394,6 +4403,17 @@
"@hapi/hoek": "^9.0.0"
}
},
+ "node_modules/@hookform/error-message": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.1.tgz",
+ "integrity": "sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0",
+ "react-hook-form": "^7.0.0"
+ }
+ },
"node_modules/@iconify-json/tabler": {
"version": "1.2.19",
"resolved": "https://registry.npmjs.org/@iconify-json/tabler/-/tabler-1.2.19.tgz",
@@ -5293,6 +5313,12 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@jsdevtools/ono": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
+ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
+ "license": "MIT"
+ },
"node_modules/@jsep-plugin/assignment": {
"version": "1.3.0",
"license": "MIT",
@@ -5692,6 +5718,315 @@
"version": "v1.15.16",
"license": "Apache-2.0"
},
+ "node_modules/@parcel/watcher": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
+ "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.3",
+ "is-glob": "^4.0.3",
+ "node-addon-api": "^7.0.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher-android-arm64": "2.5.6",
+ "@parcel/watcher-darwin-arm64": "2.5.6",
+ "@parcel/watcher-darwin-x64": "2.5.6",
+ "@parcel/watcher-freebsd-x64": "2.5.6",
+ "@parcel/watcher-linux-arm-glibc": "2.5.6",
+ "@parcel/watcher-linux-arm-musl": "2.5.6",
+ "@parcel/watcher-linux-arm64-glibc": "2.5.6",
+ "@parcel/watcher-linux-arm64-musl": "2.5.6",
+ "@parcel/watcher-linux-x64-glibc": "2.5.6",
+ "@parcel/watcher-linux-x64-musl": "2.5.6",
+ "@parcel/watcher-win32-arm64": "2.5.6",
+ "@parcel/watcher-win32-ia32": "2.5.6",
+ "@parcel/watcher-win32-x64": "2.5.6"
+ }
+ },
+ "node_modules/@parcel/watcher-android-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
+ "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
+ "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
+ "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-freebsd-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
+ "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
+ "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
+ "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
+ "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
+ "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-glibc": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
+ "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-musl": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
+ "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-arm64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
+ "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-ia32": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
+ "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-x64": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
+ "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/@pkgr/core": {
"version": "0.1.1",
"dev": true,
@@ -5837,6 +6172,32 @@
"node": ">=10"
}
},
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.11.2",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.2.tgz",
+ "integrity": "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@standard-schema/utils": "^0.3.0",
+ "immer": "^11.0.0",
+ "redux": "^5.0.1",
+ "redux-thunk": "^3.1.0",
+ "reselect": "^5.1.0"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
+ "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@restart/context": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
@@ -6037,6 +6398,12 @@
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
"integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="
},
+ "node_modules/@standard-schema/utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
+ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
+ "license": "MIT"
+ },
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
@@ -7457,6 +7824,12 @@
"version": "3.0.3",
"license": "MIT"
},
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT"
+ },
"node_modules/@types/warning": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
@@ -7748,6 +8121,20 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
+ "node_modules/ajv-draft-04": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz",
+ "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "ajv": "^8.5.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
"node_modules/ajv-formats": {
"version": "2.1.1",
"license": "MIT",
@@ -7809,6 +8196,15 @@
"algoliasearch": ">= 3.1 < 6"
}
},
+ "node_modules/allof-merge": {
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/allof-merge/-/allof-merge-0.6.8.tgz",
+ "integrity": "sha512-RJrHVDqITsU1kjE2L7s1hy4AYZSTlO1m9jTleYhVCEOfOpbbygRGfcEgrp+bW3oX/PcMUwVkt6MSJyXoyI6lRA==",
+ "license": "MIT",
+ "dependencies": {
+ "json-crawl": "^0.5.3"
+ }
+ },
"node_modules/anchor-markdown-header": {
"version": "0.5.7",
"dev": true,
@@ -7897,6 +8293,12 @@
"node": ">=4"
}
},
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "license": "MIT"
+ },
"node_modules/anymatch": {
"version": "3.1.3",
"license": "ISC",
@@ -8007,6 +8409,12 @@
"astring": "bin/astring"
}
},
+ "node_modules/async": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "license": "MIT"
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"license": "MIT"
@@ -8889,6 +9297,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/charset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz",
+ "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/cheerio": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
@@ -9503,6 +9920,18 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
+ "node_modules/copy-text-to-clipboard": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.2.tgz",
+ "integrity": "sha512-T6SqyLd1iLuqPA90J5N4cTalrtovCySh58iiZDGJ6FGznbclKh4UI+FGacQSgFzwKG77W7XT5gwbVEbd9cIH1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/copy-webpack-plugin": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz",
@@ -9729,6 +10158,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/crypto-js": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
+ "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
+ "license": "MIT"
+ },
"node_modules/crypto-random-string": {
"version": "4.0.0",
"license": "MIT",
@@ -10912,7 +11347,7 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
- "dev": true,
+ "devOptional": true,
"license": "Apache-2.0",
"engines": {
"node": ">=8"
@@ -10931,6 +11366,18 @@
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="
},
+ "node_modules/detect-package-manager": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-3.0.2.tgz",
+ "integrity": "sha512-8JFjJHutStYrfWwzfretQoyNGoZVW1Fsrp4JO9spa7h/fBfwgTMEIy4/LBzRDGsxwVPHU0q+T9YvwLDJoOApLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/detect-port": {
"version": "1.6.1",
"license": "MIT",
@@ -10979,41 +11426,156 @@
"dev": true,
"license": "MIT",
"engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/diffie-hellman": {
+ "version": "5.0.3",
+ "license": "MIT",
+ "dependencies": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "node_modules/diffie-hellman/node_modules/bn.js": {
+ "version": "4.12.0",
+ "license": "MIT"
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dns-packet": {
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
+ "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
+ "dependencies": {
+ "@leichtgewicht/ip-codec": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/docusaurus-plugin-openapi-docs": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-4.7.1.tgz",
+ "integrity": "sha512-RpqvTEnhIfdSuTn/Fa/8bmxeufijLL9HCRb//ELD33AKqEbCw147SKR/CqWu4H4gwi50FZLUbiHKZJbPtXLt9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@apidevtools/json-schema-ref-parser": "^11.5.4",
+ "@redocly/openapi-core": "^1.34.3",
+ "allof-merge": "^0.6.6",
+ "chalk": "^4.1.2",
+ "clsx": "^2.1.1",
+ "fs-extra": "^11.3.0",
+ "json-pointer": "^0.6.2",
+ "json5": "^2.2.3",
+ "lodash": "^4.17.21",
+ "mustache": "^4.2.0",
+ "openapi-to-postmanv2": "^5.0.0",
+ "postman-collection": "^5.0.2",
+ "slugify": "^1.6.6",
+ "swagger2openapi": "^7.0.8",
+ "xml-formatter": "^3.6.6"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@docusaurus/plugin-content-docs": "^3.5.0",
+ "@docusaurus/utils": "^3.5.0",
+ "@docusaurus/utils-validation": "^3.5.0",
+ "react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/docusaurus-plugin-openapi-docs/node_modules/@apidevtools/json-schema-ref-parser": {
+ "version": "11.9.3",
+ "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz",
+ "integrity": "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jsdevtools/ono": "^7.1.3",
+ "@types/json-schema": "^7.0.15",
+ "js-yaml": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/philsturgeon"
+ }
+ },
+ "node_modules/docusaurus-plugin-openapi-docs/node_modules/@redocly/config": {
+ "version": "0.22.0",
+ "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.22.0.tgz",
+ "integrity": "sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==",
+ "license": "MIT"
+ },
+ "node_modules/docusaurus-plugin-openapi-docs/node_modules/@redocly/openapi-core": {
+ "version": "1.34.11",
+ "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.34.11.tgz",
+ "integrity": "sha512-V09ayfnb5GyysmvARbt+voFZAjGcf7hSYxOYxSkCc4fbH/DTfq5YWoec8cflvmHHqyIFbqvmGKmYFzqhr9zxDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@redocly/ajv": "8.11.2",
+ "@redocly/config": "0.22.0",
+ "colorette": "1.4.0",
+ "https-proxy-agent": "7.0.6",
+ "js-levenshtein": "1.1.6",
+ "js-yaml": "4.1.1",
+ "minimatch": "5.1.9",
+ "pluralize": "8.0.0",
+ "yaml-ast-parser": "0.0.43"
+ },
+ "engines": {
+ "node": ">=18.17.0",
+ "npm": ">=9.5.0"
}
},
- "node_modules/diffie-hellman": {
- "version": "5.0.3",
+ "node_modules/docusaurus-plugin-openapi-docs/node_modules/brace-expansion": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+ "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
"license": "MIT",
"dependencies": {
- "bn.js": "^4.1.0",
- "miller-rabin": "^4.0.0",
- "randombytes": "^2.0.0"
+ "balanced-match": "^1.0.0"
}
},
- "node_modules/diffie-hellman/node_modules/bn.js": {
- "version": "4.12.0",
- "license": "MIT"
- },
- "node_modules/dir-glob": {
- "version": "3.0.1",
+ "node_modules/docusaurus-plugin-openapi-docs/node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"license": "MIT",
- "dependencies": {
- "path-type": "^4.0.0"
- },
"engines": {
- "node": ">=8"
+ "node": ">=6"
}
},
- "node_modules/dns-packet": {
- "version": "5.6.1",
- "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
- "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
+ "node_modules/docusaurus-plugin-openapi-docs/node_modules/minimatch": {
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
+ "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
+ "license": "ISC",
"dependencies": {
- "@leichtgewicht/ip-codec": "^2.0.1"
+ "brace-expansion": "^2.0.1"
},
"engines": {
- "node": ">=6"
+ "node": ">=10"
+ }
+ },
+ "node_modules/docusaurus-plugin-openapi-docs/node_modules/slugify": {
+ "version": "1.6.9",
+ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz",
+ "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
}
},
"node_modules/docusaurus-plugin-redoc": {
@@ -11032,6 +11594,80 @@
"@docusaurus/utils": "^3.6.0"
}
},
+ "node_modules/docusaurus-plugin-sass": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.6.tgz",
+ "integrity": "sha512-2hKQQDkrufMong9upKoG/kSHJhuwd+FA3iAe/qzS/BmWpbIpe7XKmq5wlz4J5CJaOPu4x+iDJbgAxZqcoQf0kg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "sass-loader": "^16.0.2"
+ },
+ "peerDependencies": {
+ "@docusaurus/core": "^2.0.0-beta || ^3.0.0-alpha",
+ "sass": "^1.30.0"
+ }
+ },
+ "node_modules/docusaurus-theme-openapi-docs": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-4.7.1.tgz",
+ "integrity": "sha512-OPydf11LoEY3fdxaoqCVO+qCk7LBo6l6s28UvHJ5mIN/2xu+dOOio9+xnKZ5FIPOlD+dx0gVSKzaVCi/UFTxlg==",
+ "license": "MIT",
+ "dependencies": {
+ "@hookform/error-message": "^2.0.1",
+ "@reduxjs/toolkit": "^2.8.2",
+ "allof-merge": "^0.6.6",
+ "buffer": "^6.0.3",
+ "clsx": "^2.1.1",
+ "copy-text-to-clipboard": "^3.2.0",
+ "crypto-js": "^4.2.0",
+ "file-saver": "^2.0.5",
+ "lodash": "^4.17.21",
+ "pako": "^2.1.0",
+ "postman-code-generators": "^2.0.0",
+ "postman-collection": "^5.0.2",
+ "prism-react-renderer": "^2.4.1",
+ "process": "^0.11.10",
+ "react-hook-form": "^7.59.0",
+ "react-live": "^4.1.8",
+ "react-magic-dropzone": "^1.0.1",
+ "react-markdown": "^10.1.0",
+ "react-modal": "^3.16.3",
+ "react-redux": "^9.2.0",
+ "rehype-raw": "^7.0.0",
+ "remark-gfm": "4.0.1",
+ "sass": "^1.89.2",
+ "sass-loader": "^16.0.5",
+ "unist-util-visit": "^5.0.0",
+ "url": "^0.11.4",
+ "xml-formatter": "^3.6.6"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@docusaurus/theme-common": "^3.5.0",
+ "docusaurus-plugin-openapi-docs": "^4.0.0",
+ "docusaurus-plugin-sass": "^0.2.3",
+ "react": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.4 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/docusaurus-theme-openapi-docs/node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/docusaurus-theme-openapi-docs/node_modules/pako": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
+ "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
+ "license": "(MIT AND Zlib)"
+ },
"node_modules/docusaurus-theme-redoc": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/docusaurus-theme-redoc/-/docusaurus-theme-redoc-2.5.0.tgz",
@@ -11793,6 +12429,12 @@
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
+ "node_modules/exenv": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
+ "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/exit": {
"version": "0.1.2",
"dev": true,
@@ -12108,6 +12750,21 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/file-saver": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
+ "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==",
+ "license": "MIT"
+ },
+ "node_modules/file-type": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
+ "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"license": "MIT",
@@ -12285,7 +12942,9 @@
"license": "MIT"
},
"node_modules/fs-extra": {
- "version": "11.2.0",
+ "version": "11.3.4",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz",
+ "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
@@ -12298,7 +12957,6 @@
},
"node_modules/fs.realpath": {
"version": "1.0.0",
- "dev": true,
"license": "ISC"
},
"node_modules/fsevents": {
@@ -12458,7 +13116,6 @@
},
"node_modules/glob": {
"version": "7.2.3",
- "dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
@@ -12617,6 +13274,15 @@
"version": "4.2.11",
"license": "ISC"
},
+ "node_modules/graphlib": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz",
+ "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash": "^4.17.15"
+ }
+ },
"node_modules/gray-matter": {
"version": "4.0.3",
"license": "MIT",
@@ -13061,6 +13727,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/html-url-attributes": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
+ "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/html-void-elements": {
"version": "3.0.0",
"license": "MIT",
@@ -13219,6 +13895,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/http-reasons": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/http-reasons/-/http-reasons-0.1.0.tgz",
+ "integrity": "sha512-P6kYh0lKZ+y29T2Gqz+RlC9WBLhKe8kDmcJ+A+611jFfxdPsbMRQ5aNmFRM3lENqFkK+HTTL+tlQviAiv0AbLQ==",
+ "license": "Apache-2.0"
+ },
"node_modules/http2-client": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz",
@@ -13341,6 +14023,22 @@
"node": ">=16.x"
}
},
+ "node_modules/immer": {
+ "version": "11.1.4",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.4.tgz",
+ "integrity": "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz",
+ "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
+ "license": "MIT"
+ },
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -13418,7 +14116,6 @@
},
"node_modules/inflight": {
"version": "1.0.6",
- "dev": true,
"license": "ISC",
"dependencies": {
"once": "^1.3.0",
@@ -13458,6 +14155,15 @@
"node": ">=12"
}
},
+ "node_modules/interpret": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/invariant": {
"version": "2.2.4",
"license": "MIT",
@@ -14750,6 +15456,15 @@
"version": "3.0.1",
"license": "MIT"
},
+ "node_modules/json-crawl": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/json-crawl/-/json-crawl-0.5.3.tgz",
+ "integrity": "sha512-BEjjCw8c7SxzNK4orhlWD5cXQh8vCk2LqDr4WgQq4CV+5dvopeYwt1Tskg67SuSLKvoFH5g0yuYtg7rcfKV6YA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/json-loader": {
"version": "0.5.7",
"license": "MIT"
@@ -15343,6 +16058,15 @@
"uc.micro": "^1.0.1"
}
},
+ "node_modules/liquid-json": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/liquid-json/-/liquid-json-0.3.1.tgz",
+ "integrity": "sha512-wUayTU8MS827Dam6MxgD72Ui+KOSF+u/eIqpatOtjnvgJ0+mnDq33uC2M7J0tPK+upe/DpUAuK4JUU89iBoNKQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/load-json-file": {
"version": "4.0.0",
"dev": true,
@@ -17738,6 +18462,15 @@
"node": ">= 0.6"
}
},
+ "node_modules/mime-format": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/mime-format/-/mime-format-2.0.2.tgz",
+ "integrity": "sha512-Y5ERWVcyh3sby9Fx2U5F1yatiTFjNsqF5NltihTWI9QgNtr5o3dbCZdcKa1l2wyfhnwwoP9HGNxga7LqZLA6gw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "charset": "^1.0.0"
+ }
+ },
"node_modules/mime-types": {
"version": "2.1.35",
"license": "MIT",
@@ -17970,6 +18703,26 @@
"multicast-dns": "cli.js"
}
},
+ "node_modules/mustache": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
+ "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
+ "license": "MIT",
+ "bin": {
+ "mustache": "bin/mustache"
+ }
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
@@ -18005,6 +18758,15 @@
"version": "2.6.2",
"license": "MIT"
},
+ "node_modules/neotraverse": {
+ "version": "0.6.15",
+ "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.15.tgz",
+ "integrity": "sha512-HZpdkco+JeXq0G+WWpMJ4NsX3pqb5O7eR9uGz3FfoFt+LYzU8iRWp49nJtud6hsDoywM8tIrDo3gjgmOqJA8LA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/net": {
"version": "1.0.2",
"license": "MIT"
@@ -18022,6 +18784,13 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/node-emoji": {
"version": "2.2.0",
"license": "MIT",
@@ -18464,6 +19233,35 @@
"url": "https://github.com/Mermade/oas-kit?sponsor=1"
}
},
+ "node_modules/oas-resolver-browser": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/oas-resolver-browser/-/oas-resolver-browser-2.5.6.tgz",
+ "integrity": "sha512-Jw5elT/kwUJrnGaVuRWe1D7hmnYWB8rfDDjBnpQ+RYY/dzAewGXeTexXzt4fGEo6PUE4eqKqPWF79MZxxvMppA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "node-fetch-h2": "^2.3.0",
+ "oas-kit-common": "^1.0.8",
+ "path-browserify": "^1.0.1",
+ "reftools": "^1.1.9",
+ "yaml": "^1.10.0",
+ "yargs": "^17.0.1"
+ },
+ "bin": {
+ "resolve": "resolve.js"
+ },
+ "funding": {
+ "url": "https://github.com/Mermade/oas-kit?sponsor=1"
+ }
+ },
+ "node_modules/oas-resolver-browser/node_modules/yaml": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
+ "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/oas-resolver/node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
@@ -18517,6 +19315,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/object-inspect": {
"version": "1.13.3",
"license": "MIT",
@@ -18644,6 +19451,64 @@
"json-pointer": "0.6.2"
}
},
+ "node_modules/openapi-to-postmanv2": {
+ "version": "5.8.0",
+ "resolved": "https://registry.npmjs.org/openapi-to-postmanv2/-/openapi-to-postmanv2-5.8.0.tgz",
+ "integrity": "sha512-7f02ypBlAx4G9z3bP/uDk8pBwRbYt97Eoso8XJLyclfyRvCC+CvERLUl0MD0x+GoumpkJYnQ0VGdib/kwtUdUw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "ajv": "^8.11.0",
+ "ajv-draft-04": "1.0.0",
+ "ajv-formats": "2.1.1",
+ "async": "3.2.6",
+ "commander": "2.20.3",
+ "graphlib": "2.1.8",
+ "js-yaml": "4.1.0",
+ "json-pointer": "0.6.2",
+ "json-schema-merge-allof": "0.8.1",
+ "lodash": "4.17.21",
+ "neotraverse": "0.6.15",
+ "oas-resolver-browser": "2.5.6",
+ "object-hash": "3.0.0",
+ "path-browserify": "1.0.1",
+ "postman-collection": "^5.0.0",
+ "swagger2openapi": "7.0.8",
+ "yaml": "1.10.2"
+ },
+ "bin": {
+ "openapi2postmanv2": "bin/openapi2postmanv2.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/openapi-to-postmanv2/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "license": "MIT"
+ },
+ "node_modules/openapi-to-postmanv2/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/openapi-to-postmanv2/node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/opener": {
"version": "1.5.2",
"license": "(WTFPL OR MIT)",
@@ -19034,7 +19899,6 @@
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -19143,7 +20007,6 @@
},
"node_modules/pirates": {
"version": "4.0.6",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
@@ -20756,19 +21619,109 @@
"postcss": "^8.4.31"
}
},
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "license": "MIT"
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "license": "MIT"
+ },
+ "node_modules/postcss-zindex": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz",
+ "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==",
+ "engines": {
+ "node": "^14 || ^16 || >=18.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.31"
+ }
+ },
+ "node_modules/postman-code-generators": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/postman-code-generators/-/postman-code-generators-2.1.1.tgz",
+ "integrity": "sha512-+egQK1Jf9a92QP23vRTKcDLOthIQmI7WI4czEsZq/wgguLMnVHJ26KlT8AVtpAdVw28hqUbHwicerYxRWCfjoA==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "async": "^3.2.2",
+ "detect-package-manager": "^3.0.2",
+ "lodash": "^4.17.21",
+ "postman-collection": "^5.0.0",
+ "shelljs": "^0.8.5"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/postman-collection": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/postman-collection/-/postman-collection-5.3.0.tgz",
+ "integrity": "sha512-PMa5vRheqDFfS1bkRg8WBidWxunRA80sT5YNLP27YC5+ycyfiLMCwPnqQd1zfvxkGk04Pr9UronWmmgsbpsVyQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@faker-js/faker": "5.5.3",
+ "file-type": "3.9.0",
+ "http-reasons": "0.1.0",
+ "iconv-lite": "0.6.3",
+ "liquid-json": "0.3.1",
+ "lodash": "4.17.23",
+ "mime": "3.0.0",
+ "mime-format": "2.0.2",
+ "postman-url-encoder": "3.0.8",
+ "semver": "7.7.1",
+ "uuid": "8.3.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/postman-collection/node_modules/lodash": {
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
+ "license": "MIT"
+ },
+ "node_modules/postman-collection/node_modules/mime": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/postman-collection/node_modules/semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/postman-collection/node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
},
- "node_modules/postcss-zindex": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz",
- "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==",
- "engines": {
- "node": "^14 || ^16 || >=18.0"
+ "node_modules/postman-url-encoder": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/postman-url-encoder/-/postman-url-encoder-3.0.8.tgz",
+ "integrity": "sha512-EOgUMBazo7JNP4TDrd64TsooCiWzzo4143Ws8E8WYGEpn2PKpq+S4XRTDhuRTYHm3VKOpUZs7ZYZq7zSDuesqA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "punycode": "^2.3.1"
},
- "peerDependencies": {
- "postcss": "^8.4.31"
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/prettier": {
@@ -21297,6 +22250,22 @@
"react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
+ "node_modules/react-hook-form": {
+ "version": "7.72.1",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.72.1.tgz",
+ "integrity": "sha512-RhwBoy2ygeVZje+C+bwJ8g0NjTdBmDlJvAUHTxRjTmSUKPYsKfMphkS2sgEMotsY03bP358yEYlnUeZy//D9Ig==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
+ }
+ },
"node_modules/react-is": {
"version": "18.3.1",
"license": "MIT"
@@ -21318,6 +22287,25 @@
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==",
"license": "MIT"
},
+ "node_modules/react-live": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/react-live/-/react-live-4.1.8.tgz",
+ "integrity": "sha512-B2SgNqwPuS2ekqj4lcxi5TibEcjWkdVyYykBEUBshPAPDQ527x2zPEZg560n8egNtAjUpwXFQm7pcXV65aAYmg==",
+ "license": "MIT",
+ "dependencies": {
+ "prism-react-renderer": "^2.4.0",
+ "sucrase": "^3.35.0",
+ "use-editable": "^2.3.3"
+ },
+ "engines": {
+ "node": ">= 0.12.0",
+ "npm": ">= 2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
"node_modules/react-loadable": {
"name": "@docusaurus/react-loadable",
"version": "6.0.0",
@@ -21343,6 +22331,55 @@
"webpack": ">=4.41.1 || 5.x"
}
},
+ "node_modules/react-magic-dropzone": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/react-magic-dropzone/-/react-magic-dropzone-1.0.1.tgz",
+ "integrity": "sha512-0BIROPARmXHpk4AS3eWBOsewxoM5ndk2psYP/JmbCq8tz3uR2LIV1XiroZ9PKrmDRMctpW+TvsBCtWasuS8vFA==",
+ "license": "MIT"
+ },
+ "node_modules/react-markdown": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz",
+ "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "hast-util-to-jsx-runtime": "^2.0.0",
+ "html-url-attributes": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.0.0",
+ "unified": "^11.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ },
+ "peerDependencies": {
+ "@types/react": ">=18",
+ "react": ">=18"
+ }
+ },
+ "node_modules/react-modal": {
+ "version": "3.16.3",
+ "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.3.tgz",
+ "integrity": "sha512-yCYRJB5YkeQDQlTt17WGAgFJ7jr2QYcWa1SHqZ3PluDmnKJ/7+tVU+E6uKyZ0nODaeEj+xCpK4LcSnKXLMC0Nw==",
+ "license": "MIT",
+ "dependencies": {
+ "exenv": "^1.2.0",
+ "prop-types": "^15.7.2",
+ "react-lifecycles-compat": "^3.0.0",
+ "warning": "^4.0.3"
+ },
+ "peerDependencies": {
+ "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19",
+ "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19"
+ }
+ },
"node_modules/react-overlays": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.2.1.tgz",
@@ -21363,6 +22400,29 @@
"react-dom": ">=16.3.0"
}
},
+ "node_modules/react-redux": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
+ "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.6",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.2.25 || ^19",
+ "react": "^18.0 || ^19",
+ "redux": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-router": {
"version": "5.3.4",
"license": "MIT",
@@ -21547,6 +22607,17 @@
"node": ">=8.10.0"
}
},
+ "node_modules/rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
+ "dependencies": {
+ "resolve": "^1.1.6"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/recma-build-jsx": {
"version": "1.0.0",
"license": "MIT",
@@ -21666,6 +22737,21 @@
"@docusaurus/utils": "^3.6.0"
}
},
+ "node_modules/redux": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
+ "license": "MIT"
+ },
+ "node_modules/redux-thunk": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
+ "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "redux": "^5.0.0"
+ }
+ },
"node_modules/reflect.getprototypeof": {
"version": "1.0.10",
"dev": true,
@@ -22099,7 +23185,9 @@
}
},
"node_modules/remark-gfm": {
- "version": "4.0.0",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
+ "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
"license": "MIT",
"dependencies": {
"@types/mdast": "^4.0.0",
@@ -22308,6 +23396,12 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
},
+ "node_modules/reselect": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
+ "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
+ "license": "MIT"
+ },
"node_modules/resolve": {
"version": "1.22.11",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
@@ -22614,6 +23708,94 @@
"version": "2.1.2",
"license": "MIT"
},
+ "node_modules/sass": {
+ "version": "1.99.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.99.0.tgz",
+ "integrity": "sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^4.0.0",
+ "immutable": "^5.1.5",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher": "^2.4.1"
+ }
+ },
+ "node_modules/sass-loader": {
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.7.tgz",
+ "integrity": "sha512-w6q+fRHourZ+e+xA1kcsF27iGM6jdB8teexYCfdUw0sYgcDNeZESnDNT9sUmmPm3ooziwUJXGwZJSTF3kOdBfA==",
+ "license": "MIT",
+ "dependencies": {
+ "neo-async": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0",
+ "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+ "sass": "^1.3.0",
+ "sass-embedded": "*",
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "node-sass": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/sass/node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/sass/node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/sax": {
"version": "1.4.1",
"license": "ISC"
@@ -23064,6 +24246,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/shelljs": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
+ "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ },
+ "bin": {
+ "shjs": "bin/shjs"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/should": {
"version": "13.2.3",
"resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz",
@@ -23871,6 +25070,37 @@
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz",
"integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="
},
+ "node_modules/sucrase": {
+ "version": "3.35.1",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
+ "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "tinyglobby": "^0.2.11",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"license": "MIT",
@@ -24313,6 +25543,27 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "license": "MIT",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/thingies": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz",
@@ -24375,6 +25626,51 @@
"node": ">=18"
}
},
+ "node_modules/tinyglobby": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+ "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/tinypool": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz",
@@ -24524,6 +25820,12 @@
"node": ">=6.10"
}
},
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "license": "Apache-2.0"
+ },
"node_modules/ts-node": {
"version": "10.9.1",
"dev": true,
@@ -25102,6 +26404,15 @@
"version": "1.4.1",
"license": "MIT"
},
+ "node_modules/use-editable": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/use-editable/-/use-editable-2.3.3.tgz",
+ "integrity": "sha512-7wVD2JbfAFJ3DK0vITvXBdpd9JAz5BcKAAolsnLBuBn6UDDwBGuCIAGvR3yA2BNKm578vAMVHFCWaOcA+BhhiA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">= 16.8.0"
+ }
+ },
"node_modules/use-sync-external-store": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
@@ -26060,6 +27371,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/xml-formatter": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/xml-formatter/-/xml-formatter-3.7.0.tgz",
+ "integrity": "sha512-+8qTc3zv2UcJ1v9IsSIce37Dl4MQG14Cp7tWrwmy202UaI1wqRukw5QMX1JHsV+DX64yw77EgGsj2s5wGvuMbQ==",
+ "license": "MIT",
+ "dependencies": {
+ "xml-parser-xo": "^4.1.5"
+ },
+ "engines": {
+ "node": ">= 16"
+ }
+ },
"node_modules/xml-js": {
"version": "1.6.11",
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
@@ -26071,6 +27394,15 @@
"xml-js": "bin/cli.js"
}
},
+ "node_modules/xml-parser-xo": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/xml-parser-xo/-/xml-parser-xo-4.1.5.tgz",
+ "integrity": "sha512-TxyRxk9sTOUg3glxSIY6f0nfuqRll2OEF8TspLgh5mZkLuBgheCn3zClcDSGJ58TvNmiwyCCuat4UajPud/5Og==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ }
+ },
"node_modules/xtend": {
"version": "4.0.2",
"license": "MIT",
diff --git a/package.json b/package.json
index df509965d..ce73bf04d 100644
--- a/package.json
+++ b/package.json
@@ -52,6 +52,8 @@
"classnames": "2.5.1",
"clsx": "2.1.0",
"debug": "4.3.4",
+ "docusaurus-plugin-openapi-docs": "4.7.1",
+ "docusaurus-theme-openapi-docs": "4.7.1",
"file-loader": "6.2.0",
"json-loader": "0.5.7",
"json-schema-faker": "0.5.8",
diff --git a/src/sidebar.ts b/src/sidebar.ts
index 73aec49ab..b62b6b2d4 100644
--- a/src/sidebar.ts
+++ b/src/sidebar.ts
@@ -5,9 +5,32 @@ import {
SidebarItem,
SidebarItemConfig,
} from "@docusaurus/plugin-content-docs/src/sidebars/types"
+import apiSidebar from "../docs/talos/reference/api/sidebar"
type SidebarItemsConfig = SidebarItemConfig[]
+function prefixSidebarIds(
+ items: SidebarItemsConfig,
+ prefix: string,
+): SidebarItemsConfig {
+ return items.map((item) => {
+ if (typeof item === "string") return `${prefix}${item}`
+ if (item.type === "doc") return { ...item, id: `${prefix}${item.id}` }
+ if (item.type === "category") {
+ const link =
+ item.link?.type === "doc"
+ ? { ...item.link, id: `${prefix}${item.link.id}` }
+ : item.link
+ return {
+ ...item,
+ link,
+ items: prefixSidebarIds(item.items as SidebarItemsConfig, prefix),
+ }
+ }
+ return item
+ })
+}
+
const homeLink: SidebarItem = {
type: "link",
href: "/welcome",
@@ -917,6 +940,129 @@ const keto: SidebarItemsConfig = [
},
]
+const talos: SidebarItemsConfig = [
+ {
+ type: "doc",
+ id: "talos/index",
+ label: "Home",
+ },
+ {
+ type: "category",
+ label: "Quickstart",
+ collapsed: false,
+ link: { type: "doc", id: "talos/quickstart/index" },
+ items: ["talos/quickstart/docker-commercial"],
+ },
+ {
+ type: "category",
+ label: "Integrate",
+ collapsed: false,
+ link: { type: "doc", id: "talos/integrate/index" },
+ items: [
+ "talos/integrate/issue-and-verify",
+ "talos/integrate/import-keys",
+ "talos/integrate/derive-tokens",
+ "talos/integrate/batch-operations",
+ "talos/integrate/key-lifecycle",
+ "talos/integrate/self-revocation",
+ "talos/integrate/ip-restrictions",
+ "talos/integrate/rate-limiting",
+ "talos/integrate/error-handling",
+ {
+ type: "category",
+ label: "SDK",
+ items: ["talos/integrate/sdk/go", "talos/integrate/sdk/curl"],
+ },
+ ],
+ },
+ {
+ type: "category",
+ label: "Operate",
+ collapsed: false,
+ link: { type: "doc", id: "talos/operate/index" },
+ items: [
+ "talos/operate/install",
+ "talos/operate/configure",
+ {
+ type: "category",
+ label: "Database",
+ link: { type: "doc", id: "talos/operate/database/index" },
+ items: [
+ "talos/operate/database/sqlite",
+ "talos/operate/database/postgresql",
+ "talos/operate/database/mysql",
+ "talos/operate/database/cockroachdb",
+ "talos/operate/database/migrations",
+ ],
+ },
+ {
+ type: "category",
+ label: "Deploy",
+ link: { type: "doc", id: "talos/operate/deploy/index" },
+ items: [
+ "talos/operate/deploy/docker",
+ "talos/operate/deploy/kubernetes",
+ "talos/operate/deploy/separate-planes",
+ "talos/operate/deploy/edge-proxy",
+ ],
+ },
+ "talos/operate/secrets",
+ "talos/operate/tls",
+ {
+ type: "category",
+ label: "Monitoring",
+ link: { type: "doc", id: "talos/operate/monitoring/index" },
+ items: [
+ "talos/operate/monitoring/metrics",
+ "talos/operate/monitoring/tracing",
+ "talos/operate/monitoring/health-checks",
+ ],
+ },
+ {
+ type: "category",
+ label: "Cache",
+ link: { type: "doc", id: "talos/operate/cache/index" },
+ items: ["talos/operate/cache/memory", "talos/operate/cache/redis"],
+ },
+ "talos/operate/multi-tenancy",
+ "talos/operate/troubleshooting",
+ "talos/operate/security-hardening",
+ ],
+ },
+ {
+ type: "category",
+ label: "Concepts",
+ collapsed: true,
+ link: { type: "doc", id: "talos/concepts/index" },
+ items: [
+ "talos/concepts/architecture",
+ "talos/concepts/credential-types",
+ "talos/concepts/token-format",
+ "talos/concepts/security-model",
+ "talos/concepts/caching",
+ "talos/concepts/rate-limiting",
+ "talos/concepts/token-derivation-security",
+ ],
+ },
+ {
+ type: "category",
+ label: "Reference",
+ collapsed: true,
+ link: { type: "doc", id: "talos/reference/index" },
+ items: [
+ {
+ type: "category",
+ label: "API",
+ link: { type: "doc", id: "talos/reference/api/ory-talos-api" },
+ items: prefixSidebarIds(apiSidebar, "talos/"),
+ },
+ "talos/reference/config",
+ "talos/reference/error-codes",
+ "talos/reference/token-format",
+ ],
+ },
+]
+
const polis: SidebarItemsConfig = [
homeLink,
"polis/index",
@@ -1346,6 +1492,7 @@ module.exports = {
polis,
oathkeeper,
api,
+ talos,
polisApi,
sdk,
cli,