Premiers pas avec l’API

Conventions API

Les règles communes aux points de terminaison Serverside.com : URL de base, noms, unités monétaires, réponses, pagination, erreurs, nouvelles tentatives et idempotence.

URL de base et versions

https://api.serverside.com

Chaque chemin commence par le segment de version /v1. Les requêtes et réponses sont en JSON sur HTTPS ; envoyez Content-Type: application/json avec toute requête ayant un corps. Chaque réponse comporte un en-tête X-Request-Id.

Noms et valeurs

EmplacementStyleExemple
Paramètres de requêtecamelCase?pageSize=50&sortColumn=name
Champs JSON des requêtes et réponsescamelCase"plan", "primaryIpv4"
Valeurs autoriséesChaînes UPPER_SNAKE_CASE"GRACEFUL_RESTART", "RAID10"

Un champ à valeurs fixes les répertorie sous Allowed values sur sa page de référence. Tous ces ensembles sont en majuscules, sauf location dans les détails d’erreur, qui n’apparaît que dans les réponses d’erreur. L’API les compare sans tenir compte de la casse : semi_annually est lu comme SEMI_ANNUALLY. Une autre orthographe (SemiAnnually), un nombre à la place du nom ou une liste séparée par des virgules est refusé avec 400 ; l’erreur indique les valeurs acceptées. La seule exception est le type d’un article de commande, qui doit être écrit exactement : BAREMETAL ou IP_BLOCK.

Les ID sont des UUID ; un champ sans ID à fournir vaut null, jamais une chaîne vide. Quelques champs acceptant un ID acceptent aussi un nom immuable : le slug d’une offre bare metal (epyc-9354p) et le code d’un datacenter, composé de trois lettres pour la métropole et d’un numéro de site (ams1). Les champs booléens sont nommés comme des questions commençant par is, par exemple isLocked ; les champs portant une unité la nomment : speedMbps, memoryGb, sizeBytes. Une durée envoyée est en secondes.

Les adresses IP et réseaux sont des chaînes, comme "192.0.2.10" et "192.0.2.0/28". Une IPv4 doit utiliser la notation décimale pointée habituelle : 10.1 et 010.0.0.1 sont refusés. Une IPv6 accepte toute forme, mais sans crochets ni zone. Les horodatages sont des chaînes ISO 8601. Un horodatage envoyé doit inclure son décalage : 2026-09-20T00:00:00Z et 2026-09-20T02:00:00+02:00 désignent le même instant ; 2026-09-20T00:00:00 est refusé. Tous les horodatages renvoyés sont en UTC et se terminent par Z.

Corps des requêtes

Une propriété JSON non déclarée par le point de terminaison est refusée avec 400 VALIDATION_ERROR ; le détail INVALID_BODY la nomme. Un champ facultatif mal orthographié est donc détecté au lieu d’être ignoré.

PATCH ne modifie que les champs nommés dans le corps : un champ omis conserve sa valeur, et la réponse est 200 avec la ressource sous la même forme que son GET. Les trois opérations PATCH, sur un serveur, un réseau virtuel et une clé SSH, acceptent un champ, name ; un nom null conserve le nom existant. PUT remplace entièrement un paramètre, comme le mode de démarrage ou le script iPXE d’un serveur ; lock et unlock forment aussi une paire PUT.

Montants

Les montants sont des entiers dans la devise de leur enregistrement, indiquée par currency (pricing.currency pour une offre). Les entiers préservent l’exactitude. La plupart des analyseurs JSON lisent un décimal comme 0.10 comme un nombre binaire à virgule flottante, qui ne peut le représenter exactement : en JavaScript, 0.1 + 0.2 vaut 0.30000000000000004. Le nom du champ indique l’échelle :

  • Un champ se terminant par Millicents compte les millièmes de centime : 150000 vaut 1,50. Les prix et tarifs des offres, commandes et abonnements utilisent cette unité pour préserver les fractions de centime des tarifs horaires.
  • Tous les autres champs monétaires comptent les centimes : 12999 vaut 129,99. Cela concerne les factures, paiements, frais d’usage et crédit du compte.

