API HTTP
Fonctionnalité déployée et prise en charge. Les champs et commandes décrits ici sont stables au sein de la version v1alpha1.
L'API StackNGO est une API REST en JSON. La CLI sng et la console l'utilisent exclusivement :
tout ce qu'elles font, vous pouvez le faire avec curl ou un client généré depuis la
spécification OpenAPI.
Adresse et version
| Base URL | https://api.dev.stackngo.fr/v1 |
| Spécification OpenAPI 3.1 | https://api.dev.stackngo.fr/v1/openapi.yaml (publique, sans authentification) |
| Version | Tout est préfixé par /v1. Il n'y a pas d'en-tête de version. |
| Santé | GET /healthz (processus vivant), GET /readyz (dépendances prêtes), hors /v1 et sans authentification |
Les routes sont documentées une par une dans Endpoints, générées depuis la
spécification. Chaque route indique l'action IAM qu'elle exige (deploy:write,
ssm:read, …) : c'est ce qu'une policy doit accorder pour qu'elle réponde autre chose que
403.
Authentification en deux temps
- Obtenir un jeton d'identité (OIDC, auprès de
https://auth.dev.stackngo.app). - L'échanger contre une session de tenant avec
POST /v1/iam/session. - Envoyer la session dans
Authorization: Bearer <session>sur toutes les routes du tenant.
Le détail, avec des exemples curl, est dans Authentification.
Un seul jeton par requête ; l'en-tête X-Tenant-Token est refusé (400) sur toutes les
routes /v1, ouverture de session comprise : la session de tenant suffit.
Conventions de requête
- Corps en JSON :
Content-Type: application/jsonobligatoire surPOST,PUTetPATCHqui portent un corps. Sinon415. - Champs inconnus refusés : un champ non prévu dans le corps vaut
400. Les schémas OpenAPI sont donc exhaustifs. - Taille : un corps est limité à 1 Mo.
- Noms dans le chemin : les noms de ressources (
{name},{tenant}) sont des labels DNS en minuscules. Le tenant d'une requête vient toujours de la session, jamais du chemin ni d'un en-tête ; sur les routes/v1/tenants/{tenant}/…,{tenant}doit être celui de la session.
Conventions de réponse
Content-Type: application/json.- Les listes renvoient un objet qui enveloppe le tableau, nommé d'après la ressource :
{"secrets": […]},{"apps": […]},{"items": […]}. Il n'y a pas de pagination : les listes sont complètes. - Les créations répondent
201, les suppressions204sans corps, le reste200. - Les erreurs ont toutes la forme
{"error": "message"},415et429compris. Voir Erreurs. Retry-Afteraccompagne les409 policies_pending(tenant tout juste créé) et les429.
Limites et délais
300 requêtes par minute et par adresse IP sur les routes /v1 ; délais serveur de 30 s en lecture et 60 s en écriture. Détail et
conseils dans Limites.
Idempotence
PUT /v1/secrets/{name}etPUT /v1/iam/policies/{name}créent ou remplacent : rejouer la même requête donne le même état.POST /v1/applypuisPOST /v1/apply/completesont conçus pour être rejoués : un manifeste identique est marquéunchanged.- Les
POSTd'action (/scale,/restart,/rotate) ne sont pas idempotents.
Générer un client
curl -fsSL https://api.dev.stackngo.fr/v1/openapi.yaml -o openapi.yaml
npx openapi-typescript openapi.yaml -o stackngo.d.ts # TypeScript
go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest -package stackngo openapi.yaml # Go
La console StackNGO est elle-même générée depuis ce fichier.
Exemple complet
# 1. Identité (ici : un jeton déjà obtenu par la CLI)
ID_TOKEN=$(yq '.access_token' ~/.config/stackngo/config.yaml)
# 2. Session de tenant
SESSION=$(curl -fsS https://api.dev.stackngo.fr/v1/iam/session \
-H "Authorization: Bearer $ID_TOKEN" -H 'Content-Type: application/json' \
-d '{"tenant":"acme"}' | jq -r .access_token)
# 3. Une route du tenant
curl -fsS https://api.dev.stackngo.fr/v1/secrets -H "Authorization: Bearer $SESSION"
{"secrets":[{"name":"db-password","version_id":"3","version_stages":{"current":"3"},"updated_at":"2026-10-01T09:12:44Z"}]}