API REST

L'adresse, comment un script se connecte, comment l'organisation est choisie, à quoi ressemblent les erreurs, et des exemples complets avec curl.

Tout ce que font la console et la CLI, elles le font à travers une seule API HTTP. La CLI est construite dessus et n'a pas de porte dérobée : tout ce que isogrid peut faire, un script muni du même identifiant peut le faire avec curl.

Cette page est un guide d'utilisation de cette API : l'adresse, la façon dont un script se connecte, et les appels dont la plupart des équipes ont besoin. Elle ne liste pas tous les points d'accès. S'il vous en faut un qui n'apparaît pas ici, la CLI couvre le même périmètre, et l'équipe vous donne l'appel exact sur demande.

L'adresse

Chaque appel part vers https://api.isogrid.skyvault.pro/api/v1.

Les exemples ci-dessous décrivent ce que l'API accepte aujourd'hui. Revérifiez-les après une mise à jour de la plateforme plutôt que de supposer qu'un champ est toujours là.

Se connecter depuis un script

Chaque appel porte un jeton :

Authorization: Bearer <token>

Pour un script, ce jeton est un identifiant CLI : un jeton de longue durée qui commence par skv_, créé par vous, en votre nom, pour une seule organisation. Vous le créez avec la CLI et vous l'approuvez dans le navigateur. Aucun formulaire de la console ne délivre de jeton sans cette approbation.

export ISOGRID_CONFIG_HOME="$(mktemp -d)"
isogrid --api https://api.isogrid.skyvault.pro login --name my-script
jq -r '.contexts[].token' "$ISOGRID_CONFIG_HOME/config.json"
rm -rf "$ISOGRID_CONFIG_HOME"

Le ISOGRID_CONFIG_HOME temporaire laisse intacte la connexion de votre propre machine. Installer la CLI explique comment obtenir isogrid.

Ce qu'il faut savoir sur l'identifiant :

  • Il est rattaché à l'organisation affichée sur la page d'approbation. Vérifiez-la avant d'approuver.
  • Il ne dépasse jamais ce que vous détenez. Ses permissions sont croisées avec votre propre rôle et vos groupes à chaque requête : réduire vos droits réduit aussi ceux du script.
  • Restreignez-le. Ajoutez --scope avec seulement ce dont le script a besoin, par exemple --scope application:create,application:write-any. Sans --scope, la page d'approbation propose ce qui convient à votre rôle et vous décochez le reste. Voir Déployer depuis la CI/CD pour les portées nécessaires à un déploiement.
  • Il dure 90 jours, sauf si vous avez choisi une durée plus courte sur la page d'approbation.
  • Certaines choses lui sont interdites, quoi qu'il demande : la facturation, la nomination d'administrateurs, et la création ou la révocation d'identifiants. Elles exigent que vous soyez connecté à la console.
  • Révoquez-le depuis la page CLI de la console quand le script est retiré ou que le jeton a pu fuiter.

Les exemples ci-dessous supposent :

export ISOGRID_API=https://api.isogrid.skyvault.pro/api/v1
export ISOGRID_TOKEN=skv_...

Gardez le jeton hors de l'historique de votre shell et hors de votre dépôt, comme vous le feriez pour un mot de passe.

Choisir l'organisation

Une personne peut appartenir à plusieurs organisations : tout ce qui appartient à l'une d'elles doit donc savoir laquelle. Vous l'indiquez par un en-tête, avec le slug de l'organisation ou son id :

X-Organization: acme

La même valeur est acceptée en paramètre de requête, ?organization=acme, pour les cas où un en-tête est peu pratique.

Avec un identifiant CLI, vous pouvez l'omettre : l'identifiant appartient déjà à une organisation et chaque appel agit dans celle-ci. En nommer une autre est refusé avec 403, et l'erreur indique à quelle organisation l'identifiant est rattaché.

À quoi ressemble une erreur

Chaque refus a la même forme, quelle que soit la cause :

{
  "error": {
    "code": "permission_denied",
    "message": "Your role in Acme (developer) does not allow this",
    "details": {
      "required_permission": "application:create",
      "role": "developer",
      "organization": "acme"
    }
  }
}

message est rédigé pour être montré à une personne. code est ce sur quoi un script doit se baser. details varie selon l'erreur et peut être vide.

