Primeros pasos con la API

Convenciones de la API

Las reglas comunes de todos los endpoints de la API de Serverside.com: URL base, nombres, unidades monetarias, respuestas de éxito y error, paginación, códigos, reintentos e idempotencia.

URL base y versiones

https://api.serverside.com

Todas las rutas empiezan con un segmento de versión, /v1. Las peticiones y respuestas usan JSON sobre HTTPS; envía Content-Type: application/json con cualquier petición que tenga cuerpo. Todas las respuestas llevan una cabecera X-Request-Id.

Nombres y valores

DóndeEstiloEjemplo
Parámetros de consultacamelCase?pageSize=50&sortColumn=name
Campos JSON de peticiones y respuestascamelCase"plan", "primaryIpv4"
Valores permitidosCadenas UPPER_SNAKE_CASE"GRACEFUL_RESTART", "RAID10"

Un campo con un conjunto fijo de valores los enumera en Allowed values en su página de endpoint. Todos los conjuntos están en mayúsculas salvo location de un detalle de error, que solo aparece en respuestas de error. La API los compara sin distinguir mayúsculas, por lo que semi_annually se lee como SEMI_ANNUALLY. Otra escritura (SemiAnnually), un número en lugar del nombre o una lista separada por comas se rechazan con 400 y el error indica los valores que acepta el campo. La única excepción es el type de un elemento de pedido, que debe escribirse exactamente: BAREMETAL o IP_BLOCK.

Los ID son UUID y un campo sin ID que proporcionar es null, nunca una cadena vacía. Algunos campos que aceptan un ID también aceptan un nombre inmutable: el slug de un plan bare metal (epyc-9354p) y el code de un centro de datos, tres letras para el área metropolitana y un número de instalación (ams1). Los campos verdadero o falso se nombran como preguntas que empiezan por is, como isLocked, y un campo con unidad la indica: speedMbps, memoryGb, sizeBytes. Una duración enviada se expresa en segundos.

Las direcciones y redes IP se transmiten como cadenas, como "192.0.2.10" y "192.0.2.0/28". Una IPv4 debe escribirse en su forma habitual con puntos, así que 10.1 y 010.0.0.1 se rechazan; una IPv6 puede escribirse en cualquier formato, sin corchetes ni zona. Las marcas de tiempo son cadenas ISO 8601. Las que envíes deben incluir su desfase: 2026-09-20T00:00:00Z y 2026-09-20T02:00:00+02:00 se leen como el mismo instante y 2026-09-20T00:00:00 se rechaza. Todas las marcas de tiempo que envía la API están en UTC y terminan en Z.

Cuerpos de petición

Una propiedad JSON no declarada por el endpoint se rechaza con 400 VALIDATION_ERROR y el detalle INVALID_BODY identifica la propiedad, de modo que un campo opcional mal escrito se detecta en vez de descartarse.

PATCH cambia solo lo indicado en el cuerpo: un campo omitido conserva su valor y la respuesta es 200 con el recurso tal como lo devuelve su GET. Las tres operaciones PATCH, sobre un servidor, una red virtual y una clave SSH, aceptan un campo, name, y un nombre null conserva el anterior. PUT sustituye un ajuste completo, como el modo de arranque de un servidor o su script iPXE; lock y unlock también forman un par PUT.

Dinero

Los importes son números enteros en la divisa de su registro, indicada en currency (pricing.currency en un plan). Los enteros mantienen exactos todos los importes. La mayoría de analizadores JSON leen un decimal como 0.10 como número binario de coma flotante, que no puede representarlo exactamente: en JavaScript, 0.1 + 0.2 es 0.30000000000000004. El nombre del campo indica la escala:

  • Un campo cuyo nombre termina en Millicents cuenta milésimas de céntimo: 150000 es 1,50. Los precios y tarifas de planes, pedidos y suscripciones se expresan así, para conservar la fracción de céntimo de una tarifa por hora.
  • Todos los demás campos monetarios cuentan céntimos: 12999 es 129,99. Las facturas, los pagos, los cargos por uso y el crédito de cuenta se expresan así.

