|
| 1 | +# API EGAPRO — Équipe SUIT |
| 2 | + |
| 3 | +API REST sécurisée pour récupérer les déclarations soumises et les fichiers (avis CSE, évaluations conjointes). |
| 4 | + |
| 5 | +## Base URL |
| 6 | + |
| 7 | +- Alpha : `https://egapro-alpha.ovh.fabrique.social.gouv.fr/api/v1` |
| 8 | + |
| 9 | +## Authentification |
| 10 | + |
| 11 | +Chaque requête doit porter **trois en-têtes** : |
| 12 | + |
| 13 | +| Header | Valeur | |
| 14 | +| --- | --- | |
| 15 | +| `Authorization` | `Bearer <EGAPRO_SUIT_API_KEY>` | |
| 16 | +| `X-Timestamp` | Epoch en secondes (UTC) | |
| 17 | +| `X-Signature` | Signature RSA-SHA256 (base64) du payload `{timestamp}\|{METHOD}\|{pathname}` avec la clé privée SUIT | |
| 18 | + |
| 19 | +Fenêtre anti-replay : **30 jours** en dev/alpha, **30 secondes** en preprod/prod. |
| 20 | + |
| 21 | +## Générer la paire de clés RSA |
| 22 | + |
| 23 | +À faire **une seule fois** côté SUIT. Garder la clé privée en lieu sûr (coffre, secret manager). |
| 24 | + |
| 25 | +```sh |
| 26 | +openssl genrsa -out suit_private_key.pem 4096 |
| 27 | +openssl rsa -in suit_private_key.pem -pubout -out suit_public_key.pem |
| 28 | +``` |
| 29 | + |
| 30 | +Encoder la clé publique en base64 et la transmettre à l'équipe EGAPRO (qui l'injectera dans `EGAPRO_SUIT_PUBLIC_KEY_PEM`) : |
| 31 | + |
| 32 | +```sh |
| 33 | +base64 -w0 suit_public_key.pem # Linux |
| 34 | +base64 -i suit_public_key.pem | tr -d '\n' # macOS |
| 35 | +``` |
| 36 | + |
| 37 | +En retour, EGAPRO fournit la clé d'API (Bearer) à exporter : |
| 38 | + |
| 39 | +```sh |
| 40 | +export EGAPRO_SUIT_API_KEY="<clé fournie par EGAPRO>" |
| 41 | +``` |
| 42 | + |
| 43 | +## Générer la signature pour toutes les routes (en une commande) |
| 44 | + |
| 45 | +Signe toutes les routes SUIT avec le même `TS` et affiche les 3 headers + un `curl` prêt à copier pour chacune. |
| 46 | + |
| 47 | +Prérequis : `suit_private_key.pem` dans le dossier courant, `EGAPRO_SUIT_API_KEY` exporté, `BASE_URL` défini. |
| 48 | + |
| 49 | +```sh |
| 50 | +BASE_URL="https://egapro-alpha.ovh.fabrique.social.gouv.fr/api/v1" |
| 51 | +API_PREFIX="/api/v1" |
| 52 | +TS=$(date +%s) |
| 53 | + |
| 54 | +# Remplacer <fileId> par l'identifiant du fichier à télécharger. |
| 55 | +for ROUTE in \ |
| 56 | + "GET /export/declarations" \ |
| 57 | + "GET /files" \ |
| 58 | + "GET /files/<fileId>" |
| 59 | +do |
| 60 | + METHOD="${ROUTE%% *}" |
| 61 | + SUBPATH="${ROUTE#* }" |
| 62 | + PATHNAME="$API_PREFIX$SUBPATH" |
| 63 | + SIG=$(printf '%s|%s|%s' "$TS" "$METHOD" "$PATHNAME" \ |
| 64 | + | openssl dgst -sha256 -sign suit_private_key.pem \ |
| 65 | + | openssl base64 -A) |
| 66 | + echo "=== $METHOD $PATHNAME ===" |
| 67 | + echo "X-Timestamp: $TS" |
| 68 | + echo "X-Signature: $SIG" |
| 69 | + echo |
| 70 | + echo "curl -X $METHOD \\" |
| 71 | + echo " -H 'Authorization: Bearer '\"\$EGAPRO_SUIT_API_KEY\" \\" |
| 72 | + echo " -H 'X-Timestamp: $TS' \\" |
| 73 | + echo " -H 'X-Signature: $SIG' \\" |
| 74 | + echo " '$BASE_URL$SUBPATH'" |
| 75 | + echo |
| 76 | +done |
| 77 | +``` |
| 78 | + |
| 79 | +> La signature porte sur le **pathname complet** reçu par le serveur (`/api/v1/...`), pas sur le sous-chemin relatif à `BASE_URL`. |
| 80 | +> Au-delà de la fenêtre anti-replay (cf. section Authentification), la requête renverra 403 — regénérer `TS` + `SIG`. |
| 81 | +
|
| 82 | +## Générer pour une seule route |
| 83 | + |
| 84 | +```sh |
| 85 | +TS=$(date +%s) |
| 86 | +METHOD=GET |
| 87 | +PATHNAME=/api/v1/export/declarations |
| 88 | +SIG=$(printf '%s|%s|%s' "$TS" "$METHOD" "$PATHNAME" \ |
| 89 | + | openssl dgst -sha256 -sign suit_private_key.pem \ |
| 90 | + | openssl base64 -A) |
| 91 | +echo "X-Timestamp: $TS" |
| 92 | +echo "X-Signature: $SIG" |
| 93 | +``` |
| 94 | + |
| 95 | +## Endpoints |
| 96 | + |
| 97 | +### 1. Exporter les déclarations |
| 98 | + |
| 99 | +```sh |
| 100 | +curl "$BASE_URL/export/declarations?date_begin=2026-01-01&date_end=2026-01-31" \ |
| 101 | + -H "Authorization: Bearer $EGAPRO_SUIT_API_KEY" \ |
| 102 | + -H "X-Timestamp: $TS" \ |
| 103 | + -H "X-Signature: $SIG" |
| 104 | +``` |
| 105 | + |
| 106 | +- `date_begin` (obligatoire, `YYYY-MM-DD`) : date de début incluse |
| 107 | +- `date_end` (optionnel, `YYYY-MM-DD`) : date de fin exclue. Par défaut : `date_begin + 1 jour` |
| 108 | + |
| 109 | +### 2. Lister les fichiers d'une déclaration |
| 110 | + |
| 111 | +```sh |
| 112 | +curl "$BASE_URL/files?siren=123456789&year=2026" \ |
| 113 | + -H "Authorization: Bearer $EGAPRO_SUIT_API_KEY" \ |
| 114 | + -H "X-Timestamp: $TS" \ |
| 115 | + -H "X-Signature: $SIG" |
| 116 | +``` |
| 117 | + |
| 118 | +- `siren` (9 chiffres) et `year` (`YYYY`) obligatoires |
| 119 | + |
| 120 | +### 3. Télécharger un fichier |
| 121 | + |
| 122 | +```sh |
| 123 | +curl -OJ "$BASE_URL/files/<fileId>" \ |
| 124 | + -H "Authorization: Bearer $EGAPRO_SUIT_API_KEY" \ |
| 125 | + -H "X-Timestamp: $TS" \ |
| 126 | + -H "X-Signature: $SIG" |
| 127 | +``` |
| 128 | + |
| 129 | +Le `fileId` est renvoyé par l'endpoint `/files`. |
| 130 | + |
| 131 | +## Réponses d'erreur |
| 132 | + |
| 133 | +| Code | Cause | |
| 134 | +| --- | --- | |
| 135 | +| `400` | Paramètres invalides | |
| 136 | +| `401` | Clé API manquante ou invalide | |
| 137 | +| `403` | Signature manquante, invalide ou timestamp hors fenêtre | |
| 138 | +| `404` | Fichier introuvable | |
| 139 | +| `500` | Erreur serveur | |
| 140 | + |
| 141 | +## Documentation OpenAPI |
| 142 | + |
| 143 | +Disponible hors production (désactivée en prod) : |
| 144 | + |
| 145 | +- Swagger UI : `https://egapro-alpha.ovh.fabrique.social.gouv.fr/api/v1/docs` |
| 146 | +- Spec JSON : `https://egapro-alpha.ovh.fabrique.social.gouv.fr/api/v1/openapi.json` |
| 147 | + |
| 148 | +## Tester via Swagger UI |
| 149 | + |
| 150 | +Swagger UI ne signe pas les requêtes. Générer `X-Timestamp` + `X-Signature` en shell (bloc **Générer pour une seule route** ci-dessus, en adaptant `PATHNAME`), puis ouvrir Swagger : |
| 151 | + |
| 152 | +```sh |
| 153 | +open "https://egapro-alpha.ovh.fabrique.social.gouv.fr/api/v1/docs" |
| 154 | +``` |
| 155 | + |
| 156 | +1. Coller `X-Timestamp`, `X-Signature` et `Authorization: Bearer $EGAPRO_SUIT_API_KEY` dans **Authorize** |
| 157 | +2. Lancer la requête via **Try it out** |
| 158 | +3. 403 → regénérer `TS` + `SIG` (fenêtre 30 s en preprod/prod, 30 j en dev/alpha) |
0 commit comments