
# Test a connection

`POST /v1/connections/{connection_id}:test` · permission `connections:write`

Starts a test sign-in with the current configuration of an enterprise connection and returns a test URL. The person setting up the connection opens the URL in a browser and signs in at the identity provider. The browser then returns to `return_url` with the `test_id` query parameter. Read the outcome with [Get the latest test result](latest-test-result.md).

A test sign-in creates no session, provisions no user and links no account. A passed test is required to activate the connection; changing the identity provider configuration invalidates it.

To test a [draft revision](revisions.md) instead of the live configuration, send its `revision_id`. The draft is laid over the live configuration for this test only (for an SP host migration the test URL is on the new host). A passed test of a revision is the evidence [Publish a revision](publish-revision.md) needs; it does not count as activation evidence for the live configuration.

The `test_url` is a bearer link: anyone who has it can run the test within 10 minutes, once. It is returned only in this response (`Cache-Control: no-store`) and is never logged or audited. If you repeat the request with the same `Idempotency-Key`, the replayed response has no `test_url` and carries `secret_redacted: true`; start a new test instead. Starts are audited as `connection.test_started` with the test ID only.

## Request

| Field | Type | Required | Description |
|---|---|---|---|
| `connection_id` | path | yes | Enterprise connection ID (`conn_…`). |
| `return_url` | string | yes | Absolute `https` URL the browser returns to after the test, at most 2048 bytes. `test_id` is added as a query parameter. |
| `revision_id` | string | no | A draft revision of the connection (`connrev_…`) to test instead of the live configuration. |

## Response

`200 OK`:

```json
{
  "test_id": "conntest_01j9xr4a6b8c0d2e4f6g8h0j2k",
  "test_url": "https://acme.eu1.keenauth.app/sso/conn_01j9xp6q0r1s5t7v9w1x3y5z7b/start?t=…",
  "expires_at": "2026-10-20T10:10:00Z"
}
```

| Field | Description |
|---|---|
| `test_id` | Test ID (`conntest_…`). |
| `test_url` | The URL to open in a browser; valid for 10 minutes and one use. Do not share or log it. Missing in a replayed response. |
| `expires_at` | When the test URL expires. |
| `secret_redacted` | `true` in a response replayed for the same `Idempotency-Key`. |

## Errors

| HTTP | code | When |
|---|---|---|
| 404 | `not_found` | The connection does not exist in this environment or is not an enterprise connection. |
| 409 | `conflict` | The connection cannot be tested yet (no protocol configuration). |
| 422 | `validation_failed` | `return_url` is missing or not an absolute `https` URL (`errors[]` points at `/return_url`), or `revision_id` is malformed (`invalid_value`) or not a draft revision of this connection (`not_found`; pointer `/revision_id`). |
| 400 | `unknown_field` | The body has an unknown field. |
| 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. |
| 503 | `service_unavailable` | A dependency is temporarily unavailable; retry after the `Retry-After` period. |

## Example

```bash
curl -X POST "https://api.eu.keenauth.com/v1/connections/conn_01j9xp6q0r1s5t7v9w1x3y5z7b:test" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"return_url":"https://admin.example.com/sso/test-done"}'
```

```bash
keenauth connections test conn_01j9xp6q0r1s5t7v9w1x3y5z7b --return-url https://admin.example.com/sso/test-done
```