Statut code Signification
401 unauthenticated Pas de jeton, ou un jeton inconnu, expiré ou révoqué.
402 insufficient_credits L'organisation ne peut pas payer ce qui est demandé. details indique combien il fallait.
403 permission_denied Vous, ou cet identifiant, n'avez pas le droit de faire cela.
404 not_found La ressource n'existe pas, ou vous n'avez pas le droit de la voir.
409 conflict La demande heurte l'existant : un nom déjà pris, ou un produit qui n'a pas encore de prix dans cette région.
422 validation_error La requête est mal formée. details.fields nomme chaque champ et ce qui ne va pas.
503 no_capacity La plateforme ne peut pas héberger cela pour le moment. La requête n'était pas fausse ; réessayez plus tard.

Avec curl, utilisez -f (ou --fail-with-body, pour garder le message) afin qu'un refus fasse échouer votre script au lieu d'être transmis à la commande suivante.

Listes et pages

Les listes principales (applications, bases de données, instances de bases de données, réseaux, régions, images) renvoient une page à la fois :

{ "items": [ ... ], "total": 37, "limit": 50, "offset": 0 }

limit vaut 50 par défaut et 200 au maximum. offset est le point de départ de la page. Pour tout lire, ajoutez limit à offset jusqu'à atteindre total.

Toutes les listes ne sont pas paginées ainsi. Quelques listes courtes (les constructions d'une application, les types d'instance d'une région) renvoient un simple tableau. Les exemples ci-dessous montrent la forme de chacune.

Ce qui prend du temps

Créer quelque chose rend la main avant que cela ne fonctionne. La réponse vous dit que la ressource existe et vous donne son id ; vous lisez ensuite son état jusqu'à ce qu'il se stabilise.

Vous avez demandé L'appel répond Lisez ensuite Jusqu'à ce que
Une application 201, avec l'application GET /applications/{id}/status deployment_status vaille running, ou failed
Une construction 202, avec un build_id GET /applications/{id}/builds/{build_id} status vaille succeeded, ou l'un de failed, no_dockerfile, restricted, cancelled
Un redéploiement 202 GET /applications/{id}/status comme pour une application
Une base de données 202, avec la base GET /databases/{id} status vaille ready, ou failed

Le deployment_status d'une application vaut none, queued, deploying, starting, running, degraded, stopped ou failed. degraded signifie qu'elle fonctionne, mais pas entièrement : moins de copies en marche que demandé, ou des copies qui redémarrent sans cesse. Le message qui l'accompagne dit pourquoi, en toutes lettres.

Interrogez toutes les quelques secondes, pas en boucle serrée. La sortie d'une construction se lit de la même façon : GET /applications/{id}/builds/{build_id}/logs?after=0 renvoie les lignes écrites jusque-là et un last_id ; passez-le dans after pour n'obtenir que ce qui est nouveau.

Exemples complets

Qui suis-je, et où puis-je déployer

curl -fsS "$ISOGRID_API/me" -H "Authorization: Bearer $ISOGRID_TOKEN"

renvoie votre compte et les organisations auxquelles vous appartenez. Les régions qui vous sont ouvertes, et les types d'instance qu'une région propose avec leurs prix :

curl -fsS "$ISOGRID_API/clusters" -H "Authorization: Bearer $ISOGRID_TOKEN" \
  | jq '.items[] | {id, slug, name}'

curl -fsS "$ISOGRID_API/pricing/applications/$CLUSTER_ID" \
  -H "Authorization: Bearer $ISOGRID_TOKEN" \
  | jq '.[] | {id, name, vcpu, memory_mb, prices}'

Dans l'API, une région est un cluster et un type d'instance est un resource_tier.

Lister vos applications

curl -fsS "$ISOGRID_API/applications?limit=20" \
  -H "Authorization: Bearer $ISOGRID_TOKEN" \
  | jq '.items[] | {id, slug, deployment_status, public_url}'

Créer une application à partir d'une image

curl -fsS -X POST "$ISOGRID_API/applications" \
  -H "Authorization: Bearer $ISOGRID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "hello",
    "source": "registry",
    "external_image": "nginx:1.27",
    "port": 80,
    "is_public": true
  }'

La réponse est l'application, avec son id, son slug, et l'adresse à laquelle elle répondra dans public_url. Son premier déploiement est déjà en file d'attente.

Ce que signifient les champs, et ce qui se passe quand vous en omettez un :

