
# Complete the rpId migration of a connection

`POST /v1/connections/{connection_id}:complete-rp-id-migration` · permission `connections:write`

Ends the running rpId migration of a passkey connection before its window ends. The status becomes `completed_early` (or `completed` if the window had already ended), the passkeys still on the previous rpId are revoked (reason `rp_id_changed`), the previous rpId's origin stops being accepted and the `passkey_rp_id.migration_completed` event is published. This cannot be undone: users who have not registered a passkey on the new rpId must sign in another way.

## Request

| Field | Type | Required | Description |
|---|---|---|---|
| `connection_id` | path | yes | Passkey connection ID (`conn_…`). |
| `Idempotency-Key` | header | no | Optional key that makes a retried request safe (16-64 characters). |

The body is optional; if present it must be `{}`.

## Response

`200 OK`; the closed migration (see [Get the rpId migration](rp-id-migration.md)).

```json
{
  "id": "rpm_01j9xr4a6b8c0d2e4f6g8h0j2k",
  "connection_id": "conn_01j9xp6q0r1s5t7v9w1x3y5z7b",
  "previous_rp_id": null,
  "new_rp_id": "login.example.com",
  "status": "completed_early",
  "started_at": "2026-10-27T10:00:00Z",
  "ends_at": "2027-01-25T10:00:00Z",
  "completed_at": "2026-12-01T09:00:00Z",
  "revoked_count": 12,
  "new_registration_count": 340,
  "fallback_enabled_by_migration": false
}
```

## Errors

| HTTP | code | When |
|---|---|---|
| 400 | `unknown_field` | The body contains a field. |
| 404 | `not_found` | The connection does not exist or belongs to another environment. |
| 409 | `no_active_rp_id_migration` | The connection has no running rpId migration (for example, it was already completed). |
| 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` | The passkey counts could not be read, or another dependency is unavailable; the migration stays open. Retry after the `Retry-After` period. |

## Example

```bash
curl -X POST "https://api.eu.keenauth.com/v1/connections/conn_01j9xp6q0r1s5t7v9w1x3y5z7b:complete-rp-id-migration" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

```bash
keenauth connections complete-rp-id-migration conn_01j9xp6q0r1s5t7v9w1x3y5z7b --yes
```
