Guide · Delivery URLsOne URL shape, a small transform grammar, and an optional signature.
Every ready file is served on the project's delivery host. The path is a transform chain, the /f/ marker and the file slug. The first request for a chain renders it; after that it is served from cache. In JavaScript, imageUrl() from @img2site/sdk-client and <Img2siteImage> build these URLs for you.
URL shape
https://{project}.i2scd.net/{transform_chain}/f/{file_slug}
https://{project}.i2scd.net/originals/f/{file_slug}
https://{project}.i2scd.net/download/raw/f/{file_slug}
[?exp=…&kid=…&sig=… signed URLs only]Operations are lowercase name/value segments separated by slashes, in any order; each may appear once. The /f/ segment is required. Only GET and HEAD are served; OPTIONS answers CORS for any origin.
Examples
# The sanitized image at its own size
https://my-store.i2scd.net/originals/f/hero
# 1024 px wide, height keeps the aspect ratio
https://my-store.i2scd.net/resize/1024x/f/hero
# 800x600 with attention-based cropping, WebP at quality 80
https://my-store.i2scd.net/resize/800x600/smart/format/webp/quality/80/f/hero
# Crop a box first, then resize
https://my-store.i2scd.net/crop/100,50,1200,800/resize/600x/f/hero
# A resolution preset defined on the project, with a named watermark preset
https://my-store.i2scd.net/preset:large/watermark:wm_brand/f/hero
Transform operations
Transform operations of the delivery URL grammar| Operation | Syntax | Notes |
|---|
resize | resize/{w}x{h} | 1 to 8192 px per side, within the output limits below. Leave one side empty (1024x, x600) to keep the aspect ratio. Upscaling is allowed up to 16 times the source area (any source may go up to 2048x2048). |
fit mode | resize/{w}x{h}/{mode} or resize/{w}x{h}/fit/{mode} | fill (default; crop is an alias) covers the box and crops the centre, smart covers it and crops around the most interesting region, fit fits inside the box. |
crop | crop/{x},{y},{w},{h} | A pixel box taken from the source before resizing. |
format | format/{webp|avif|jpeg|png} | Output format (jpg is accepted for jpeg). Default: the stored format (PNG for an SVG, whose crop and resize coordinates are in its raster grid: the file's width and height). |
quality | quality/{1-100} | Encoder quality for jpeg, webp and avif; mapped to compression level for png. |
watermark | watermark or watermark:{preset} | Composite a watermark preset. See below for how it combines with the project default. |
preset | preset:{name} | Expands to one of the project's resolution presets. At most one per URL. |
A chain that does not parse, names an unknown preset, or repeats an operation answers 404 not_found. Output never carries embedded metadata and is at most 8192 px on each side.
Output limits: a rendered image is at most 16.7 megapixels (4096x4096) in webp, jpeg and png, and at most 12 megapixels (for example 4000x3000) in avif; a larger request is scaled down to fit, keeping its aspect ratio. Upscaling is limited to 16 times the source area (or 2048x2048, whichever is larger): a chain that enlarges more answers 404 not_found without rendering. Very large avif and webp sources get smaller renders, and avif sources above about 15 megapixels, like lossless webp sources above about 22.5 to 25 megapixels, cannot be transformed at all (404 not_found). For the full-size file, use /originals/f/{slug}.
Watermarks
When the project has a default watermark preset, it is applied to every derived image, with or without a watermark operation. watermark:{preset} uses that preset instead; a preset id the project does not have falls back to the default, so a made-up name cannot remove it. Originals and raw downloads are never watermarked.
Every preset of a project can be selected on public URLs, so a faint or zero-opacity preset weakens the default. Restrict public chains with allowed_transform_chains if that matters (see project setup).
Originals and raw downloads
/originals/f/{slug} serves the sanitized image as stored, without transforms or metadata.
/download/raw/f/{slug} serves the same image with its saved EXIF, ICC and XMP metadata restored, as an attachment and never cached. It works only when the project enables raw_download_enabled; otherwise it answers 404. It is not the byte-identical upload.
Public and protected delivery
On a public project anyone with a URL can fetch it. On a protected project every URL must carry exp, kid and sig, minted by your server with POST /v1/projects/{slug}/signed-url or img2site.signedUrl(); unsigned requests answer 403 signature_required. See signing.
No query strings
An unsigned URL with any query string answers 404 not_found, and a signed URL may carry only exp, kid and sig. Do not add cache-busting parameters: re-uploading a slug changes what its URLs serve on its own.
Caching
- Public images:
Cache-Control: public, max-age=300, s-maxage=31536000. Browsers revalidate after five minutes; the CDN keeps images up to a year and is purged whenever something changes what a URL serves (re-upload, delete, block, project settings, watermark presets). Purges are queued, not instant, and delivery servers cache file and project lookups for up to 30 seconds, so a deleted, blocked or re-uploaded file can keep serving briefly. - Signed URLs are cached by the CDN until they expire; browsers revalidate them.
- Raw downloads and errors are never cached.
- Responses carry
ETag and X-Img2site-Revision (the file's revision), so you can tell which upload a response came from.
Delivery errors
Delivery error responses, in the order they are checked| Status | Code | Cause |
|---|
| 404 | not_found | Malformed path, unexpected query string, or unknown host. |
| 403 | project_suspended | The project is suspended. |
| 403 | quota_exceeded | The organization has no credits left. See usage and billing. |
| 404 | not_found | The file does not exist or was deleted. |
| 403 | file_blocked | Moderation blocked the file. Applies to every path, including originals and raw downloads. |
| 403 | invalid_signature, signature_expired, unknown_kid | The signature does not verify, has expired, or names a key that no longer exists. |
| 403 | signature_required | A protected project received an unsigned URL. |
| 403 | transform_chain_not_allowed | An unsigned derived URL uses a chain outside allowed_transform_chains. |
| 404 | not_found | Raw downloads are disabled, or the chain fails the grammar or names an unknown preset. |
| 415 | raw_unavailable | The file's format cannot take its metadata back for a raw download. |
| 503 | busy | Rendering is saturated; retry after the Retry-After seconds. |
| 504 | render_timeout | The render took too long; retry. |
Refused requests are never billed.