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' } }),
})