
# List signing keys

`GET /v1/signing-keys` · permission `signing-keys:read`

Returns the token signing keys currently published in the environment's JWKS: `next` (published, not signing yet), `active` (signs new tokens) and `retired` (stopped signing, stays published for 7 days so tokens it signed still verify). The order is `next`, `active`, then `retired` (newest first). Keys that left the JWKS and keys revoked by an emergency rotation are not returned. The response holds public information only: `kid` is the RFC 7638 JWK SHA-256 thumbprint (base64url) and no response ever contains private key material, which never leaves the signing service.

## Request

This operation takes no path, query or body fields. The environment comes from the credential.

## Response

`200 OK` with `data` (keys) and `list_metadata`. The list is as small as the JWKS and is not paginated, so both cursors are always `null`. `activated_at` is `null` for the `next` key; `retired_at` and `removal_at` (when the key leaves the JWKS) are set only for `retired` keys.

```json
{
  "data": [
    {
      "kid": "ypeBEsobvcr6wjGzmiPcTaeG7_gUfE5yuYB3ha_uSLs",
      "use": "token_signing",
      "algorithm": "RS256",
      "state": "next",
      "storage": "wrapped",
      "created_at": "2026-09-05T09:30:00.123456Z",
      "activated_at": null,
      "retired_at": null,
      "removal_at": null
    },
    {
      "kid": "PiPoFgA5WUoziU9lZOGxNIu9egCI1CxKy3PurtWcAJ0",
      "use": "token_signing",
      "algorithm": "RS256",
      "state": "active",
      "storage": "wrapped",
      "created_at": "2026-03-09T09:30:00.123456Z",
      "activated_at": "2026-09-05T09:30:00.123456Z",
      "retired_at": null,
      "removal_at": null
    },
    {
      "kid": "Ln0sA6lQeuJl7PW1NWiFpTOTogKdJBOUmXJloaJa78Y",
      "use": "token_signing",
      "algorithm": "RS256",
      "state": "retired",
      "storage": "wrapped",
      "created_at": "2025-09-10T09:30:00.123456Z",
      "activated_at": "2026-03-09T09:30:00.123456Z",
      "retired_at": "2026-09-05T09:30:00.123456Z",
      "removal_at": "2026-09-12T09:30:00.123456Z"
    }
  ],
  "list_metadata": {
    "before": null,
    "after": null
  }
}
```

## Errors

| HTTP | code | When |
|---|---|---|
| 401 | `unauthenticated` | The credential is missing, invalid or revoked. |
| 403 | `insufficient_permissions` | The credential lacks the required permission. |
| 429 | `rate_limited` | The rate limit was exceeded; retry after the `Retry-After` period. |
| 501 | `not_implemented` | The operation is not available in this deployment yet; retrying does not change the result. |
| 503 | `service_unavailable` | A dependency is temporarily unavailable; retry after the `Retry-After` period. |

## Example

```bash
curl https://api.eu.keenauth.com/v1/signing-keys \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```