Une commande ne porte que son prix. Les taxes, remises et montant dû figurent sur la facture (Facturation).

Réponses de réussite et d’erreur

Le statut HTTP distingue les deux formes : une réponse 2xx est une réussite, toute autre est une erreur ; success répète cette information dans le corps.

Réussite

{
  "success": true,
  "data": { },
  "pagination": {
    "totalRecords": 42,
    "page": 1,
    "pageSize": 25,
    "totalPages": 2
  }
}
ChampSignification
successtrue.
dataLes données : un objet, ou un tableau pour les listes.
paginationPour les listes paginées (Pagination). Absent des autres réponses.

Un appel de création répond 201 avec la ressource créée, sous la même forme que sa lecture. 202 Accepted signifie que la modification est encore en cours. Le rattachement d’un serveur à un réseau virtuel, son détachement et le changement de mode de démarrage placent la progression dans data : status vaut APPLYING et since indique l’acceptation de la modification. La suppression d’un serveur répond 202 sans corps pendant son retrait. Les réponses 204 No Content n’ont aucun corps. Télécharger le PDF d’une facture est le seul point de terminaison renvoyant un fichier plutôt que du JSON.

Erreur

{
  "success": false,
  "data": null,
  "code": "VALIDATION_ERROR",
  "message": "pageSize: Must be between 1 and 1000.",
  "traceId": "SRV-7F3A-0C21-9B4E-51D2",
  "details": [
    {
      "code": "INVALID_VALUE",
      "message": "Must be between 1 and 1000.",
      "field": "pageSize",
      "location": "query"
    }
  ]
}
ChampSignification
successfalse.
datanull, sauf en cas de refus du paiement d’une facture : contient alors le résultat du paiement (Facturation).
codeLe problème sous forme de code stable UPPER_SNAKE_CASE. Utilisez-le avec le statut pour choisir le traitement. Un code inconnu du client se traite selon son statut.
messageUne phrase destinée aux personnes. Sa formulation peut changer : ne l’analysez pas automatiquement.
traceIdID de la requête, égal à l’en-tête X-Request-Id. Indiquez-le au support.
detailsUne entrée par problème pour les erreurs de validation et quelques autres. Chacune possède son code, son message, le field concerné (null pour l’ensemble de la requête) et sa location : body, query, route ou header.

Le corps d’erreur partage success et data avec une réussite ; un client peut donc lire les deux avec un seul type.

Pagination

Huit listes renvoient toutes les lignes à la fois, sans pagination : Lister les régions, Lister les images système, Lister les applications, Obtenir l’état des PSU, Lister les sessions console, Lister les supports virtuels, Obtenir l’analyse de sécurité et Lister les plugins d’analyse. Toutes les autres listes sont paginées avec les mêmes paramètres :

ParamètreValeur par défautNotes
page1Commence à 1. Au-delà de la dernière page, data est vide.
pageSize25De 1 à 1000. Une valeur hors plage donne 400.
sortColumnaucuneChamp de tri.
ascendingtruefalse inverse le tri.
searchaucuneTexte libre ; les espaces au début et à la fin sont retirés. Les champs recherchés dépendent du point de terminaison.
filter[<field>]aucuneUn paramètre par champ filtré.

La pagination de la réponse reprend page et pageSize, et ajoute totalRecords et totalPages. Pour lire toute une liste, demandez les pages jusqu’à ce que page atteigne totalPages ; une liste vide renvoie totalPages à 0, vérifiez donc ce cas d’abord. Vous pouvez aussi vous arrêter à la première page vide. Chaque liste paginée termine son tri sur l’ID de chaque ligne ; les lignes à égalité sur sortColumn gardent ainsi leur ordre d’une page à l’autre.

curl --request GET \
  --url 'https://api.serverside.com/v1/baremetal?page=2&pageSize=100&sortColumn=name' \
  --header 'Authorization: Bearer <api-key>'

