Documentation
Partner API

Rate limits

Two requests a second with small bursts on the default plan, Retry-After on 429, monthly caps, and the non-JSON 403 edge throttle with a 90-second back-off.

Updated 2026-10-24MarkdownOpenAPI

Two limits apply to your keys: a pace per key, and monthly caps per plan. Both answer 429 with a JSON envelope. The network edge in front of the API adds a third, coarser one that answers without JSON.

Pace

The default plan allows 2 requests a second per key with bursts up to 10; your plan may allow more, and GET /v1/ping reports your rate_limit. Over the limit you get 429 RATE_LIMITED with Retry-After in seconds, X-RateLimit-Limit and X-RateLimit-Remaining. Throttled calls are logged like any other and counted in your usage.

Monthly caps

Your plan may cap requests, live orders and test orders per calendar month (UTC). GET /v1/account shows the caps under limits — monthly_request_cap, monthly_order_cap, monthly_test_order_cap, where 0 means no cap — and this month's usage. At 80 percent of a cap you get usage.warning once; at the cap, 429 QUOTA_EXCEEDED until the first of next month. The request cap is checked against a count refreshed every 30 seconds, so a handful of calls may pass over it. A quote cap per day (quote_daily_cap) works the same way.

The edge throttle

In front of the API sits a network edge that protects every LayerCrew service. Above roughly 5 requests a second from one address it answers 403 with an HTML or empty body — no JSON envelope, no X-Request-ID.

  • Treat a 403 without JSON as the edge: back off 90 seconds, then resume at two requests a second.
  • Keep to two requests a second per source address, with small bursts, even when your plan's key limit is higher.
  • Never retry a create blindly. For an order, send the same Idempotency-Key again or look it up by reference; for a file, list your files; for a webhook endpoint, list your endpoints.

Designing for the limits

  • Use webhooks for state changes and the events feed to reconcile; polling each order is the pattern that hits the limits first.
  • Batch your reads: lists take per_page up to 100, the feed limit up to 200.
  • One client, one queue: a shared token bucket in your integration keeps bursts in bounds.
  • Back off on 429 and on 5xx with jitter; quote X-Request-ID if a pattern repeats.
Node
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

export async function layercrew(path, init = {}, attempt = 0) {
  const res = await fetch(`https://engine.layercrew.com/v1${path}`, {
    ...init,
    headers: { Authorization: `Bearer ${process.env.LAYERCREW_API_KEY}`, ...(init.headers ?? {}) },
  });
  const isJson = (res.headers.get("content-type") ?? "").includes("application/json");
  if (res.status === 403 && !isJson) {
    await sleep(90_000);                       // the edge: back off 90 seconds
    return layercrew(path, init, attempt + 1); // same init, same Idempotency-Key
  }
  if ((res.status === 429 || res.status >= 500) && attempt < 5) {
    const retryAfter = Number(res.headers.get("retry-after")) || 2 ** attempt;
    await sleep(retryAfter * 1000 + Math.random() * 500);
    return layercrew(path, init, attempt + 1);
  }
  return res;
}

A fetch wrapper that honours Retry-After, backs off the edge and never retries a create without its key

Body size

Request bodies are limited to 256 KiB — 413 PAYLOAD_TOO_LARGE beyond it. File bytes never travel in JSON; they go to the signed upload URL described under Files.

Îți respectăm confidențialitatea

Folosim cookie-uri pentru analiză și publicitate, ca să îți îmbunătățim experiența și să ne măsurăm marketingul. Vezi Politica de confidențialitate.