Zaroz
Usar la API

Usar la API de Zaroz

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

TerminalCode
export ZAROZ_API="https://kernel.zaroz.cloud/api/v2" export ZAROZ_TOKEN="zaroz_..." # ver "Tokens" más abajo AUTH="Authorization: Bearer $ZAROZ_TOKEN"

TypeScript

TypeScriptCode
// 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 }; }

Python

Code
# zaroz.py (pip install requests) import os import requests API = os.environ.get("ZAROZ_API", "https://kernel.zaroz.cloud/api/v2") _session = requests.Session() _session.headers["Authorization"] = "Bearer " + os.environ["ZAROZ_TOKEN"] def call(method, path, body=None, **kwargs): """Devuelve (estado, JSON analizado o None).""" r = _session.request(method, API + path, json=body, timeout=40, **kwargs) return r.status_code, (r.json() if r.content else None)

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:

JSONCode
{ "data": [ { "id": "..." } ], "pagination": { "page": 1, "page_size": 25, "total_items": 61, "total_pages": 3, "has_next_page": true, "has_previous_page": false } }

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.

curl

TerminalCode
curl -sS "$ZAROZ_API/subscriptions?page=1&page_size=50" -H "$AUTH"

TypeScript

TypeScriptCode
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 call page, 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 += 1 print(len(subscriptions))

Errores

Cada rechazo trae un estado HTTP y un cuerpo JSON con un code estable en kebab-case:

JSONCode
{ "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

TypeScriptCode
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:

curl

TerminalCode
curl -sS "$ZAROZ_API/public/capabilities"
JSONCode
{ "container_registry": true, "object_storage_buckets": true, "domain_connect": true, "unit_log_store": true, "unit_metrics_store": true, "paypal": true, "mollie": true, "nowpayments": true, "mail": true, "web_push": true, "warden": true }

TypeScript

TypeScriptCode
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 requests caps = 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

TerminalCode
curl -sS "$ZAROZ_API/public/incidents" # [{"id","title","message","started_at"}], solo incidentes en curso curl -sS "$ZAROZ_API/public/maintenances" # [{"id","title","scheduled_at","expected_duration_minutes"}], lo más próximo primero

TypeScript

TypeScriptCode
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.

Consulta Inicio de sesión, sesiones y seguridad de la cuenta para obtener una sesión, y Notificaciones, flujos en vivo y tickets de soporte para que te avisen cuando ocurra algo.

Last modified on