
# Publier une révision de connexion

`POST /v1/connections/{connection_id}/revisions/{revision_id}:publish` · autorisation `connections:write`

Fait de la révision en brouillon la configuration active d'une connexion d'entreprise. En une seule étape, les éléments de la révision remplacent ceux de la configuration active :

- SAML : l'identifiant d'entité du fournisseur d'identité, les URL SSO et SLO, et les certificats de signature de la révision ;
- OIDC : les champs du client et, si la révision en contient un, le nouveau secret client ;
- migration de l'hôte SP : l'hôte SP et les URL SP. L'hôte précédent continue de répondre pendant 30 jours supplémentaires, puis renvoie `404`.

La révision doit avoir fait l'objet d'un **test de connexion réussi pour cette révision** au cours des dernières 24 heures : lancez-en un avec [Tester une connexion](test.md) et `revision_id`, puis terminez-le dans le navigateur. Le test de la configuration active ne compte pas.

Publier une révision déjà publiée n'écrit rien et renvoie `200` avec `already_published: true` ; parmi deux publications simultanées, une seule écrit. La publication est journalisée sous `connection.revision_published`.

La requête n'a pas de corps (n'en envoyez aucun ou envoyez `{}`), ni d'`If-Match` : une révision n'a pas de version. Si la configuration active a changé après la création du brouillon, la publication est refusée et vous devez créer un nouveau brouillon.

## Requête

| Champ | Type | Obligatoire | Description |
|---|---|---|---|
| `connection_id` | path | oui | Identifiant de la connexion d'entreprise (`conn_…`). |
| `revision_id` | path | oui | Identifiant de la révision (`connrev_…`) issu de [Lister les révisions](revisions.md). |
| `Idempotency-Key` | header | non | Clé facultative qui rend sûre la nouvelle tentative d'une requête (16 à 64 caractères). |

## Réponse

`200 OK` :

```json
{
  "revision": {
    "id": "connrev_01j9xr8c2d4e6f8g0h2j4k6m8n",
    "connection_id": "conn_01j9xp6q0r1s5t7v9w1x3y5z7b",
    "protocol": "saml",
    "kind": "sp_host",
    "status": "published",
    "discard_reason": null,
    "created_at": "2026-10-28T10:00:00Z",
    "decided_at": "2026-10-28T11:00:00Z",
    "purge_after": "2027-01-26T11:00:00Z",
    "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"
    }
  },
  "already_published": false
}
```

## Erreurs

| HTTP | code | Quand |
|---|---|---|
| 400 | `unknown_field` | Le corps n'est pas vide et n'est pas `{}`. |
| 401 | `unauthenticated` | L'identifiant d'accès est absent, invalide ou révoqué. |
| 403 | `insufficient_permissions` | L'identifiant d'accès ne dispose pas de `connections:write`. |
| 404 | `not_found` | La connexion ou la révision n'existe pas dans cet environnement, ou la révision appartient à une autre connexion. |
| 409 | `conflict` | Une condition préalable n'est pas remplie ; `detail` indique laquelle : la révision a été abandonnée ; elle n'a pas de test réussi au cours des dernières 24 heures ; la connexion a changé après la création du brouillon (créez un nouveau brouillon) ; la fenêtre de 30 jours de la migration précédente de l'hôte SP est toujours ouverte ; le nouvel hôte SP n'est plus un hôte de cet environnement ; la connexion dépasserait 3 certificats de signature actifs. |
| 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/revisions/connrev_01j9xr8c2d4e6f8g0h2j4k6m8n:publish" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

```bash
keenauth connections revisions publish conn_01j9xp6q0r1s5t7v9w1x3y5z7b connrev_01j9xr8c2d4e6f8g0h2j4k6m8n --yes
```
