Skip to main content

Base URL

Everything, the API and the CDN, is served from one host:
The dashboard lives at https://app.openinary.dev, and is not an API.

Authentication

Send your API key on every request, either header works:
Keys are created in the dashboard (Settings → API keys), shown once, and pinned to a single bucket. Every request a key makes reads and writes that bucket, so you never pass a bucket ID to these endpoints, it’s carried by the key. See Create an API key.
API keys are server-side credentials. The only endpoint meant to be called from a browser is POST /upload, and only with a presigned signature, never with a key. Every other endpoint’s CORS policy is pinned to the dashboard origin, so a browser on your own domain can’t call them even if you tried, call them from your backend.

Endpoints

Delivery

Public, cached at the edge, no authentication. Omit the transformation segment to serve the file as stored.
string
required
Your bucket’s ID. It’s the /b/…/ segment of the url returned by POST /upload, and visible on any asset in the dashboard.
string
Comma-separated parameters, e.g. w_400,h_400,c_fill,f_webp. Identical syntax to self-hosted, see Image transformations and Video transformations.
string
required
Storage path of the file, e.g. products/photo.jpg.
The first request for a given URL runs the transformation and caches the result; later requests are served from cache. Cached deliveries count as CDN requests only. An image request that misses the cache also counts as one image transformation. Video transformations are queued, see Video processing.

Upload

multipart/form-data.
file
required
The file to upload. Repeat the field to send several in one request.
string
Destination folder, e.g. products/2026. Defaults to the bucket root. Ignored when a signature is present, the signature carries its own folder.
string
A presigned token from POST /upload/sign. Use this instead of an API key for browser uploads.
Response
Accepted types: JPEG, PNG, WebP, AVIF, GIF, HEIC/HEIF, PSD, MP4, MOV, WebM. SVG is rejected. HEIC/HEIF is converted to JPEG on upload, so the returned path may end in .jpg. A name that already exists is de-duplicated (photo (1).jpg), always trust the returned path over the one you sent.
The self-hosted transformations field (prewarming variants at upload time) is not supported on Cloud. It’s ignored, and variants are generated on the first request instead.

Presigned uploads

Mints a short-lived token so a browser can upload without an API key. Call it from your backend only.
string
Folder the upload is scoped to. Derive it from the authenticated user, never from the browser.
number
default:"300"
Lifetime in seconds, clamped to 1–3600. Keep it short, 60–300 is plenty.
Response
The token names the account, bucket, and folder it was minted for, so it can’t be replayed against another bucket or folder. See File Uploader for the full flow.

Storage

Body: { "name": "new-name.jpg" }, a bare name, no slashes. Works on files and folders. Returns { "success": true, "path": "products/new-name.jpg" }.
Body: { "destination": "archive/2025" }. An empty or missing body moves the item to the bucket root. Works on files and folders.
No body. The copy is named photo copy.jpg, de-duplicated if that already exists. Files only.
Deletes the original and its cached transform variants. Deleting a folder deletes everything under it. Storage usage is credited back.
Cached figures. POST /storage/stats/recalculate recomputes them from storage; POST /storage/cache/clear empties the bucket’s transform cache (204), after which variants are regenerated on demand.
Authenticated download of the untransformed file, with Range support. Public delivery goes through /b/{bucketId}/t/… instead.
Paths are URL-encoded in the request and compared as stored, so products/Marée.jpg becomes /storage/products/Mar%C3%A9e.jpg.

Video processing

A video transformation is queued rather than run inline. The first request for a transformed video returns 202 with a JSON body while it encodes.
The transformation segment matters: jobs are tracked per parameter set, so ask about the exact URL you requested.
string
One of pending · running · completed · error · not_found.
number
0 to 100.
GET /queue/events is a Server-Sent Events stream of the same job updates, for when polling is the wrong shape.
A video URL carrying no parameters is never transcoded, it streams the stored file (with range requests, so seeking works) and costs no processing minutes.

Errors

A 402 tells you which allowance ran out:
feature is one of storage_mb · image_transformations · video_processing_seconds · cdn_requests. Over the transformation quota, already-cached assets keep being served, only new work is refused. See Plans and limits.

Rate limits

Both answer 429. They exist to stop abuse, not to shape normal traffic, if you expect to run against them, get in touch before you do.

Not available on Cloud

These self-hosted endpoints have no Cloud equivalent today:
  • /authenticated/s--{sig}/… signed delivery URLs
  • /api-keys/*, keys are managed in the dashboard
  • /queue/stats, /queue/worker/stats, /queue/jobs, job retry/cancel
  • /invalidate/{path}, use POST /storage/cache/clear, or delete the asset
  • /download-folder, /download-zip
  • /health