Champ Signification S'il est omis
name Obligatoire.
source registry pour une image ; github ou gitlab pour construire depuis un dépôt. github
external_image Une image de n'importe quel registre, en entier : nginx:1.27, ghcr.io/acme/web:main.
external_registry_id Le registre enregistré dont les identifiants servent à la tirer. L'image doit être publique.
cluster_id La région. La région du réseau que vous avez nommé, sinon la région par défaut de la plateforme.
resource_tier_id Le type d'instance. Le plus petit que la région propose.
network_id Le réseau privé sur lequel elle tourne. Le réseau de votre organisation dans cette région.
port Le port sur lequel le conteneur écoute. 8080 pour une image.
replicas Nombre de copies, de 1 à 10. 1
environment Paramètres non secrets, sous forme d'objet de chaînes. Aucun.
is_public Si elle est joignable depuis Internet. false

Une image du registre de votre organisation se désigne plutôt par image_id (GET /images les liste). Pour construire depuis un dépôt, envoyez repository_full_name (acme/api) et, si ce n'est pas main, default_branch ; le dépôt doit déjà être connecté à votre organisation, comme décrit dans Dépôts Git.

Les secrets ne vont pas dans environment. Envoyez-les dans secrets ; ils sont conservés à part et ne sont jamais renvoyés par aucun appel.

Lire son état

curl -fsS "$ISOGRID_API/applications/$APP_ID/status" \
  -H "Authorization: Bearer $ISOGRID_TOKEN"
{
  "application_id": "5b0c...",
  "deployment_status": "running",
  "desired": 1,
  "running": 1,
  "message": null,
  "checked_at": "2026-10-07T09:12:44Z",
  "listens": true,
  "tasks": [ ... ]
}

desired est le nombre de copies demandées et running le nombre de copies en marche maintenant. Pour attendre dans un script :

while :; do
  STATUS=$(curl -fsS "$ISOGRID_API/applications/$APP_ID/status" \
    -H "Authorization: Bearer $ISOGRID_TOKEN" | jq -r '.deployment_status')
  echo "$STATUS"
  case "$STATUS" in running|degraded|stopped|failed) break ;; esac
  sleep 5
done

Déployer de nouveau

Pour une application qui exécute une image, redéployez-la :

curl -fsS -X POST "$ISOGRID_API/applications/$APP_ID/deploy" \
  -H "Authorization: Bearer $ISOGRID_TOKEN"

Pour une application construite depuis un dépôt, lancez la construction d'une branche, d'un tag ou d'un commit ; elle est déployée quand la construction réussit :

curl -fsS -X POST "$ISOGRID_API/applications/$APP_ID/builds" \
  -H "Authorization: Bearer $ISOGRID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"git_ref": "main"}'

Lister vos bases de données

curl -fsS "$ISOGRID_API/databases" -H "Authorization: Bearer $ISOGRID_TOKEN" \
  | jq '.items[] | {id, name, engine, status}'

Ce sont les bases de données créées sur un serveur partagé. Vos propres serveurs de bases de données forment une liste distincte, GET /database-instances. Le status d'une base vaut pending, creating, importing, ready, failed ou deleting.

Les informations de connexion, mot de passe compris, font l'objet d'un appel distinct (GET /databases/{id}/connection) avec une permission distincte : pouvoir constater qu'une base existe n'est pas la même chose que recevoir ses identifiants.

Cas particuliers à connaître avant d'y être confronté

Un 401 sur un jeton qui fonctionnait hier. Il a expiré ou a été révoqué. Créez-en un nouveau ; rien d'autre ne change. La réponse est volontairement la même pour un jeton inconnu, expiré ou révoqué.

Un 403 qui nomme une autre organisation. Vous avez envoyé X-Organization pour une organisation à laquelle l'identifiant n'est pas rattaché. Retirez l'en-tête, ou créez un identifiant pendant que la console affiche l'organisation voulue.

Un 409 à la création qui parle d'un prix. Ce produit n'a pas encore de prix dans cette région : il n'y est donc pas en vente. Choisissez une autre région ou posez la question. Voir Prix et facturation.

Un 402 sur is_public. Votre organisation doit une somme pour une utilisation antérieure, et la publication est suspendue tant qu'elle n'est pas réglée. Créez l'application en privé, ou rechargez votre crédit.

L'appel de création a réussi et l'application a échoué. L'appel promettait seulement que l'application existe. Lisez /status, puis le journal de construction ou de déploiement. Quand ça ne va pas passe en revue les causes habituelles.

Les montants sont en nanos. Les montants terminés par _nanos sont des milliardièmes de l'unité monétaire : 1500000000 vaut 1,5. L'objet prices placé à côté porte le même chiffre, déjà mis en forme pour l'affichage.

Pour continuer