---
title: "List"
method: GET
path: "/api-keys"
tags: ["api-keys"]
---

# List

`GET /api-keys`

## Request

- Base URL: `https://api.instruxi.dev/api/v1/enforcer`
- URL: `https://api.instruxi.dev/api/v1/enforcer/api-keys`
- Auth: one of:
  - API key in header `Authorization`
  - API key in header `X-API-Key`

Machine credentials visible to the caller: their own keys, or — for a tenant admin — every key issued in their tenant. The plaintext secret is never returned here or anywhere after creation; only id, name, key_prefix, active and last_used_at are exposed. Filters only narrow that scope; total counts the rows matching every filter. q searches name and key_prefix only. expires_before uses the `to` grammar: YYYY-MM-DD includes that whole UTC day, RFC3339 is an exact (exclusive) instant; keys that never expire never match. A malformed active or expires_before is a 400; an unknown sort falls back to created.

## Query parameters

- `q` string
- `active` boolean
- `expires_before` string
- `sort` 'created' | 'name' | 'last_used' | 'expires'
- `sort_dir` 'asc' | 'desc'
- `limit` integer
- `offset` integer
- `tenant_id` string, uuid
- `all_tenants` boolean

## Response `200`

OK

- InternalDeliveryHttpHandlerApiKeyPageResponse
  - `data` EnforcerV3InternalDomainApikeyAPIKey[]
    - `account_id` string
    - `active` boolean
    - `created_at` string
    - `created_by` string: CreatedBy is the account that minted the key: provenance, never authority. Equal to AccountID for a self-minted key; nil for keys minted before 000111.
    - `expires_at` string: ExpiresAt is when the key stops authenticating (000111). nil — every key minted before the column existed — never expires. Both transports refuse an expired key through Expired, so the rule cannot differ between them.
    - `id` string
    - `key_prefix` string
    - `last_used_at` string
    - `name` string
    - `scope` string: Scope narrows what the key may do below its owner's grant. nil is the only value existing keys carry and means unnarrowed — the key acts with the account's full permissions, exactly as before the column existed. Omitted from JSON when nil, so a response for an unscoped key is byte-identical to what it was.
    - `tenant_id` string
    - `updated_at` string
  - `limit` integer
  - `offset` integer
  - `success` boolean
  - `total` integer

## Other responses

- `400`: Bad Request
- `401`: Unauthorized
- `403`: forbidden: tenant_id/all_tenants beyond your own tenant without the cross_tenant grant

---

[API](https://skmtc.dev/instruxi/apis/enforcer-api.md) · [All operations](https://skmtc.dev/instruxi/apis/enforcer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/instruxi/apis/enforcer-api/revisions/fa82bc1becc0?raw)
