# API publique

Chaque page de statut publie des données en lecture seule, sans clé ni compte. Les adresses ci-dessous sont relatives à ta page : `https://status.hgdc.ch/<ton-nom>`, ou ton domaine personnalisé.

## Format Statuspage v2

Le format reprend l’API Statuspage v2, pour les outils qui la lisent déjà.

| Adresse                                        | Contenu                                                              |
| ---------------------------------------------- | -------------------------------------------------------------------- |
| `/api/v2/summary.json`                         | Résumé : état global, composants, incidents et maintenances en cours |
| `/api/v2/status.json`                          | État global de la page                                               |
| `/api/v2/components.json`                      | Composants et leur état                                              |
| `/api/v2/incidents.json`                       | Incidents récents                                                    |
| `/api/v2/incidents/unresolved.json`            | Incidents non résolus                                                |
| `/api/v2/scheduled-maintenances.json`          | Maintenances planifiées                                              |
| `/api/v2/scheduled-maintenances/active.json`   | Maintenances en cours                                                |
| `/api/v2/scheduled-maintenances/upcoming.json` | Maintenances à venir                                                 |

### Exemple de réponse

```json
{
  "page": { "id": "…", "name": "HGDC", "url": "https://status.hgdc.ch/hgdc", "time_zone": "Europe/Zurich", "updated_at": "2026-10-15T10:45:31.864Z" },
  "status": { "indicator": "none", "description": "All Systems Operational" },
  "components": [
    { "id": "…", "name": "Site hgdc.ch", "status": "operational", "group": false, "group_id": null, "position": 1 }
  ],
  "incidents": [],
  "scheduled_maintenances": []
}
```

Les champs et leurs valeurs sont ceux de Statuspage : `status.indicator` vaut `none`, `minor`, `major` ou `critical`, et `components[].status` vaut `operational`, `degraded_performance`, `partial_outage`, `major_outage` ou `under_maintenance`. Les textes d’incident sont ceux que tu as rédigés. Une page non publiée répond `404`, comme une page qui n’existe pas.

## Cache, accès depuis un navigateur et plafond

| Sujet      | Comportement                                                                                                              |
| ---------- | ------------------------------------------------------------------------------------------------------------------------- |
| Cache      | Réponse gardée 30 secondes au bord du réseau. Une lecture plus fréquente ne rend pas plus frais.                          |
| `ETag`     | Chaque réponse porte un `ETag`. Renvoie-le dans `If-None-Match` : si rien n’a changé, la réponse est un `304` sans corps. |
| CORS       | Ouvert en lecture (`Access-Control-Allow-Origin: *`) : un navigateur peut lire l’API depuis n’importe quel site.          |
| Plafond    | 120 lectures par minute et par adresse IP. Au-delà, `429` avec `Retry-After` : attends le délai indiqué.                  |
| Paramètres | Une adresse avec des paramètres (`?x=1`) est redirigée vers l’adresse sans paramètre.                                     |

## Exemples d’intégration

### Un widget sur ton site

```js
const res = await fetch("https://status.hgdc.ch/<ton-nom>/api/v2/status.json")
const { status } = await res.json()
document.querySelector("#etat").textContent = status.indicator === "none" ? "Tout fonctionne" : "Perturbation en cours"
```

Le navigateur gère l’`ETag` seul. Pas de clé à cacher : les données sont publiques.

### Depuis un serveur, par exemple Portal

```ts
let etag: string | undefined
let last: SummaryJson | undefined

async function readStatus(slug: string) {
  const res = await fetch(`https://status.hgdc.ch/${slug}/api/v2/summary.json`, {
    headers: etag ? { "if-none-match": etag } : {},
  })
  if (res.status === 304 && last) return last
  if (res.status === 404) return null // page inconnue ou non publiée
  if (!res.ok) throw new Error(`Status ${res.status}`)
  etag = res.headers.get("etag") ?? undefined
  last = (await res.json()) as SummaryJson
  return last
}
```

Lis `status.indicator` pour l’état global, et `components` pour le détail. Garde la dernière réponse en mémoire : en cas de `429` ou d’erreur réseau, affiche-la plutôt que de laisser un trou. Si tu as un domaine personnalisé, remplace `https://status.hgdc.ch/<ton-nom>` par ton domaine.

## Flux d’historique

| Adresse         | Format                       |
| --------------- | ---------------------------- |
| `/history.rss`  | RSS, pour un lecteur de flux |
| `/history.atom` | Atom, même contenu           |

L’historique couvre les incidents et les maintenances de la page.

## Badge

| Adresse       | Contenu                       |
| ------------- | ----------------------------- |
| `/badge.svg`  | Image SVG de l’état global    |
| `/badge.json` | Le même badge, au format JSON |

Le code prêt à coller est dans l’onglet **Intégrer** de la page, voir [afficher le statut sur ton site](/docs/guides/afficher-le-statut-sur-ton-site/).

## Ce qui n’est pas exposé

Les moniteurs, leurs adresses surveillées, leurs en-têtes et les abonnés ne figurent pas dans l’API publique. Seuls les composants et les évènements publiés sont exposés.

Les états sont décrits dans la [référence des statuts](/docs/reference/statuts/).