Un pedido solo contiene su precio. Los impuestos, descuentos e importe pendiente están en la factura (Facturación).

Respuestas de éxito y error

El estado HTTP distingue ambas estructuras: una respuesta 2xx es un éxito, cualquier otra es un error y success lo repite en el cuerpo.

Éxito

{
  "success": true,
  "data": { },
  "pagination": {
    "totalRecords": 42,
    "page": 1,
    "pageSize": 25,
    "totalPages": 2
  }
}
CampoSignificado
successtrue.
dataLos datos: un objeto o un array en endpoints de listas.
paginationEn listas paginadas (Paginación). Las demás respuestas lo omiten.

Una llamada que crea algo responde 201 con lo creado, con la estructura que devuelve su lectura. 202 Accepted significa que el cambio sigue aplicándose. Conectar un servidor a una red virtual, desconectarlo y cambiar su modo de arranque incluyen el progreso del cambio en data: un status de APPLYING y since, la hora en que se aceptó el cambio. Eliminar un servidor responde 202 sin cuerpo mientras se desmantela. Las respuestas 204 No Content no tienen cuerpo. Descargar PDF de factura es el único endpoint que devuelve un archivo en lugar de JSON.

Error

{
  "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"
    }
  ]
}
CampoSignificado
successfalse.
datanull, salvo si se rechaza un pago de factura: entonces contiene el resultado del pago (Facturación).
codeQué falló, como código estable UPPER_SNAKE_CASE. Decide el comportamiento con él y el estado. Un código que el cliente aún no conozca se gestiona por su estado.
messageUna frase para personas. Su redacción puede cambiar, así que no la analices programáticamente.
traceIdEl ID de la petición, igual a la cabecera X-Request-Id. Cítalo al contactar con soporte.
detailsUna entrada por problema, en errores de validación y algunos otros. Cada una tiene su propio code y message, el field afectado (null si el problema afecta a toda la petición) y la location de ese campo: body, query, route o header.

El cuerpo de error comparte success y data con uno de éxito, así que un cliente puede leer ambos con un único tipo.

Paginación

Ocho listas devuelven todas las filas a la vez y no llevan pagination: Listar regiones, Listar imágenes de SO, Listar aplicaciones, Obtener estado de PSU, Listar sesiones de consola, Listar medios virtuales, Obtener análisis de seguridad y Listar plugins de análisis. Todas las demás listas están paginadas y aceptan los mismos parámetros:

ParámetroPredeterminadoNotas
page1Empieza en 1. Una página posterior a la última devuelve data vacío.
pageSize25De 1 a 1000. Un valor fuera del intervalo produce 400.
sortColumnningunoEl campo por el que ordenar.
ascendingtruefalse invierte el orden.
searchningunoTexto libre; se eliminan los espacios iniciales y finales. Los campos donde busca dependen del endpoint.
filter[<field>]ningunoUn parámetro por campo filtrado.

La pagination de la respuesta repite page y pageSize y añade totalRecords y totalPages. Para leer toda una lista, solicita páginas hasta que page alcance totalPages; una lista vacía devuelve totalPages 0, así que compruébalo primero. También funciona detenerse en la primera página vacía. Todas las listas paginadas terminan su orden por el ID de cada fila, para que las filas empatadas en sortColumn mantengan su orden de una página a otra.

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

Un filtro sobre un campo de texto coincide con cualquier valor que lo contenga, sin distinguir mayúsculas. Un filtro sobre un campo con valores permitidos usa el valor tal como lo escribe la API, filter[status]=CANCELLATION_REQUESTED, y uno sobre un campo verdadero o falso acepta true o false. Un valor que el campo no pueda contener, un nombre por el que la lista no pueda filtrar o cualquier filtro en una lista que no los admita se rechazan con 400 VALIDATION_ERROR, con un detalle INVALID_VALUE cuyo field es la clave enviada (filter[status]). Un valor vacío no aplica filtro.

