Making a request
- Base URL
https://api.watx.in/v1. - Send
Authorization: Bearer <key>on every request. See Authentication. - Send
Content-Type: application/jsonon any request with a body. - Fields the endpoint does not know about are ignored.
- A request body is capped at 32 MB.
The success envelope
A single resource comes back underdata:
data, with a meta block carrying the
cursor for the next page:
200 for a read or an update, 201 for
something created, 202 for a broadcast that has been queued. POST /contacts
answers 200 when the phone number already belonged to a contact and 201 when
it created one, so the status tells you which happened.
The error envelope
error.code — it is stable. error.message is written for a person
reading a log and may be reworded.
Pagination
GET /contacts, GET /conversations and GET /conversations/{id}/messages
page the same way. Results are newest first.
integer
default:"50"
How many rows to return. Maximum 100. A missing or unusable value falls back
to 50, and anything above 100 is capped at 100.
string
The
meta.next_cursor from the previous response, passed back unchanged.
Cursors are opaque — do not parse or construct one. A cursor that cannot be
read is ignored and you get the first page again.string | null
The cursor for the next page, or
null when this was the last page.GET /segments returns every segment with no paging at all; GET /webhooks
returns every endpoint and always reports next_cursor: null; and
GET /segments/{id}/contacts honours limit but has no cursor.
Rate limits
120 requests per minute, per key. The window starts at the first request and covers the next 60 seconds, after which the count resets. Keys are counted independently, so one busy integration cannot spend another’s allowance. Over the limit, the request is refused with429 before it does any work:
429 carries four headers:
These headers appear on the
429 only. A successful response carries no
rate-limit headers, so track your own send rate rather than reading a counter
off every response.POST /broadcasts takes up to 1000 recipients in one request and sends them in
the background, which is both faster and kinder to the limit than 1000 calls to
POST /messages.
What to retry
There are no idempotency keys, so a retried
POST /messages sends a second
message. If a send times out, read the conversation with
GET /conversations/{id}/messages before sending again.
Two endpoints are naturally safe to repeat: POST /contacts finds or creates by
phone number, so calling it twice leaves one contact, and
POST /segments/{id}/contacts skips anyone already in the segment and tells you
how many rows it actually added.
Timestamps and ids
Every timestamp is ISO 8601 in UTC (2026-09-14T10:15:00.000Z). Every id is a
UUID. A nullable field is really null — phone is null for a contact who only
exists on Instagram, last_inbound_at is null for someone who has never
written to you.