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

# List Roles

> Discover the permission roles you can attach to an API key

## List Roles

```text theme={"dark"}
GET /v1/roles
```

Returns your tenant's permission roles. This is the endpoint that makes
[`role_ids`](/api-reference/api-keys/create) usable from code: a Terraform module
or a provisioning script cannot hard-code a per-tenant UUID, and before this
existed the only way to find one was to open the admin UI and copy it out of the
URL bar.

**Read-only, permanently.** Creating, editing and deleting roles stays on the
MFA-gated admin surface (Settings → Permissions). There is no `POST`, `PATCH` or
`DELETE` on `/v1/roles`.

Requires the `role:list` permission, which all four seeded machine roles carry.

### Query Parameters

| Parameter      | Type    | Description                                                                                                                                                       |
| -------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `subject_kind` | string  | `api_key` or `user`. Returns only roles whose `applies_to` includes it. Use `api_key` to list roles you can actually attach to a key. Any other value is a `400`. |
| `page`         | integer | Page number (default `1`)                                                                                                                                         |
| `per_page`     | integer | Results per page (default `20`, max `100`)                                                                                                                        |

### Response

```json theme={"dark"}
{
  "data": [
    {
      "id": "b3f1c2d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "name": "Key — Infrastructure",
      "description": "For Terraform and other infrastructure-as-code runners.",
      "applies_to": ["api_key"],
      "is_default": false,
      "seeded": true
    },
    {
      "id": "c4e2d3f5-6a7b-4c8d-9e0f-1a2b3c4d5e6f",
      "name": "Key — Read-only",
      "description": "List/read config and analytics/log metadata.",
      "applies_to": ["api_key"],
      "is_default": true,
      "seeded": true
    }
  ],
  "meta": {
    "total": 2,
    "page": 1,
    "per_page": 20,
    "total_pages": 1,
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
  }
}
```

| Field        | Description                                                                                                               |
| ------------ | ------------------------------------------------------------------------------------------------------------------------- |
| `applies_to` | Subject kinds the role may be assigned to. Passing a role whose `applies_to` is `["user"]` in `role_ids` returns a `400`. |
| `is_default` | Whether the admin UI prefills this role when creating a key.                                                              |
| `seeded`     | `true` for roles KnoxCall creates and maintains. Seeded roles cannot be deleted.                                          |

<Note>
  The **rules** a role grants are deliberately not returned. Enumerating them
  would hand every machine credential in the tenant a map of your authorization
  surface. To see what a role grants, open it in the admin UI.
</Note>

### The seeded machine roles

| Role                   | For                                                                                                                                                                                                                                                      |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Key — Invoke`         | Keys that **call** your APIs. Reads the route/client/environment config needed to resolve a target. No writes.                                                                                                                                           |
| `Key — Read-only`      | List/read config and analytics metadata. The default for a fresh key.                                                                                                                                                                                    |
| `Key — Editor`         | CRUD on routes, clients, environments, webhooks and secrets. No key management, no billing, no permissions.                                                                                                                                              |
| `Key — Infrastructure` | **Terraform and other infrastructure-as-code runners.** The whole provisioning surface: routes, environments, secrets, clients, API keys, webhooks, workflows, vaults, PKI, dynamic DB credentials, transit keys, AI gateways, OAuth clients and agents. |

`Key — Infrastructure` deliberately **excludes**, and explicitly denies:

* `secret:reveal` — a provisioning credential never needs the plaintext of a
  secret it created. KnoxCall holds the plaintext; that is the product.
* `secret:custody_enable` / `custody_disable` / `custody_rotate` — custody
  transitions decrypt the current administrative credential server-side.
* `workload_binding:create` / `delete` — a binding is a permanent route to a live
  credential for anyone presenting a matching JWT.
* `ephemeral_proxy:invoke` — one-shot runtime invocation against live
  credentials. It is not infrastructure state, and no Terraform resource models
  it.

None of those four can be reached by a wildcard rule either: they require an
exact `(resource_type, action)` allow, so a legacy `*:*` key does not silently
hold them.

### Examples

<CodeGroup>
  ```bash cURL theme={"dark"}
  # $TOKEN is a minted OAuth access token — see /api-reference/authentication
  curl "https://api.knoxcall.com/v1/roles?subject_kind=api_key" \
    -H "Authorization: Bearer $TOKEN"
  ```

  ```python Python theme={"dark"}
  from knoxcall import KnoxCall

  kc = KnoxCall(tenant="acme")
  roles = kc.roles.list(subject_kind="api_key")["data"]
  infra = next(r for r in roles if r["name"] == "Key — Infrastructure")

  key = kc.api_keys.create(name="terraform-prod", role_ids=[infra["id"]])
  print(key["api_key"])  # shown once
  ```

  ```javascript Node.js theme={"dark"}
  import { KnoxCall } from "@knoxcall/sdk";

  const kc = new KnoxCall({ tenant: "acme" });
  const { data: roles } = await kc.roles.list({ subject_kind: "api_key" });
  const infra = roles.find((r) => r.name === "Key — Infrastructure")!;

  const key = await kc.apiKeys.create({ name: "terraform-prod", role_ids: [infra.id] });
  console.log(key.api_key); // shown once
  ```
</CodeGroup>

### Errors

| Status | Type               | Description                                     |
| ------ | ------------------ | ----------------------------------------------- |
| 400    | `validation_error` | `subject_kind` was neither `api_key` nor `user` |
| 403    | `forbidden`        | The calling key does not hold `role:list`       |
