SDKs de TypeScript e Python

Clientes tipados gerados a partir do contrato OpenAPI: como usá-los hoje a partir do repositório, com exemplos de agendamento, erros, paginação e idempotência.

Atualizado:

A Wagend tem dois SDKs que são gerados a partir do contrato packages/openapi/openapi.yaml, então seus tipos sempre acompanham a API.

Os SDKs ainda não estão publicados no npm nem no PyPI (Em breve). Hoje são usados a partir do repositório, como explicado abaixo. Se preferir não depender deles, a API REST funciona com qualquer cliente HTTP.

TypeScript

O cliente (packages/sdk-ts) é um invólucro leve sobre fetch com tipos de todas as rotas.

Instalar a partir do repositório

cd packages/sdk-ts
npm ci
npm run build          # genera dist/

No seu projeto, instale-o a partir dessa pasta:

npm install /caminho/para/wagendapp/packages/sdk-ts

Agendar um horário

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];

  // Pré-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 },
  });

  // Confirmação com os dados do 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;
  }
}
  • Autenticação: o cliente adiciona Authorization: Bearer sozinho.
  • Idempotência: em toda escrita adiciona uma Idempotency-Key se você não passar uma. Para repetir uma operação, passe você a mesma chave nas duas tentativas (vale 24 horas). O tipo do TypeScript a declara em params.header nas rotas que a exigem.
  • Erros: toda resposta que não seja 2xx lança WagendError com .status, .code, .problem (RFC 9457) e .retryAfter (segundos, em 429).

Paginação

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 e ações

// Buscar e criar clientes (scopes customers:read e customers:write)
const { data: found } = await api.GET("/customers", { params: { query: { q: "carlos" } } });
await api.POST("/customers", { body: { name: "Ana", phone: "+5491155551111", tags: ["vip"] } });

// Executar uma ação da etapa, por exemplo atribuir uma entrega a um entregador (scope bookings:write).
// "atribuir" é a chave dessa ação no 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 },
});

As chaves de ação (key) são definidas pela configuração de etapas do seu negócio: consulte-as com GET /stage-config.

Python

O cliente (packages/sdk-py) usa httpx e modelos Pydantic v2 gerados.

Instalar a partir do repositório

pip install /caminho/para/wagendapp/packages/sdk-py
# ou, com uv:
uv pip install /caminho/para/wagendapp/packages/sdk-py

Agendar um horário

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() e list_slots() devolvem modelos tipados. Para as demais rotas use api.request(método, rota, params=…, json=…); você pode validar a resposta com wagend.models.
  • Idempotência: as escritas levam Idempotency-Key (uma é gerada se você não passar idempotency_key). Repita com a mesma chave.
  • Erros: WagendError com .status, .code, .problem e .retry_after (em 429).
  • Paginação: api.paginate("/bookings", params={"limit": 50}) percorre todas as páginas.
for booking in api.paginate("/bookings", params={"limit": 50}):
    print(booking["id"])

Limites de uso

O limite é por chave e por projeto. Diante de um 429, espere retry_after / retryAfter segundos antes de tentar de novo. Veja Convenções.

Regenerar os SDKs

Se o contrato mudar, make sdk regenera os dois a partir de openapi.yaml e make sdk-check falha se ficaram desatualizados.