Un filtre texte correspond à toute valeur qui le contient, sans tenir compte de la casse. Un filtre sur un champ à valeurs fixes utilise la valeur écrite par l’API, filter[status]=CANCELLATION_REQUESTED ; un filtre booléen accepte true ou false. Une valeur incompatible, un champ non filtrable ou tout filtre sur une liste qui n’en accepte aucun sont refusés avec 400 VALIDATION_ERROR, avec un détail INVALID_VALUE dont field est la clé envoyée (filter[status]). Une valeur vide ne filtre pas.

sortColumn et les noms dans filter[...] ne font pas partie du contrat stable. Une sortColumn inconnue est ignorée ; la liste utilise son ordre par défaut.

Erreurs

Statuts

StatutSignificationAction
400Requête illisible : JSON mal formé, type incorrect, propriété non déclarée, valeur hors plage, valeur autorisée inconnue, horodatage sans décalage.Corrigez la requête ; la même échouera encore.
401Clé absente, incorrecte, désactivée ou expirée, ou opération nécessitant une session console (Authentification).Envoyez une clé valide.
403Clé valide sans la permission vérifiée.Utilisez une clé qui la possède.
404Aucun objet avec cet ID dans votre organisation, ou aucun point de terminaison à ce chemin. Une ressource d’une autre organisation reçoit la même réponse.Vérifiez l’ID et le chemin.
405, 406, 408, 413, 415Méthode (les méthodes acceptées figurent dans Allow), en-tête Accept, délai du corps, taille ou type de contenu incorrect.Corrigez la requête.
409Un obstacle existe : doublon, ressource utilisée, opération déjà en cours.Réessayez après Retry-After s’il est présent ; sinon résolvez le conflit.
422Requête lue, mais refusée par une règle de la ressource ou son état actuel.Modifiez votre demande.
500Une erreur de notre côté.Réessayez plus tard et transmettez le traceId au support si elle persiste.
502Un système derrière l’API a renvoyé une erreur.Réessayez plus tard.
503Un système derrière l’API est inaccessible ou une fonctionnalité est suspendue. Inclut toujours Retry-After.Réessayez après Retry-After.
504Un système derrière l’API n’a pas répondu à temps.Réessayez plus tard.

Retry-After est un nombre de secondes. Chaque 503 le contient, ainsi que chaque 409 qui se résout seul, comme un contrôleur de gestion en redémarrage. Réessayer un 500, 502 ou 504 est sûr pour les lectures. Parmi les appels de modification, seules les cinq opérations sous Idempotence acceptent une clé rendant la nouvelle tentative sûre ; avant de réessayer une autre, lisez l’état existant, car la première requête peut avoir abouti.

Validation

Deux codes contiennent une liste de details :

  • VALIDATION_ERROR, 400 : la requête n’a pas pu être lue. Le code d’un détail est INVALID_BODY lorsque le corps JSON lui-même est illisible : syntaxe incorrecte, type incorrect, membre obligatoire absent, membre non déclaré, valeur non autorisée. Il vaut INVALID_VALUE pour une valeur de requête, de route ou d’en-tête, ainsi que pour un champ du corps lu mais ne respectant pas une limite déclarée de longueur ou de plage. VALUE_OUT_OF_RANGE désigne un nombre vérifié dans le code propre à l’opération.
  • VALIDATION_FAILED, 422 : la requête a été lue, mais une ou plusieurs règles l’ont refusée. Le code de chaque détail nomme la règle, comme BILLING_CYCLE_UNAVAILABLE pour une commande ; sa location vaut null.

Un champ du corps est nommé par son chemin JSON, avec les indices des tableaux (items[0].plan, billingAddress.countryCode). Un champ de requête porte le nom envoyé, un champ de route le nom du paramètre et un en-tête son nom. Avec un détail, message prend la forme field: problem ; avec plusieurs, The request has N problems: suivi de chacun.

Une commande avec un cycle de facturation non proposé pour son offre :

{
  "success": false,
  "data": null,
  "code": "VALIDATION_FAILED",
  "message": "cycle: This billing cycle is not offered.",
  "traceId": "SRV-1A2B-3C4D-5E6F-7A8B",
  "details": [
    {
      "code": "BILLING_CYCLE_UNAVAILABLE",
      "message": "This billing cycle is not offered.",
      "field": "cycle",
      "location": null
    }
  ]
}

