
# 接続のパスキー rpId を変更する

`POST /v1/connections/{connection_id}:change-rp-id` · 権限 `connections:write`

パスキーの接続を新しい rpId に移し、移行期間を開始します。パスキーは登録時の rpId に紐づくため、ユーザーがパスキーを持っている場合、rpId を変更できるのはこの方法だけです。`settings.rp_id` を変更する `PATCH` は `409 rp_id_change_requires_migration` で拒否されます。

移行期間中、ユーザーは以前の rpId のパスキーで引き続きサインインでき、新しいパスキーは新しい rpId で登録されます。移行期間が終了したとき、または [rpId の移行を完了する](complete-rp-id-migration.md) で早期に終了したとき、以前の rpId に残っているパスキーは取り消されます（理由 `rp_id_changed`）。他のサインイン方法を持たないユーザーは、パスワードレスのメールサインインまたはアカウント復旧が必要になります。1 つの環境で同時に実行できる移行は 1 件だけです。

接続の rpId、移行レコード、管理操作の監査ログ、`passkey_rp_id.migration_started` イベントは一括で書き込まれます。rpId、または実行中の移行の以前の rpId に該当するカスタムドメインは削除できません（`409 domain_in_use_by_rp_id`）。

## リクエスト

| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
| `connection_id` | path | はい | パスキー接続の ID（`conn_…`）。 |
| `If-Match` | header | はい | 接続の `ETag`（[接続を取得する](get.md) を参照）。 |
| `Idempotency-Key` | header | いいえ | 再試行されたリクエストを安全にするための任意のキー（16〜64 文字）。 |
| `new_rp_id` | string | はい | 新しい rpId。環境内の `active` 状態のカスタムドメインのホスト名（小文字、IDNA A ラベル）、または各サインインホストをそれぞれ独立した rpId として使う場合は空文字列。最大 253 バイト。 |
| `confirm_rp_id` | string | はい | 確認用に `new_rp_id` をもう一度入力した値。 |
| `migration_window_days` | integer | いいえ | 以前の rpId のパスキーを引き続き使用できる日数。30〜365、デフォルトは 90。 |

```json
{
  "new_rp_id": "login.example.com",
  "confirm_rp_id": "login.example.com",
  "migration_window_days": 90
}
```

## レスポンス

`200 OK`。移行の内容と、接続の新しいバージョンを示す `ETag` ヘッダーが返されます。

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

| フィールド | 説明 |
|---|---|
| `previous_rp_id`, `new_rp_id` | 変更前と変更後の rpId。`null` は各サインインホストがそれぞれ独立した rpId であることを意味します。 |
| `status` | 期間の実行中は `active`、期間が終了すると `completed`、期間の途中で早期終了した場合は `completed_early`。 |
| `ends_at` | 移行期間が終了する予定の日時。 |
| `completed_at`, `revoked_count`, `new_registration_count` | 移行が終了したときに書き込まれます。`active` の間は `null`。 |
| `fallback_enabled_by_migration` | パスキーが唯一の第一要素だったため、移行期間中にフォールバックのサインイン方法が有効化された場合は `true`。 |

## エラー

| HTTP | code | 発生条件 |
|---|---|---|
| 400 | `unknown_field` | ボディに未知のフィールドが含まれています。 |
| 404 | `not_found` | 接続が存在しないか、別の環境に属しています。 |
| 409 | `rp_id_migration_in_progress` | この環境で別の rpId 移行が実行中です。 |
| 412 | `precondition_failed` | `If-Match` が現在のバージョンと一致しません。 |
| 422 | `validation_failed` | フィールドが欠落しているか、長すぎる、または範囲外です。`new_rp_id` が環境内の `active` 状態のカスタムドメインではないか、現在の rpId と同じです。`confirm_rp_id` が一致しません。または接続がパスキー接続ではありません（`errors[].pointer`: `/new_rp_id`, `/confirm_rp_id`, `/migration_window_days`, `/connection_id`）。 |
| 428 | `precondition_required` | `If-Match` ヘッダーがありません。 |
| 401 | `unauthenticated` | 認証情報がないか、無効または取り消し済みです。 |
| 403 | `insufficient_permissions` | 認証情報に必要な権限がありません。 |
| 429 | `rate_limited` | レート制限を超えました。`Retry-After` の期間を待ってから再試行してください。 |
| 503 | `service_unavailable` | 依存先のサービスが一時的に利用できません。`Retry-After` の期間を待ってから再試行してください。 |

## 例

```bash
curl -X POST "https://api.eu.keenauth.com/v1/connections/conn_01j9xp6q0r1s5t7v9w1x3y5z7b:change-rp-id" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H 'If-Match: "3"' \
  -H "Content-Type: application/json" \
  -d '{"new_rp_id":"login.example.com","confirm_rp_id":"login.example.com"}'
```

```bash
keenauth connections change-rp-id conn_01j9xp6q0r1s5t7v9w1x3y5z7b --if-match '"3"' --yes \
  --data '{"new_rp_id":"login.example.com","confirm_rp_id":"login.example.com"}'
```
