Pixloomdocs

Errors and limits

Every status code the API returns, what your plan allows per minute, and the headers that tell you where you stand.

Keys

Send the key as a header, or as ?key= where a header is impossible.

curl https://pixloom.dev/api/v1/styles -H "Authorization: Bearer sk_live_..."
curl "https://pixloom.dev/api/v1/styles?key=sk_live_..."

Secret keys (sk_live_) reach everything. Publishable keys (pk_live_) reach only what a browser needs: job, styles, embed resolve, analytics and the image proxy. Use one anywhere else and you get:

403 { "error": "Publishable keys cannot access this endpoint. Use a secret key (sk_live_)." }

Account status

The beta is invite-only and every account is approved by hand. Until yours is, every call returns:

403 { "error": "Account pending approval", "code": "pending_approval" }

pending_approval is the one error code worth branching on. Retrying does not help; wait for the email. A suspended or banned account gets a 403 too, with Account suspended or Account banned and no code.

Domains

Each key carries a list of domains it may run on. We check the browser's Origin header, or Referer for the image proxy, since browsers do not send Origin for image loads.

  • An empty list means any domain. That is what you want for a server-side secret key.
  • *.example.com covers example.com and every subdomain.
  • Localhost always passes, so development needs no setup.
  • A request with no origin at all passes, which is every server-to-server call.

A blocked origin gets 403 { "error": "Origin not allowed" }.

Rate limits

Per minute, counted against the key, on a sliding window.

PlanRequests per minute
Free30
Hobby60
Pro120
Business300
Enterprise600

The limit applies to generate, render and embed resolve. Analytics has the same ceiling in a separate bucket, so telemetry never spends your generation budget. Polling a job, listing styles and listing characters are not limited at all.

Responses carry X-RateLimit-Limit and X-RateLimit-Remaining. Over the line:

429 { "error": "Rate limit exceeded", "retryAfterMs": 60000 }

Back off for retryAfterMs and try again. The window slides, so a steady pace recovers faster than a burst.

Generations

Your plan includes a number of generations a month. The counter resets on a rolling monthly date, not the first of the month.

Only fresh images count. Cache hits, instant mode, permalinks serving something they already have, and everything in the library are all free.

Every generation response carries where you stand:

X-Quota-Used: 42
X-Quota-Limit: 100
X-Quota-Reset: 2026-10-01T00:00:00.000Z

Out of generations:

402 {
  "error": "Generation quota exceeded",
  "used": 100,
  "limit": 100,
  "resetAt": "2026-10-01T00:00:00.000Z"
}

Render tries harder before giving up: if you already made an image from that exact prompt, it redirects there instead of failing. A page that has been live for a while keeps working after you hit your limit.

Status codes

StatusMeaning
200Done.
202Accepted, work continues in the background. Generate and analytics.
302Redirect to an image. Render, image, proxy.
400Bad input. { "error": "Invalid request", "details": { ... } }, with details naming the fields.
401Missing API key or Invalid API key.
402Out of generations.
403Account not approved, wrong key type, or a domain that is not on the key.
404Not found, or not yours. We do not distinguish the two.
429Over the rate limit.
500{ "error": "Internal server error" }. Ours, not yours. Retry, and tell us if it persists.
502Generation failed at the model. Retry.

Validation errors

A bad body comes back with the field that was wrong:

400 {
  "error": "Invalid request",
  "details": {
    "formErrors": [],
    "fieldErrors": { "width": ["Number must be a multiple of 64"] }
  }
}

A body that is not JSON at all gets { "error": "Invalid JSON" }.

CORS

Every /api/v1/ endpoint answers preflight and allows GET, POST and OPTIONS with Content-Type and Authorization. When your key has a domain list, we echo back the matching origin. When it does not, we allow any. We never reflect an origin we have not checked.

On this page