BoxLatviaDevelopers
Get access
Guides

Limits & best practices

What the API limits, and how to build an integration that stays within it.

#Limits

LimitValue
Request size27 MB
Pictures5 files per request, 5 MB each; JPEG, PNG, WebP or GIF; at most 20 per box or location
List page size1 to 200 (default 50)
Access token lifetime15 minutes
Failed authentications10 per 5 minutes per IP address, then 429
Idempotency-Key1 to 200 characters; remembered for 24 hours
Text fieldsLocation name 100, description and address 250; box name and description 255; external_id 100 characters
Time per requestA few seconds. A request that runs too long answers 503.
Request rate
There is no hard request-rate limit in this preview, and limits may be introduced later. Please be considerate: a few requests per second is plenty, and batching with PUT …/by-external-id/… is better than reading everything before every write.

#Synchronising your catalogue

  1. Keep your own id as external_id on every location and box.
  2. When something changes in your system, call PUT /v1/locations/by-external-id/{id} or PUT /v1/boxes/by-external-id/{id} with the fields that changed.
  3. For stock, send the full current figure (available_units), never an increment: customers may book while your feed runs.
  4. Submit new boxes for review when their missing list is empty.
  5. Read the reference lists once a day at most.

#Retrying

Retry on timeouts, 5xx and 429, with growing pauses and the same Idempotency-Key:

JavaScript
async function send(url, options, tries = 5) {
  const key = crypto.randomUUID();                       // one key per operation
  for (let attempt = 0; attempt < tries; attempt++) {
    try {
      const res = await fetch(url, {
        ...options,
        headers: { ...options.headers, "Idempotency-Key": key },
      });
      if (res.status < 500 && res.status !== 429) return res; // done (or a real error to fix)
      const wait = Number(res.headers.get("Retry-After")) * 1000 || 2 ** attempt * 1000;
      await new Promise((r) => setTimeout(r, wait));
    } catch {
      await new Promise((r) => setTimeout(r, 2 ** attempt * 1000)); // network error
    }
  }
  throw new Error("Giving up after " + tries + " tries");
}

#Good practice