Quickstart

Create your first booking through the API in five minutes using a sandbox key.

This guide uses a test key (wg_test_...). Test keys work against a sandbox copy of your workspace: no WhatsApp messages are sent and no real payments are made.

Base URL: https://api.wagend.app/v1. Every request needs Authorization: Bearer <key>.

1. Get a test key

In the dashboard, go to Developers → API keys → New key, choose Test, and select the scopes slots:read, bookings:write and config:read. The key is shown only once.

export WAGEND_KEY="wg_test_xxxxxxxx_xxxxxxxxxxxxxxxxxxxx"

2. Check who you are

curl https://api.wagend.app/v1/me -H "Authorization: Bearer $WAGEND_KEY"
{
  "workspace": { "id": "ws_9f2c", "name": "Downtown Barbershop", "timezone": "America/Sao_Paulo", "locale": "pt", "currency": "BRL" },
  "scopes": ["slots:read", "bookings:write", "config:read"],
  "mode": "test"
}

The workspace always comes from the key. You never send a workspace id.

3. List services

curl https://api.wagend.app/v1/services -H "Authorization: Bearer $WAGEND_KEY"
{
  "data": [
    { "id": "svc_corte", "name": "Haircut", "duration_min": 30, "price_cents": 5000, "currency": "BRL",
      "requirements": [{ "resource_group_id": "grp_barbers", "units": 1 }] }
  ]
}

4. Find available slots

curl "https://api.wagend.app/v1/slots?service_id=svc_corte&from=2026-10-15T08:00:00-03:00&to=2026-10-15T13:00:00-03:00" \
  -H "Authorization: Bearer $WAGEND_KEY"
{
  "data": [
    { "start": "2026-10-15T09:00:00-03:00", "end": "2026-10-15T09:30:00-03:00", "resource_ids": ["res_juan"] },
    { "start": "2026-10-15T09:45:00-03:00", "end": "2026-10-15T10:15:00-03:00", "resource_ids": ["res_juan"] }
  ],
  "unavailable_reason": null
}

5. Hold the slot

A hold reserves the slot for 10 minutes while you collect the customer's details. Always send an Idempotency-Key so retries are safe.

curl -X POST https://api.wagend.app/v1/holds \
  -H "Authorization: Bearer $WAGEND_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "service_id": "svc_corte", "start": "2026-10-15T09:45:00-03:00", "resource_ids": ["res_juan"] }'
{ "id": "bkg_7Qx1", "status": "held", "expires_at": "2026-10-14T15:30:00-03:00", "start": "2026-10-15T09:45:00-03:00" }

6. Confirm

curl -X POST https://api.wagend.app/v1/holds/bkg_7Qx1/confirm \
  -H "Authorization: Bearer $WAGEND_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "customer": { "name": "Carlos", "phone": "+5521999990000", "locale": "pt" } }'
{ "id": "bkg_7Qx1", "status": "confirmed", "start": "2026-10-15T09:45:00-03:00", "source": "api" }

If the service requires a Pix deposit, the status is pending_payment and the response includes the Pix code. It becomes confirmed when the payment arrives.

Same flow in JavaScript

const api = (path: string, init: RequestInit = {}) =>
  fetch(`https://api.wagend.app/v1${path}`, {
    ...init,
    headers: { Authorization: `Bearer ${process.env.WAGEND_KEY}`, 'Content-Type': 'application/json', ...init.headers },
  }).then((r) => r.json())

const { data: slots } = await api(`/slots?service_id=svc_corte&from=${from}&to=${to}`)
const hold = await api('/holds', {
  method: 'POST',
  headers: { 'Idempotency-Key': crypto.randomUUID() },
  body: JSON.stringify({ service_id: 'svc_corte', start: slots[0].start }),
})
const booking = await api(`/holds/${hold.id}/confirm`, {
  method: 'POST',
  headers: { 'Idempotency-Key': crypto.randomUUID() },
  body: JSON.stringify({ customer: { name: 'Carlos', phone: '+5521999990000' } }),
})

Next