Signed URLs
POST /api/v1/image-urls — browser-safe URLs billed once at creation.
Signed URLs let a browser, an email or a CMS load an image without ever seeing your API key. Your backend mints them; anyone holding the URL can open it until it expires. Each URL costs one credit at creation, no matter how many times it is opened within its TTL.
Create URLs
POST
/api/v1/image-urlsimages:read1 credit per URL
| Parameter | Type | Description |
|---|---|---|
imagesrequired | ImageRequest[] (1–50) | Each item takes the same fields as GET /api/v1/images/car: make, model, year (required), view, color, size, width, height, format. A single object is also accepted as the whole body. |
ttl_seconds | integer 1–604,800 | How long the URLs stay valid. Maximum seven days.Default: 3600 |
max_uses | integer ≥ 0 | Cap on redemptions per URL. 0 means unlimited within the TTL; 1 makes a single-use link.Default: 0 |
curl --fail-with-body \
-X POST https://carimage.dev/api/v1/image-urls \
-H "Authorization: Bearer $CAR_IMAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"images":[{"make":"porsche","model":"911","year":2024,"view":"front-3-4","color":"red"}],"ttl_seconds":3600}'{
"data": [
{
"id": "3f0c2a7e-1c1e-4c2a-9c39-4f1f0a4b2d10",
"url": "https://carimage.dev/api/v1/delivery/eyJhbGciOi…",
"expires_at": "2026-09-02T18:00:00.000Z",
"max_uses": 0,
"vehicle": {
"make": "porsche",
"model": "911",
"year": 2024,
"view": "front-3-4",
"color": "red"
}
}
],
"billing": {
"charged_on": "creation",
"credits_per_url": 1,
"credits_charged": 1,
"credits_remaining": 4869
},
"request_id": "req_01j9x…"
}Redeem a URL
GET
/api/v1/delivery/{token}nonefree
Redemption needs no key and is not billed. Drop the URL straight into an <img>:
<img
src="https://carimage.dev/api/v1/delivery/eyJhbGciOi…"
alt="2024 Porsche 911, red, front three-quarter"
width="1024" height="1024" loading="lazy"
/>| Header | Example | Meaning |
|---|---|---|
Cache-Control | public, max-age=3421 | Public caching is allowed for the remaining TTL, so CDNs and browsers serve repeats for free. |
ETag | "9f2a…c41d" | Same stable tag as the keyed endpoint. |
X-Image-Source | cache | Whether the underlying render was cached or freshly generated. |
Lifecycle and errors
403— the token is malformed, expired, or the key that minted it was revoked. Mint a new URL.410— the URL hit itsmax_usescap. Mint a new URL.502— rendering failed on first delivery. The creation credit is refunded; mint a new URL before retrying.413— the JSON body exceeded 64 KiB. Split the batch; each call takes up to 50 images.
Why billing happens at creation
Charging when the URL is minted makes cost predictable for agents (one call, one known number) and lets the delivery endpoint be cached publicly: nothing has to be metered on the hot path.