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
| Emplacement | Style | Exemple |
|---|---|---|
| Paramètres de requête | camelCase | ?pageSize=50&sortColumn=name |
| Champs JSON des requêtes et réponses | camelCase | "plan", "primaryIpv4" |
| Valeurs autorisées | Chaî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
Millicentscompte les millièmes de centime :150000vaut 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 :
12999vaut 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
}
}
| Champ | Signification |
|---|---|
success | true. |
data | Les données : un objet, ou un tableau pour les listes. |
pagination | Pour 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"
}
]
}
| Champ | Signification |
|---|---|
success | false. |
data | null, sauf en cas de refus du paiement d’une facture : contient alors le résultat du paiement (Facturation). |
code | Le 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. |
message | Une phrase destinée aux personnes. Sa formulation peut changer : ne l’analysez pas automatiquement. |
traceId | ID de la requête, égal à l’en-tête X-Request-Id. Indiquez-le au support. |
details | Une 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ètre | Valeur par défaut | Notes |
|---|---|---|
page | 1 | Commence à 1. Au-delà de la dernière page, data est vide. |
pageSize | 25 | De 1 à 1000. Une valeur hors plage donne 400. |
sortColumn | aucune | Champ de tri. |
ascending | true | false inverse le tri. |
search | aucune | Texte libre ; les espaces au début et à la fin sont retirés. Les champs recherchés dépendent du point de terminaison. |
filter[<field>] | aucune | Un 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
| Statut | Signification | Action |
|---|---|---|
400 | Requê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. |
401 | Clé absente, incorrecte, désactivée ou expirée, ou opération nécessitant une session console (Authentification). | Envoyez une clé valide. |
403 | Clé valide sans la permission vérifiée. | Utilisez une clé qui la possède. |
404 | Aucun 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, 415 | Mé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. |
409 | Un 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. |
422 | Requête lue, mais refusée par une règle de la ressource ou son état actuel. | Modifiez votre demande. |
500 | Une erreur de notre côté. | Réessayez plus tard et transmettez le traceId au support si elle persiste. |
502 | Un système derrière l’API a renvoyé une erreur. | Réessayez plus tard. |
503 | Un système derrière l’API est inaccessible ou une fonctionnalité est suspendue. Inclut toujours Retry-After. | Réessayez après Retry-After. |
504 | Un 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. Lecoded’un détail estINVALID_BODYlorsque le corps JSON lui-même est illisible : syntaxe incorrecte, type incorrect, membre obligatoire absent, membre non déclaré, valeur non autorisée. Il vautINVALID_VALUEpour 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_RANGEdé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. Lecodede chaque détail nomme la règle, commeBILLING_CYCLE_UNAVAILABLEpour une commande ; salocationvautnull.
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 :
| Code | Statut | Signification |
|---|---|---|
VALIDATION_ERROR | 400 | Requête illisible ; voir details. |
BAD_REQUEST | 400 | Requête HTTP elle-même illisible. |
UNAUTHENTICATED | 401 | Voir les erreurs d’authentification. |
NO_PERMISSION | 403 | La clé n’a pas la permission indiquée. |
ENTITY_NOT_FOUND | 404 | Aucune ressource avec cet ID dans votre organisation. |
ROUTE_NOT_FOUND | 404 | Aucun point de terminaison à ce chemin. |
METHOD_NOT_ALLOWED | 405 | Le chemin existe mais pas la méthode ; Allow liste les méthodes acceptées. |
ENTITY_ALREADY_EXISTS | 409 | Une ressource de même identité existe. |
ENTITY_IN_USE | 409 | La ressource est utilisée et ne peut être supprimée ou déplacée. |
ENTITY_STATE_INVALID | 422 | L’état de la ressource interdit l’opération et aucun code plus précis n’existe. |
VALIDATION_FAILED | 422 | Une règle a refusé la requête ; voir details. |
INTERNAL_ERROR | 500 | Une erreur de notre côté. |
UPSTREAM_ERROR | 502 | Un système derrière l’API a renvoyé une erreur. |
UPSTREAM_UNAVAILABLE | 503 | Un système derrière l’API est inaccessible. Retry-After: 30. |
UPSTREAM_TIMEOUT | 504 | Un système derrière l’API a dépassé le délai. |
Codes des serveurs bare metal :
| Code | Statut | Signification |
|---|---|---|
SERVICE_SUSPENDED | 422 | Service suspendu ; aucune modification avant rétablissement. |
SERVICE_LOCKED | 422 | Service verrouillé. |
SERVICE_DELETING | 422 | Service en cours de suppression, avec les mêmes refus qu’un service suspendu. |
OPERATION_IN_PROGRESS | 409 | Une autre opération s’exécute sur le serveur. |
BMC_RESET_IN_PROGRESS | 409 | Contrôleur de gestion en redémarrage. Retry-After: 30. |
BMC_UNREACHABLE | 503 | Contrôleur de gestion sans réponse. Retry-After: 30. |
BMC_REQUEST_FAILED | 502 | Le contrôleur de gestion a renvoyé une erreur. |
KVM_SESSION_REQUEST_IN_PROGRESS | 409 | Une demande de session console est déjà en cours pour ce serveur. Retry-After: 10. |
OPERATION_NOT_SUPPORTED_PLATFORM | 422 | Le matériel du serveur ne prend pas en charge l’opération. |
PRIMARY_IPV4_REQUIRED | 422 | Le déploiement nécessite une IPv4 principale sur le serveur. |
ISO_LIMIT_REACHED | 422 | L’organisation a atteint son nombre maximal d’ISO. |
ISO_UPLOAD_INCOMPLETE | 422 | Le téléversement de l’ISO n’est pas terminé ou n’a pas pu être vérifié. |
VIRTUAL_MEDIA_EJECT_FAILED | 502 | Le contrôleur de gestion n’a pas pu éjecter le support. |
VIRTUAL_MEDIA_ATTACH_TIMEOUT | 504 | Le rattachement du support virtuel a dépassé le délai. |
NETWORK_METRICS_UNAVAILABLE | 503 | Les métriques de trafic sont temporairement illisibles. Retry-After: 30. |
Codes des commandes et de la facturation :
| Code | Statut | Signification |
|---|---|---|
OFFERING_NOT_AVAILABLE | 422 | Offre impossible à commander ainsi : rupture de stock dans le datacenter, absence d’espace d’adressage ou UUID de datacenter inconnu. |
USAGE_BILLING_DISABLED | 422 | Facturation horaire désactivée pour l’organisation (Démarrage rapide). |
BILLING_ADDRESS_REQUIRED | 422 | L’organisation n’a pas d’adresse de facturation. |
PAYMENT_FAILED | 422 | Paiement impossible : carte refusée ou aucun crédit sur le compte ; data contient le résultat du paiement. |
INVOICE_CANNOT_ACCEPT_PAYMENT | 422 | Facture déjà payée, annulée ou remboursée, sans montant dû, ou paiement en attente de confirmation. |
SUBSCRIPTION_NOT_ACTIVE | 422 | Abonnement déjà résilié. |
SUBSCRIPTION_SERVER_TRANSFERRED | 422 | Un serveur facturé par l’abonnement appartient désormais à une autre organisation ; aucune modification. |
TERMINATION_BLOCKED | 422 | Un article de l’abonnement ne peut pas être résilié maintenant ; aucune modification. |
BUNDLED_ITEM_CANCELLATION_BLOCKED | 422 | Le bloc d’IP était inclus avec un serveur ; supprimer le serveur le libère. |
SUBSCRIPTION_CANCELLATION_INCOMPLETE | 422 | Certains articles ont été résiliés avant un échec. Renvoyer la requête est sûr. |
IDEMPOTENCY_KEY_REUSED | 409 | La Idempotency-Key a déjà servi pour une requête différente. |
ORDER_CREATION_IN_PROGRESS | 409 | Une requête avec la même Idempotency-Key crée encore la commande. Retry-After: 5. |
ORDER_PROVISIONING_IN_PROGRESS | 409 | Une création avec la même Idempotency-Key est encore en cours. Retry-After: 5. |
PROVISIONING_FAILED | 409 | Aucun élément d’une commande horaire, ou d’une demande horaire de serveur ou bloc d’IP, n’a pu être provisionné. |
VAT_SERVICE_UNAVAILABLE | 503 | La vérification du numéro de TVA UE n’a pas pu aboutir. Retry-After: 30. |
STRIPE_PROVIDER_ERROR | 502 | É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êtes | Limite |
|---|---|
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.