Request and Response Format

10 views Markdown

One envelope, one set of status codes and one pagination shape, on every endpoint of every surface.

Overview

The shape of a call does not change from resource to resource. If you can read one response you can read all of them, and error handling written once keeps working as your integration grows.

Two rules carry most of it. A successful answer puts its payload under data, and a failed one puts a machine-readable code under error. The HTTP status always agrees with which of the two arrived.

Reference

The Request

Send JSON with a Content-Type: application/json header. A form-encoded POST is accepted as well, which helps when a client cannot set the header. Filters, sorting and paging travel in the query string on every method.

Authorization: Bearer The API key. X-Api-Key is the fallback for clients that cannot set this one.
Content-Type Set it to application/json when the body is JSON. Without it the body is read as form fields.
Idempotency-Key Optional, POST only, 8 to 191 characters. A repeat of the same key returns the stored answer instead of doing the work twice.
X-Http-Method-Override For callers behind a proxy that allows only GET and POST. The value replaces the method.

The Envelope

Success carries data, plus meta when there is anything to say about the payload. Failure carries error with a stable code, a human message and, on validation failures, a details map naming the fields.

both shapes
{ "data": { "id": 42, "email": "[email protected]" } }

{ "data": [ ], "meta": { "total": 318, "page": 2, "limit": 25, "next_page": 3 } }

{ "error": { "code": "validation_failed", "message": "Email is not valid.",
             "details": { "email": "invalid_format" } } }

Branch on the key, not on the text. code is part of the contract and stays put; message is written for a human reading a log and may be reworded.

Status Codes

200 · 201 Done. Creation answers with 201 and returns the new record.
401 No key, or one the installation does not know. Fix the credential; a retry will not help.
403 The key is known but not allowed here: wrong surface, missing permission, or a write while demo mode is on.
404 No such endpoint, or no such record for this key. On the client surface a record owned by someone else answers the same way.
409 A request with the same Idempotency-Key is still running. Wait and retry.
413 The body is past the server upload limit. It never reached the resource, so nothing was saved.
422 The input was understood and refused. details names the fields.
429 Too many requests. Honour Retry-After.
500 Something failed on the far side. The detail is kept in the operator's log, not in your response.

Pagination

List endpoints take page and limit in the query string. limit defaults to 25 and is capped at 100, so asking for more silently gives you 100. Walk pages with meta.next_page, which is 0 on the last one.

Offset paging is the v1 contract. Cursor paging exists only where the data is a timeline, such as ticket messages, and those endpoints document their own cursor fields.

Response Headers

Every credentialed answer reports the state of your budget, so you can pace yourself without guessing.

X-RateLimit-Limit Requests allowed in the current one-minute window.
X-RateLimit-Remaining What is left of it.
X-RateLimit-Reset Unix time when the window turns over.
Idempotency-Replayed Present when the answer came from storage rather than fresh work.

Example

a write with a safe retry
curl -X POST 'https://panel.example.com/api/v1/admin/clients' \
     -H 'Authorization: Bearer wak_...' \
     -H 'Content-Type: application/json' \
     -H 'Idempotency-Key: signup-8f21c0' \
     -d '{"name":"Ada","surname":"Lovelace","email":"[email protected]"}'
# 201  {"data":{"id":91,...}}

# the same call again returns the same body, and does not create a second client
# 201  Idempotency-Replayed: true

Pitfalls

Totals live under meta, not at the top

A list answer keeps its count at meta.total. Reading total from the root gives you nothing and no error, which reads as an empty result set. The same goes for page and limit.

Demo mode refuses every write

While an installation is in demo mode, POST, PUT, PATCH and DELETE come back as 403 demo_mode before any resource is reached. Reads keep working, so a demo stays browsable through the API. An integration that fails only on writes is worth checking against this first.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.