Car Image API
Documentation

Rate limits & caching

120 req/min per key, RateLimit-* headers, ETags and cache policy.

Rate limits

Each API key may make 120 requests per minute by default, counted in a fixed 60-second window. Every response announces the budget so clients can pace themselves without guessing; higher per-key limits are available on request. Unauthenticated endpoints (device codes, the playground) are limited per IP.

HeaderExampleMeaning
RateLimit-Limit120Requests allowed per window for this key.
RateLimit-Remaining117Requests left in the current window.
RateLimit-Reset42Seconds until the window resets.
Retry-After42Only on 429: integer seconds to wait before retrying.
429 Too Many Requests
HTTP/2 429
content-type: application/problem+json
ratelimit-limit: 120
ratelimit-remaining: 0
ratelimit-reset: 42
retry-after: 42

{"type":"https://carimage.dev/docs/errors#429","title":"Too Many Requests","status":429,"detail":"Rate limit exceeded for this key. Retry after 42 seconds.","request_id":"req_01j9x…"}

ETags: free repeats

Every image response carries a stable ETag per variant. Send it back as If-None-Match and an unchanged image returns 304 Not Modified with no body and no credit charged. Weak comparison is used, so a W/ prefix on either side still matches.

bash
curl -sI -H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
  -H 'If-None-Match: "9f2a…c41d"' \
  "https://carimage.dev/api/v1/images/car?make=porsche&model=911&year=2024&view=side"
# HTTP/2 304
# etag: "9f2a…c41d"

Cache policy by response type

ResponseCache-ControlWhy
Keyed image bytes (GET /api/v1/images/car)private, no-storeBilled requests reach authorization and metering. Save bytes explicitly and use ETags for free conditional requests, or use signed URLs for embeds.
Signed URL, unlimited usespublic, max-age=<up to 300>, s-maxage=<up to 3600>, must-revalidateBilled once at creation. Browser caching is capped at five minutes and shared caching at one hour, always within the URL lifetime. Reuse the same URL to maximize CDN hits.
Signed URL with max_usesprivate, no-storeEvery redemption must reach the origin so the use counter can be enforced.
Free example imagespublic, max-age=300, s-maxage=3600, stale-while-revalidate=60Public images stay fast at the edge while upgrades become visible on revalidation. The original image stays available during background upgrades.

The rule of thumb: a response that cost a credit is private to the caller; a response that was prepaid (a signed URL) or free (an example) may be shared. If you want a CDN in front of your images, mint signed URLs with a long TTL and unlimited uses.

Cold renders and concurrency

Cold renders are the slow path (up to two minutes). Concurrent requests for the same new variant share one generation; each delivered image costs one credit. Allow three minutes on the client for generation and coordination. Spread large batches out: generation capacity and the daily provider budget are finite, separate from rate limits.