Un ID du corps ne correspondant à rien est traité selon ce qu’il désigne. Une offre, image, application, segment ou interface est une entrée du catalogue ; si elle est inconnue, la réponse est 422 avec un détail sur ce champ, comme OFFERING_NOT_FOUND sur items[0].plan. L’ID d’un objet appartenant à votre organisation (serveur, réseau, clé SSH) donne 404 ENTITY_NOT_FOUND sans champ ; l’ID d’une autre organisation ressemble ainsi à un ID inexistant. Un datacenter fait exception : un code inconnu donne un détail DATACENTER_NOT_FOUND, un UUID inconnu donne 422 OFFERING_NOT_AVAILABLE.

Codes

Codes possibles pour tout point de terminaison :

CodeStatutSignification
VALIDATION_ERROR400Requête illisible ; voir details.
BAD_REQUEST400Requête HTTP elle-même illisible.
UNAUTHENTICATED401Voir les erreurs d’authentification.
NO_PERMISSION403La clé n’a pas la permission indiquée.
ENTITY_NOT_FOUND404Aucune ressource avec cet ID dans votre organisation.
ROUTE_NOT_FOUND404Aucun point de terminaison à ce chemin.
METHOD_NOT_ALLOWED405Le chemin existe mais pas la méthode ; Allow liste les méthodes acceptées.
ENTITY_ALREADY_EXISTS409Une ressource de même identité existe.
ENTITY_IN_USE409La ressource est utilisée et ne peut être supprimée ou déplacée.
ENTITY_STATE_INVALID422L’état de la ressource interdit l’opération et aucun code plus précis n’existe.
VALIDATION_FAILED422Une règle a refusé la requête ; voir details.
INTERNAL_ERROR500Une erreur de notre côté.
UPSTREAM_ERROR502Un système derrière l’API a renvoyé une erreur.
UPSTREAM_UNAVAILABLE503Un système derrière l’API est inaccessible. Retry-After: 30.
UPSTREAM_TIMEOUT504Un système derrière l’API a dépassé le délai.

Codes des serveurs bare metal :

CodeStatutSignification
SERVICE_SUSPENDED422Service suspendu ; aucune modification avant rétablissement.
SERVICE_LOCKED422Service verrouillé.
SERVICE_DELETING422Service en cours de suppression, avec les mêmes refus qu’un service suspendu.
OPERATION_IN_PROGRESS409Une autre opération s’exécute sur le serveur.
BMC_RESET_IN_PROGRESS409Contrôleur de gestion en redémarrage. Retry-After: 30.
BMC_UNREACHABLE503Contrôleur de gestion sans réponse. Retry-After: 30.
BMC_REQUEST_FAILED502Le contrôleur de gestion a renvoyé une erreur.
KVM_SESSION_REQUEST_IN_PROGRESS409Une demande de session console est déjà en cours pour ce serveur. Retry-After: 10.
OPERATION_NOT_SUPPORTED_PLATFORM422Le matériel du serveur ne prend pas en charge l’opération.
PRIMARY_IPV4_REQUIRED422Le déploiement nécessite une IPv4 principale sur le serveur.
ISO_LIMIT_REACHED422L’organisation a atteint son nombre maximal d’ISO.
ISO_UPLOAD_INCOMPLETE422Le téléversement de l’ISO n’est pas terminé ou n’a pas pu être vérifié.
VIRTUAL_MEDIA_EJECT_FAILED502Le contrôleur de gestion n’a pas pu éjecter le support.
VIRTUAL_MEDIA_ATTACH_TIMEOUT504Le rattachement du support virtuel a dépassé le délai.
NETWORK_METRICS_UNAVAILABLE503Les métriques de trafic sont temporairement illisibles. Retry-After: 30.

Codes des commandes et de la facturation :

