Draft
Conventions
Formats, idempotency, pagination, errors and rate limits.
Basics
- Base URL
https://api.wagend.app/v1. Breaking changes ship as a new version. - JSON in and out (
Content-Type: application/json). - Timestamps in ISO 8601 with offset (
2026-10-15T09:45:00-03:00). Stored in UTC. - Money in integer cents plus
currency(BRL,ARS,PYG,USD). - IDs are opaque strings with a prefix (
bkg_,svc_,res_,grp_,cus_).
Idempotency
POST /holds, POST /holds/{id}/confirm, POST /bookings and POST /bookings/{id}/reschedule require an Idempotency-Key header (for example a UUID). Repeating a request with the same key within 24 hours returns the original response. Reusing a key with a different body returns 422.
Pagination
List endpoints use cursors:
curl "https://api.wagend.app/v1/bookings?limit=50" -H "Authorization: Bearer $WAGEND_KEY"
# → { "data": [...], "next_cursor": "eyJpZCI6..." }
curl "https://api.wagend.app/v1/bookings?limit=50&cursor=eyJpZCI6..." -H "Authorization: Bearer $WAGEND_KEY"
Errors
Errors follow RFC 9457 (application/problem+json):
{
"type": "https://wagend.app/docs/api/conventions#errors",
"title": "Slot no longer available",
"status": 409,
"code": "slot_taken",
"alternatives": [{ "start": "2026-10-15T10:15:00-03:00", "end": "2026-10-15T10:45:00-03:00" }]
}
code | Status | When |
|---|---|---|
invalid_request | 400 / 422 | Validation failed |
unauthorized | 401 | Missing, invalid or revoked key |
insufficient_scope | 403 | Key lacks the scope |
not_found | 404 | Unknown id (or belongs to another workspace) |
slot_taken | 409 | Someone else got the slot |
invalid_transition | 409 | For example confirming a cancelled booking |
hold_expired | 410 | The hold expired before confirm |
idempotency_mismatch | 422 | Same key, different body |
rate_limited | 429 | Too many requests |
Rate limits
Limits apply per key and per workspace. Every response includes RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. On 429, wait Retry-After seconds.