
# Migrer l'hôte SP d'une connexion

`POST /v1/connections/{connection_id}:migrate-sp-host` · autorisation `connections:write`

Lance le déplacement des points de terminaison SP (ACS, métadonnées, déconnexion unique, rappel OIDC) d'une connexion d'entreprise vers un nouvel hôte, par exemple de l'hôte `keenauth.app` vers votre domaine personnalisé vérifié. Les URL SP sont par ailleurs figées, car le fournisseur d'identité les possède.

La requête crée une **révision en brouillon** de type `sp_host`, quel que soit le statut de la connexion. Rien ne change encore pour les connexions :

1. Téléchargez les nouvelles métadonnées SP avec [Télécharger les métadonnées SP](sp-metadata.md) et `revision_id`, puis transmettez-les à l'administrateur du fournisseur d'identité. Le nouvel hôte ne sert que ces métadonnées et la connexion de test du brouillon, rien d'autre.
2. Testez le brouillon avec [Tester une connexion](test.md) et `revision_id`.
3. [Publiez la révision](publish-revision.md). La connexion utilise désormais le nouvel hôte. L'ancien hôte continue de répondre pendant 30 jours supplémentaires afin que le fournisseur d'identité puisse être mis à jour, puis il renvoie `404`.

Un nouveau brouillon supprime le brouillon précédent de la connexion. La requête est auditée sous `connection.revision_created`.

## Requête

| Champ | Type | Requis | Description |
|---|---|---|---|
| `connection_id` | chemin | oui | ID de la connexion d'entreprise (`conn_…`). |
| `Idempotency-Key` | en-tête | non | Clé facultative qui rend sûre la nouvelle tentative d'une requête (16 à 64 caractères). |
| `sp_host` | chaîne | oui | Le nouvel hôte : un hôte actif de cet environnement (son hôte `keenauth.app` ou un domaine personnalisé vérifié), en minuscules, sans port. |

## Réponse

`200 OK` avec la révision en brouillon :

```json
{
  "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": null
}
```

`superseded_revision_id` est le brouillon précédent que cette requête a supprimé, le cas échéant.

## Erreurs

| HTTP | code | Quand |
|---|---|---|
| 400 | `unknown_field` | Le corps contient un champ inconnu. |
| 401 | `unauthenticated` | L'identifiant est absent, invalide ou révoqué. |
| 403 | `insufficient_permissions` | L'identifiant ne dispose pas de l'autorisation `connections:write`. |
| 404 | `not_found` | La connexion n'existe pas dans cet environnement ou n'est pas une connexion d'entreprise. |
| 409 | `conflict` | La fenêtre de 30 jours de la migration précédente de l'hôte SP est encore ouverte, ou la connexion n'a pas encore de configuration de protocole. |
| 422 | `validation_failed` | `errors[]` indique `/sp_host` avec `required`, `invalid_value` (pas un nom d'hôte en minuscules), `not_in_environment` (pas un hôte actif de cet environnement) ou `unchanged` (déjà l'hôte SP de la connexion). |
| 429 | `rate_limited` | La limite de débit a été dépassée ; réessayez après la durée indiquée par `Retry-After`. |
| 503 | `service_unavailable` | Une dépendance est temporairement indisponible ; réessayez après la durée indiquée par `Retry-After`. |

## Exemple

```bash
curl -X POST "https://api.eu.keenauth.com/v1/connections/conn_01j9xp6q0r1s5t7v9w1x3y5z7b:migrate-sp-host" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"sp_host":"login.example.com"}'
```

```bash
keenauth connections migrate-sp-host conn_01j9xp6q0r1s5t7v9w1x3y5z7b --sp-host login.example.com --yes
```
