SDK de TypeScript y Python
Clientes tipados generados desde el contrato OpenAPI: cómo usarlos hoy desde el repositorio, con ejemplos de reserva, errores, paginación e idempotencia.
Actualizado:
Wagend tiene dos SDK que se generan a partir del contrato packages/openapi/openapi.yaml, así que sus tipos siempre siguen la API.
Los SDK todavía no están publicados en npm ni en PyPI (Próximamente). Hoy se usan desde el repositorio, como se explica abajo. Si preferís no depender de ellos, la API REST funciona con cualquier cliente HTTP.
TypeScript
El cliente (packages/sdk-ts) es un envoltorio liviano sobre fetch con tipos de todas las rutas.
Instalar desde el repositorio
cd packages/sdk-ts
npm ci
npm run build # genera dist/
En tu proyecto, instalalo desde esa carpeta:
npm install /ruta/a/wagendapp/packages/sdk-ts
Reservar un horario
import { createWagendClient, WagendError } from "@wagend/sdk";
const api = createWagendClient({
baseUrl: "https://api.wagend.app/v1",
apiKey: process.env.WAGEND_API_KEY!, // wg_live_xxx
});
try {
const { data: services } = await api.GET("/services");
const serviceId = services!.data![0].id!;
const { data: slots } = await api.GET("/slots", {
params: { query: { service_id: serviceId, from: "2026-10-15T08:00:00-03:00", to: "2026-10-15T13:00:00-03:00" } },
});
const slot = slots!.data[0];
// Pre-reserva de 10 minutos
const { data: hold } = await api.POST("/holds", {
params: { header: { "Idempotency-Key": crypto.randomUUID() } },
body: { service_id: serviceId, start: slot.start, party_size: 1, resource_ids: slot.resource_ids },
});
// Confirmación con los datos del cliente
const { data: booking } = await api.POST("/holds/{id}/confirm", {
params: { path: { id: hold!.id! }, header: { "Idempotency-Key": crypto.randomUUID() } },
body: { customer: { name: "Carlos", phone: "+5491155550000", locale: "es" } },
});
console.log(booking!.status); // "confirmed"
} catch (err) {
if (err instanceof WagendError) {
console.error(err.status, err.code, err.retryAfter);
} else {
throw err;
}
}
- Autenticación: el cliente agrega
Authorization: Bearersolo. - Idempotencia: en toda escritura agrega una
Idempotency-Keysi no pasás una. Para reintentar una operación, pasá vos la misma clave en los dos intentos (vale 24 horas). El tipo de TypeScript la declara enparams.headerpara las rutas que la exigen. - Errores: toda respuesta que no sea 2xx lanza
WagendErrorcon.status,.code,.problem(RFC 9457) y.retryAfter(segundos, en 429).
Paginación
let cursor: string | undefined;
do {
const { data: page } = await api.GET("/bookings", { params: { query: { limit: 50, cursor } } });
for (const booking of page?.data ?? []) console.log(booking.id);
cursor = page?.next_cursor ?? undefined;
} while (cursor);
Clientes y acciones
// Buscar y crear clientes (scopes customers:read y customers:write)
const { data: found } = await api.GET("/customers", { params: { query: { q: "carlos" } } });
await api.POST("/customers", { body: { name: "Ana", phone: "+5491155551111", tags: ["vip"] } });
// Ejecutar una acción de la etapa, por ejemplo asignar una entrega a un repartidor (scope bookings:write).
// "atribuir" es la clave de esa acción en el modelo de entregas.
await api.POST("/bookings/{id}/actions/{key}", {
params: { path: { id: taskId, key: "atribuir" }, header: { "Idempotency-Key": crypto.randomUUID() } },
body: { data: {}, resource_id: courierResourceId },
});
Las claves de acción (key) las define la configuración de etapas de tu negocio: consultalas con GET /stage-config.
Python
El cliente (packages/sdk-py) usa httpx y modelos Pydantic v2 generados.
Instalar desde el repositorio
pip install /ruta/a/wagendapp/packages/sdk-py
# o, con uv:
uv pip install /ruta/a/wagendapp/packages/sdk-py
Reservar un horario
from datetime import UTC, datetime
from wagend import Wagend, WagendError
with Wagend("https://api.wagend.app/v1", "wg_live_xxx") as api:
try:
service = api.list_services()[0]
slots = api.list_slots(
str(service.id), datetime(2026, 10, 15, 8, tzinfo=UTC), datetime(2026, 10, 15, 13, tzinfo=UTC)
)
hold = api.request(
"POST", "/holds",
json={"service_id": str(service.id), "start": slots[0].start.isoformat(), "party_size": 1},
idempotency_key="reserva-carlos-2026-10-15",
)
booking = api.request(
"POST", f"/holds/{hold['id']}/confirm",
json={"customer": {"name": "Carlos", "phone": "+5491155550000"}},
)
print(booking["status"])
except WagendError as err:
print(err.status, err.code, err.retry_after)
list_services()ylist_slots()devuelven modelos tipados. Para el resto de las rutas usáapi.request(método, ruta, params=…, json=…); podés validar la respuesta conwagend.models.- Idempotencia: las escrituras llevan
Idempotency-Key(se genera una si no pasásidempotency_key). Reintentá con la misma clave. - Errores:
WagendErrorcon.status,.code,.problemy.retry_after(en 429). - Paginación:
api.paginate("/bookings", params={"limit": 50})recorre todas las páginas.
for booking in api.paginate("/bookings", params={"limit": 50}):
print(booking["id"])
Límites de uso
El límite es por clave y por proyecto. Ante un 429, esperá retry_after / retryAfter segundos antes de reintentar. Ver Convenciones.
Regenerar los SDK
Si cambia el contrato, make sdk regenera los dos desde openapi.yaml y make sdk-check falla si quedaron desactualizados.