sortColumn y los nombres dentro de filter[...] no forman parte del contrato estable. Un sortColumn que el endpoint no conoce se ignora y la lista vuelve en su orden predeterminado.

Errores

Estados

EstadoSignificadoQué hacer
400No se pudo leer la petición: JSON mal formado, tipo incorrecto, propiedad no declarada por el endpoint, valor fuera del intervalo declarado, valor permitido desconocido, marca de tiempo sin desfase.Corrige la petición; la misma volverá a fallar.
401Falta la clave, es incorrecta, está desactivada o caducada, o el endpoint requiere una sesión de consola (Autenticación).Envía una clave válida.
403La clave es válida, pero le falta el permiso que comprueba el endpoint.Usa una clave que lo tenga.
404No existe nada con ese ID en tu organización o ningún endpoint tiene esa ruta. Un recurso de otra organización obtiene la misma respuesta.Comprueba el ID y la ruta.
405, 406, 408, 413, 415El método (la cabecera Allow enumera los admitidos por la ruta), la cabecera Accept, el tiempo del cuerpo, su tamaño o el tipo de contenido son incorrectos.Corrige la petición.
409Hay un impedimento: un duplicado, un recurso en uso o una operación en curso.Reintenta tras Retry-After si la respuesta lo incluye; de lo contrario, resuelve el conflicto.
422La petición se leyó y una regla del recurso o su estado actual la rechazó.Cambia lo solicitado.
500Un fallo de nuestro lado.Reintenta más tarde y envía el traceId a soporte si persiste.
502Un sistema detrás de la API respondió con un error.Reintenta más tarde.
503No se puede acceder a un sistema detrás de la API o una función está pausada. Siempre lleva Retry-After.Reintenta tras Retry-After.
504Un sistema detrás de la API no respondió a tiempo.Reintenta más tarde.

Retry-After es un número de segundos. Todas las respuestas 503 lo incluyen, igual que cada 409 que se resuelve solo, como un controlador de gestión que se reinicia. Reintentar un 500, 502 o 504 es seguro para las lecturas. De las llamadas que cambian algo, solo las cinco enumeradas en Idempotencia aceptan una clave que hace seguro el reintento; antes de reintentar cualquier otra, lee lo que existe, ya que la primera petición puede haberse completado.

Validación

Dos códigos incluyen una lista de details:

  • VALIDATION_ERROR, 400: no se pudo leer la petición. El code de un detalle es INVALID_BODY si no se puede leer el propio cuerpo JSON: sintaxis incorrecta, tipo incorrecto, miembro obligatorio ausente, miembro no declarado por el endpoint o valor fuera de los permitidos por el campo. Es INVALID_VALUE para un valor de consulta, ruta o cabecera y para un campo del cuerpo leído que incumple un límite declarado, como una longitud o intervalo. VALUE_OUT_OF_RANGE identifica un número que la operación comprueba en su propio código.
  • VALIDATION_FAILED, 422: la petición se leyó y una o más reglas la rechazaron. El code de cada detalle indica la regla, como BILLING_CYCLE_UNAVAILABLE en un pedido, y su location es null.

Un campo del cuerpo se identifica por su ruta JSON, con índices para arrays (items[0].plan, billingAddress.countryCode). Un campo de consulta se identifica tal como lo enviaste, uno de ruta por el nombre de su parámetro y una cabecera por su nombre. Con un detalle, message muestra field: problem; con varios, The request has N problems: seguido de cada uno.

Un pedido con un ciclo de facturación en el que no se vende su plan:

{
  "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 del cuerpo que no coincide con nada se trata según lo que identifica. Un plan, imagen, aplicación, segmento o interfaz es una entrada de catálogo y uno desconocido produce 422 con un detalle sobre ese campo, como OFFERING_NOT_FOUND en items[0].plan. Un ID de algo que posee tu organización (servidor, red o clave SSH) produce 404 ENTITY_NOT_FOUND sin campo, para que un ID de otra organización tenga el mismo aspecto que uno inexistente. Un centro de datos es la excepción: un code desconocido produce un detalle DATACENTER_NOT_FOUND y un UUID desconocido es 422 OFFERING_NOT_AVAILABLE.

Códigos

Códigos que puede devolver cualquier endpoint:

CódigoEstadoSignificado
VALIDATION_ERROR400No se pudo leer la petición; consulta details.
BAD_REQUEST400No se pudo leer la propia petición HTTP.
UNAUTHENTICATED401Consulta Errores de autenticación.
NO_PERMISSION403A la clave le falta el permiso indicado por el endpoint.
ENTITY_NOT_FOUND404No hay un recurso con ese ID en tu organización.
ROUTE_NOT_FOUND404Ningún endpoint tiene esa ruta.
METHOD_NOT_ALLOWED405La ruta existe, pero no el método; Allow enumera los métodos admitidos.
ENTITY_ALREADY_EXISTS409Existe un recurso con la misma identidad.
ENTITY_IN_USE409El recurso está en uso, por lo que no se puede eliminar ni mover.
ENTITY_STATE_INVALID422El estado del recurso no permite la operación y no existe un código más específico.
VALIDATION_FAILED422Una regla rechazó la petición; consulta details.
INTERNAL_ERROR500Un fallo de nuestro lado.
UPSTREAM_ERROR502Un sistema detrás de la API respondió con un error.
UPSTREAM_UNAVAILABLE503No se puede acceder a un sistema detrás de la API. Retry-After: 30.
UPSTREAM_TIMEOUT504Un sistema detrás de la API agotó el tiempo de espera.

Códigos de servidores bare metal:

CódigoEstadoSignificado
SERVICE_SUSPENDED422El servicio está suspendido; nada puede cambiar hasta que se restablezca.
SERVICE_LOCKED422El servicio está bloqueado.
SERVICE_DELETING422Se está eliminando el servicio y rechaza lo mismo que uno suspendido.
OPERATION_IN_PROGRESS409Hay otra operación en curso en el servidor.
BMC_RESET_IN_PROGRESS409El controlador de gestión se está reiniciando. Retry-After: 30.
BMC_UNREACHABLE503El controlador de gestión no responde. Retry-After: 30.
BMC_REQUEST_FAILED502El controlador de gestión devolvió un error.
KVM_SESSION_REQUEST_IN_PROGRESS409Ya hay una solicitud de sesión de consola en curso para el servidor. Retry-After: 10.
OPERATION_NOT_SUPPORTED_PLATFORM422El hardware del servidor no admite la operación.
PRIMARY_IPV4_REQUIRED422Un despliegue necesita una dirección IPv4 principal en el servidor.
ISO_LIMIT_REACHED422La organización tiene tantas ISO como se le permiten.
ISO_UPLOAD_INCOMPLETE422La subida de la ISO no ha terminado o no se ha podido verificar.
VIRTUAL_MEDIA_EJECT_FAILED502El controlador de gestión no pudo expulsar el medio.
VIRTUAL_MEDIA_ATTACH_TIMEOUT504Se agotó el tiempo de espera al conectar medios virtuales.
NETWORK_METRICS_UNAVAILABLE503No se pueden leer las métricas de tráfico por ahora. Retry-After: 30.

Códigos de pedidos y facturación:

CódigoEstadoSignificado
OFFERING_NOT_AVAILABLE422El plan no se puede contratar como se solicita: no hay existencias en ese centro de datos, no hay espacio de direcciones allí o el UUID del centro de datos es desconocido.
USAGE_BILLING_DISABLED422La organización no tiene activada la facturación por hora (Guía rápida).
BILLING_ADDRESS_REQUIRED422La organización no tiene dirección de facturación.
PAYMENT_FAILED422No se pudo cobrar el pago: la tarjeta fue rechazada o la organización no tiene crédito; data contiene el resultado del pago.
INVOICE_CANNOT_ACCEPT_PAYMENT422La factura ya está pagada, cancelada o reembolsada, no tiene importe pendiente o un pago está pendiente de confirmación.
SUBSCRIPTION_NOT_ACTIVE422La suscripción ya se ha cancelado.
SUBSCRIPTION_SERVER_TRANSFERRED422Un servidor facturado por la suscripción ahora pertenece a otra organización; no cambió nada.
TERMINATION_BLOCKED422Un elemento de la suscripción no puede cancelarse ahora; no cambió nada.
BUNDLED_ITEM_CANCELLATION_BLOCKED422El bloque de IP venía con un servidor; eliminar el servidor lo libera.
SUBSCRIPTION_CANCELLATION_INCOMPLETE422Algunos elementos se cancelaron antes de que fallara uno. Es seguro volver a enviar la petición.
IDEMPOTENCY_KEY_REUSED409La Idempotency-Key ya se usó para una petición diferente.
ORDER_CREATION_IN_PROGRESS409Una petición con la misma Idempotency-Key sigue creando el pedido. Retry-After: 5.
ORDER_PROVISIONING_IN_PROGRESS409Una creación con la misma Idempotency-Key sigue en curso. Retry-After: 5.
PROVISIONING_FAILED409No pudo aprovisionarse nada de un pedido por hora o de una solicitud de servidor o bloque de IP por hora.
VAT_SERVICE_UNAVAILABLE503No se pudo completar la comprobación del número de IVA de la UE. Retry-After: 30.
STRIPE_PROVIDER_ERROR502Falló el proveedor de pagos.

Los códigos de red se enumeran en Gestionar direcciones IP y Configurar redes virtuales, junto a las llamadas que los devuelven. Los códigos de detalle VALIDATION_FAILED se indican en la guía de la operación que los envía.

Idempotencia

Cinco operaciones aceptan una cabecera Idempotency-Key de hasta 200 caracteres: crear un pedido, crear un servicio bare metal, crear un bloque de IP y conectar o desconectar un servidor de una red virtual. Envía un valor nuevo para cada acción nueva y el mismo valor cuando reintentes esa acción.

Las tres llamadas de creación comparten un conjunto de claves por organización y una clave nunca se olvida. Un reintento con la misma clave y la misma compra (ciclo, código promocional y elementos) no crea nada nuevo y responde 200 en lugar de 201 con lo creado por la primera petición; Crear pedido también pone data.isReplayed en true. Identificar el plan por su slug en una petición y por su ID en la otra sigue contando como la misma compra, igual que el code de un centro de datos frente a su ID. La misma clave con una compra diferente se rechaza con 409 IDEMPOTENCY_KEY_REUSED. Mientras la primera petición sigue en curso, un reintento recibe 409 ORDER_CREATION_IN_PROGRESS u ORDER_PROVISIONING_IN_PROGRESS con Retry-After: 5; vuelve a enviarlo tras esos segundos.

En las llamadas de red virtual, una clave pertenece al servidor y se recuerda hasta 90 días después de aplicarse el cambio. Un reintento responde 202 de nuevo sin encolar un segundo cambio y la misma clave con otra red o segmento recibe 409 IDEMPOTENCY_KEY_REUSED. Un segundo cambio mientras el primero sigue aplicándose recibe 409 NETWORK_CHANGE_IN_PROGRESS con Retry-After: 10.

Límites de peticiones

Cada clave de API tiene sus propios límites:

PeticionesLímite
Lecturas (GET)1.000 por minuto
Escrituras (POST, PUT, PATCH, DELETE)100 por minuto

Los límites se aplican delante de la API y la propia API no envía 429.

Consultar un despliegue cada 20 segundos, como hacen las guías, usa 3 lecturas por minuto.