CodeStatutSignification
OFFERING_NOT_AVAILABLE422Offre impossible à commander ainsi : rupture de stock dans le datacenter, absence d’espace d’adressage ou UUID de datacenter inconnu.
USAGE_BILLING_DISABLED422Facturation horaire désactivée pour l’organisation (Démarrage rapide).
BILLING_ADDRESS_REQUIRED422L’organisation n’a pas d’adresse de facturation.
PAYMENT_FAILED422Paiement impossible : carte refusée ou aucun crédit sur le compte ; data contient le résultat du paiement.
INVOICE_CANNOT_ACCEPT_PAYMENT422Facture déjà payée, annulée ou remboursée, sans montant dû, ou paiement en attente de confirmation.
SUBSCRIPTION_NOT_ACTIVE422Abonnement déjà résilié.
SUBSCRIPTION_SERVER_TRANSFERRED422Un serveur facturé par l’abonnement appartient désormais à une autre organisation ; aucune modification.
TERMINATION_BLOCKED422Un article de l’abonnement ne peut pas être résilié maintenant ; aucune modification.
BUNDLED_ITEM_CANCELLATION_BLOCKED422Le bloc d’IP était inclus avec un serveur ; supprimer le serveur le libère.
SUBSCRIPTION_CANCELLATION_INCOMPLETE422Certains articles ont été résiliés avant un échec. Renvoyer la requête est sûr.
IDEMPOTENCY_KEY_REUSED409La Idempotency-Key a déjà servi pour une requête différente.
ORDER_CREATION_IN_PROGRESS409Une requête avec la même Idempotency-Key crée encore la commande. Retry-After: 5.
ORDER_PROVISIONING_IN_PROGRESS409Une création avec la même Idempotency-Key est encore en cours. Retry-After: 5.
PROVISIONING_FAILED409Aucun élément d’une commande horaire, ou d’une demande horaire de serveur ou bloc d’IP, n’a pu être provisionné.
VAT_SERVICE_UNAVAILABLE503La vérification du numéro de TVA UE n’a pas pu aboutir. Retry-After: 30.
STRIPE_PROVIDER_ERROR502Échec du prestataire de paiement.

Les codes réseau figurent dans Gérer les adresses IP et Configurer les réseaux virtuels, à côté des appels qui les renvoient. Les codes de détail VALIDATION_FAILED sont nommés dans le guide de l’opération concernée.

Idempotence

Cinq opérations acceptent un en-tête Idempotency-Key de 200 caractères maximum : créer une commande, créer un service bare metal, créer un bloc d’IP, et rattacher ou détacher un serveur d’un réseau virtuel. Envoyez une nouvelle valeur par action et la même valeur lors de ses nouvelles tentatives.

Les trois appels de création partagent un ensemble de clés par organisation ; une clé n’est jamais oubliée. Une nouvelle tentative avec la même clé et le même achat (cycle, code promotionnel, articles) ne crée rien de nouveau et répond 200 au lieu de 201, avec le résultat initial ; Créer une commande définit aussi data.isReplayed à true. Nommer l’offre par son slug puis par son ID reste le même achat, tout comme utiliser le code puis l’ID d’un datacenter. La même clé avec un achat différent est refusée avec 409 IDEMPOTENCY_KEY_REUSED. Pendant l’exécution initiale, une nouvelle tentative reçoit 409 ORDER_CREATION_IN_PROGRESS ou ORDER_PROVISIONING_IN_PROGRESS et Retry-After: 5 ; renvoyez-la après ce délai.

Pour les appels de réseau virtuel, une clé appartient au serveur et reste mémorisée jusqu’à 90 jours après application de la modification. Une nouvelle tentative répond encore 202 sans mettre une seconde modification en file ; la même clé avec un autre réseau ou segment donne 409 IDEMPOTENCY_KEY_REUSED. Une seconde modification pendant l’application de la première donne 409 NETWORK_CHANGE_IN_PROGRESS avec Retry-After: 10.

Limites de débit

Chaque clé API possède ses propres limites :

RequêtesLimite
Lectures (GET)1 000 par minute
Écritures (POST, PUT, PATCH, DELETE)100 par minute

Les limites sont appliquées en amont de l’API ; l’API elle-même n’envoie pas de 429.

Interroger un déploiement toutes les 20 secondes, comme dans les guides, utilise 3 lectures par minute.