
# List the revisions of a connection

`GET /v1/connections/{connection_id}/revisions` · permission `connections:read`

Lists the revisions of an enterprise (SAML or OIDC) connection, newest first: the pending draft (at most one) and the revisions published or discarded in the last 90 days.

On an **active** connection, a security-critical change is not applied directly. It becomes a **draft revision** and the live configuration stays as it is until you test and publish the draft:

- importing SAML metadata that changes the identity provider's entity ID or SSO URL, or removes a signing pin ([Import metadata](import-metadata.md));
- changing the OIDC `issuer` or `client_id` ([Put the OIDC configuration](../connection-oidc/put.md));
- every SP host migration, whatever the connection's status ([Migrate the SP host](migrate-sp-host.md)).

Test a draft with [Test a connection](test.md) and its `revision_id`, then [publish it](publish-revision.md). A new draft discards the previous one (`discard_reason: superseded`).

A revision shows only the new non-secret values (`changes`). A new OIDC client secret appears only as `client_secret_change` (`keep`, `replace` or `clear`); the secret and its last characters are never returned. Who made or decided a revision is recorded in the management audit log (`connection.revision_created`, `connection.revision_published`), not here.

## Request

| Field | Type | Required | Description |
|---|---|---|---|
| `connection_id` | path | yes | Enterprise connection ID (`conn_…`). |
| `limit` | query | no | Page size, 1–100 (default 20). |
| `after` | query | no | Cursor from `list_metadata.after`. A cursor works only for the connection that produced it. |

The list is paged forward only: `before` and `order` are not supported (`422`).

## Response

`200 OK`:

```json
{
  "data": [
    {
      "id": "connrev_01j9xr8c2d4e6f8g0h2j4k6m8n",
      "connection_id": "conn_01j9xp6q0r1s5t7v9w1x3y5z7b",
      "protocol": "saml",
      "kind": "sp_host",
      "status": "draft",
      "discard_reason": null,
      "created_at": "2026-10-28T10:00:00Z",
      "decided_at": null,
      "purge_after": null,
      "superseded_revision_id": null,
      "changes": {
        "sp_host": "login.example.com",
        "idp_entity_id": null,
        "idp_sso_url": null,
        "idp_slo_url": null,
        "certificate_fingerprints": [],
        "mfa_authn_context_values": null,
        "issuer": null,
        "client_id": null,
        "client_auth_method": null,
        "provider_profile": null,
        "client_secret_change": null
      },
      "latest_test": {
        "test_id": "conntest_01j9xr4a6b8c0d2e4f6g8h0j2k",
        "status": "passed",
        "failure_reason": null,
        "started_at": "2026-10-28T10:05:00Z",
        "completed_at": "2026-10-28T10:06:00Z"
      }
    }
  ],
  "list_metadata": { "before": null, "after": null }
}
```

| Field | Description |
|---|---|
| `kind` | `configuration` (identity provider or OIDC client change) or `sp_host` (SP host migration). |
| `status` | `draft` (waiting for test and publication), `published` or `discarded`. |
| `decided_at` / `purge_after` | When the revision was published or discarded, and when it is deleted (90 days later); `null` for a draft. |
| `changes` | The new values. Fields that the revision does not change are `null`. |
| `latest_test` | The latest test sign-in of this revision from the last 24 hours, or `null`. Publication needs a `passed` one. |

## Errors

| HTTP | code | When |
|---|---|---|
| 400 | `invalid_cursor` | The cursor is malformed or belongs to another connection or query. |
| 401 | `unauthenticated` | The credential is missing, invalid or revoked. |
| 403 | `insufficient_permissions` | The credential lacks `connections:read`. |
| 404 | `not_found` | The connection does not exist in this environment or is not an enterprise connection. |
| 422 | `validation_failed` | A query parameter is invalid (for example `limit` above 100, or `before`). |
| 429 | `rate_limited` | The rate limit was exceeded; retry after the `Retry-After` period. |
| 503 | `service_unavailable` | A dependency is temporarily unavailable; retry after the `Retry-After` period. |

## Example

```bash
curl "https://api.eu.keenauth.com/v1/connections/conn_01j9xp6q0r1s5t7v9w1x3y5z7b/revisions?limit=20" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

```bash
keenauth connections revisions list conn_01j9xp6q0r1s5t7v9w1x3y5z7b --limit 20
```
