Errors & conventions
Error envelope, status codes, pagination, scopes, and operational behavior.
Everything on this page applies uniformly to every Space API endpoint.
Base URLs
| Env | Base |
|---|---|
| Production | https://api.wakato.io/functions/v1/space-api |
| Development | https://pnwxrleocjbcvrrwrycq.supabase.co/functions/v1/space-api |
The MCP surface lives next to it at /functions/v1/space-mcp and accepts the
same token.
Authentication
Every request sends the Space API key as a Bearer token:
curl "$BASE/contacts" -H "Authorization: Bearer wks_live_YOUR_TOKEN"A key is bound to exactly one Space at mint time. There is no way to switch Spaces with a key — mint one key per Space.
Error envelope
All errors return a single, consistent JSON shape:
{ "error": "Human-readable message" }| Status | Meaning | Typical causes |
|---|---|---|
400 | Bad request | Invalid JSON body, missing required field |
401 | Unauthorized | Missing/malformed token, revoked key, expired key |
403 | Forbidden | The key lacks the scope the operation requires |
404 | Not found | Unknown route, or a resource id that doesn't exist in this Space |
500 | Server error | Unexpected failure — safe to retry once |
Two behaviors worth knowing:
404never reveals scope. A route outside your scopes that doesn't exist returns404, not403— error responses never confirm what a key could do with more scopes.- Cross-Space ids look like
404. Passing a valid id that belongs to a different Space behaves exactly like a nonexistent id.
Scopes
Each operation requires one scope, shown as Required scope on its
reference page (and as x-required-scope in the raw spec).
The three actions:
| Action | Grants |
|---|---|
read | List and inspect |
write | Create and edit — drafts, never anything live |
run | The consequential action: publish, send, post, run |
A 403 always means: the key works, the route exists, but this scope wasn't
granted. Re-mint the key (or mint a second one) with the scope added — scopes
on an existing key are fixed at creation.
Pagination
List endpoints that paginate accept limit and offset query parameters:
curl "$BASE/contacts?limit=50&offset=100" -H "Authorization: Bearer $KEY"- Default
limitis endpoint-specific (typically 50, capped at 200). - Responses return the records under a named key (e.g.
contacts,rows) — there is no envelope withtotal; page until you receive fewer thanlimitrecords.
Idempotency & retries
GETis always safe to retry.POSTcreates are not idempotent — there are no idempotency keys yet. After a timeout, check with the corresponding list/GETendpoint before re-creating.PATCHupdates are merge-style and safe to repeat with the same body.- Automation runs return
202and execute asynchronously — re-posting runs the automation again.
Rate limits
There are currently no per-request rate limits on the Space API. Two
structural limits exist instead: a Space can hold at most 20 active keys,
and consequential run actions (SMS, email, social posts) bill against the
Space wallet — an empty wallet stops them.
Be a good citizen: agents should batch reads where possible and back off on
5xx.
Realtime
Writes through the API appear live in any open Wakato tab (Pages, Contacts, Tasks, Documents, Calendar, Forms, Booking, Social) via Supabase Realtime — no polling needed on the human side.
Auditing
Every key records last_used_at, visible in Space → Settings → API Keys.
Revoking a key (same panel) takes effect immediately — in-flight requests
finish; the next request gets 401.