Todo lo que hace la consola lo puedes hacer con la API. Esta página recoge lo que es igual en todas las rutas; las guías siguientes (organizaciones, tokens, facturación, dominios, bases de datos, copias de seguridad, servicios) solo describen lo que es propio de cada una.
Todas las guías usan el mismo ayudante corto. Cópialo una vez.
curl
Code
export ZAROZ_API="https://kernel.zaroz.cloud/api/v2"export ZAROZ_TOKEN="zaroz_..." # ver "Tokens" más abajoAUTH="Authorization: Bearer $ZAROZ_TOKEN"
TypeScript
Code
// zaroz.ts (Node 20+, sin dependencias)const API = process.env.ZAROZ_API ?? "https://kernel.zaroz.cloud/api/v2";const TOKEN = process.env.ZAROZ_TOKEN!;export async function call<T = any>( method: string, path: string, body?: unknown, headers: Record<string, string> = {},): Promise<{ status: number; body: T }> { const res = await fetch(`${API}${path}`, { method, headers: { Authorization: `Bearer ${TOKEN}`, ...(body !== undefined ? { "Content-Type": "application/json" } : {}), ...headers, }, body: body !== undefined ? JSON.stringify(body) : undefined, }); const text = await res.text(); return { status: res.status, body: (text ? JSON.parse(text) : null) as T };}
La lista completa y siempre actual de rutas, cuerpos y respuestas es la referencia de la API. Estas guías son lo que la referencia no puede contarte: qué llamada hacer primero y por qué.
Tokens
Envía Authorization: Bearer <token> en cada petición. Un script usa un token de API que creas en la consola o con la API, limitado exactamente a los permisos que necesita; consulta Tokens de API y permisos. Un token nunca tiene más autoridad que la persona (u organización) que lo creó.
Paginación
Las rutas de lista que pueden crecer aceptan page (desde 1) y page_size, y responden con un sobre:
Sigue siempre has_next_page en lugar de adivinar cuántas páginas hay. Una lista sin paginar (por ejemplo los miembros de una organización) responde un array JSON simple.
import { call } from "./zaroz";let page = 1;const all: any[] = [];for (;;) { const { body } = await call("GET", `/subscriptions?page=${page}&page_size=50`); all.push(...body.data); if (!body.pagination.has_next_page) break; page += 1;}console.log(all.length);
Python
Code
from zaroz import callpage, subscriptions = 1, []while True: _, body = call("GET", f"/subscriptions?page={page}&page_size=50") subscriptions += body["data"] if not body["pagination"]["has_next_page"]: break page += 1print(len(subscriptions))
Errores
Cada rechazo trae un estado HTTP y un cuerpo JSON con un code estable en kebab-case:
Code
{ "code": "member-outranks-caller", "description": "You cannot change a member whose role is above yours", "details": "member-outranks-caller: You cannot change a member whose role is above yours"}
Decide por code, nunca por description. La descripción es una frase para personas y puede reescribirse o traducirse; el código no cambia.
Un 404 es también lo que recibes ante algo que no tienes permiso para ver, para que la API no revele qué existe.
429 significa que vayas más despacio. Respeta la cabecera Retry-After.
Los rechazos sobre los que un programa puede actuar (la API de Units) traen además un docs_url que apunta a la sección que explica el código y qué hacer.
Un rechazo nunca es un éxito parcial: una petición que falla no cambió nada.
TypeScript
Code
import { call } from "./zaroz";const r = await call("PATCH", `/organizations/${ORG}/members/${USER}`, { role: "admin" });if (r.status >= 400) { if (r.body.code === "member-outranks-caller") console.log("pide a un propietario que lo haga"); else throw new Error(`${r.status} ${r.body.code}`);}
Python
Code
status, body = call("PATCH", f"/organizations/{ORG}/members/{USER}", {"role": "admin"})if status >= 400: if body["code"] == "member-outranks-caller": print("pide a un propietario que lo haga") else: raise RuntimeError(f"{status} {body['code']}")
Idempotencia
Las rutas que mueven dinero o crean algo difícil de deshacer (canjear un código de monedero, pagar una factura con el monedero, la llamada allocate de Units) aceptan la cabecera Idempotency-Key. Repetir la misma petición con la misma clave responde con el primer resultado en lugar de un rechazo o un duplicado, así que un cliente que agotó el tiempo puede reintentar sin riesgo. Usa un valor aleatorio nuevo (un UUID) por cada acción, y reutilízalo solo al reintentar esa misma acción.
Qué ofrece un despliegue
Zaroz Cloud puede ejecutarlo un socio con solo una parte de la plataforma. Un despliegue puede no tener configurados el registro de contenedores, el almacenamiento de objetos, un proveedor de pago, Domain Connect o el almacén de logs de unidades. Pregúntaselo, sin autenticación:
const caps = await (await fetch(`${API}/public/capabilities`)).json();if (!caps.object_storage_buckets) console.log("este despliegue no tiene almacenamiento de objetos");
Python
Code
import requestscaps = requests.get(API + "/public/capabilities", timeout=10).json()if not caps["domain_connect"]: print("muestra solo las instrucciones manuales de DNS")
Un valor false significa que la función está ausente en ese despliegue, no averiada:
sus rutas responden 501 con el código capability-not-available;
sus productos no aparecen en el catálogo;
una integración no debería ofrecerla.
Un proveedor al que no se puede llegar en este momento también aparece como false. Guarda la respuesta poco tiempo (un minuto basta), no durante toda la vida de tu programa.
Estado de la plataforma
Dos lecturas sin autenticación dicen a un programa si la propia plataforma tiene problemas, incluso cuando nadie puede iniciar sesión. Son las que usan los avisos de caída y de mantenimiento de la consola.
curl
Code
curl -sS "$ZAROZ_API/public/incidents" # [{"id","title","message","started_at"}], solo incidentes en cursocurl -sS "$ZAROZ_API/public/maintenances" # [{"id","title","scheduled_at","expected_duration_minutes"}], lo más próximo primero
TypeScript
Code
const incidents = await (await fetch(`${API}/public/incidents`)).json();if (incidents.length) console.log("Incidente de la plataforma:", incidents[0].title);
Python
Code
incidents = requests.get(API + "/public/incidents", timeout=10).json()if incidents: print("Incidente de la plataforma:", incidents[0]["title"])
Los incidentes resueltos nunca se devuelven, y los mantenimientos son los no cancelados y programados desde hace menos de 24 horas. Compruébalo antes de avisar a alguien por un despliegue que falla.