Guides

Errors, pagination, and rate limits

Handle Monument REST API status codes and error bodies, page through list endpoints, and stay within rate limits.

This guide covers the three things every integration has to handle: how errors come back, how to page through lists, and how the rate limiter behaves.

Status codes

  • 200 OK and 201 Created return a record.
  • 204 No Content is returned by deletes and has an empty body.
  • 400 Bad Request means the query or JSON body failed validation.
  • 401 Unauthorized means the key is missing, invalid, revoked, or expired.
  • 404 Not Found means the record does not exist or is not visible to your key.
  • 429 Too Many Requests means you hit the rate limit.

Error shape

Errors return an error label and a human-readable message. Validation failures also include a details object describing which fields were rejected.

Error body
{
  "error": "Bad Request",
  "message": "Invalid request body",
  "details": {
    "fieldErrors": { "name": ["Required"] },
    "formErrors": []
  }
}
Some endpoints add a machine-readable code and a requestId alongside those fields. Log the message and, when present, the requestId to make support requests faster.

Paginate list endpoints

List endpoints return a pagination object with total, limit, and offset. Walk offset-based pages until you have collected total records.

JavaScript
const headers = { 'X-API-Key': 'monument_your_api_key' };
const limit = 100;
let offset = 0;
const all = [];

for (;;) {
  const res = await fetch(
    `https://api.monument.so/api/v1/projects?limit=${limit}&offset=${offset}`,
    { headers },
  );
  const { data, pagination } = await res.json();
  all.push(...data);

  offset += limit;
  if (offset >= pagination.total) break;
}

Rate limits

Keys default to 60 requests per minute and may be given a custom per-minute limit. Every response carries the current window on three headers:

  • X-RateLimit-Limit is the ceiling for this window.
  • X-RateLimit-Remaining is how many requests are left.
  • X-RateLimit-Reset is the Unix timestamp, in seconds, when the window resets.

When you exceed the limit, the request returns 429 with a Retry-After header (seconds to wait) and this body:

429 body
{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Retry after 12 seconds.",
  "code": "RATE_LIMITED",
  "retryAfter": 12
}

Retry safely

Honor the Retry-After header before retrying a 429, and watch X-RateLimit-Remaining to slow down before you hit the wall. Retry 429 and 5xx responses with exponential backoff. Do not retry other 4xx responses; the request itself needs to change first.