Generated straight into
your storage.

Name a destination on any request and the finished media lands in your own S3, R2, or Bunny storage — your bucket, your paths, your CDN URLs back in the response. No download-and-reupload step in your pipeline.

await mynth.image.generate({model: "auto",prompt: "obsidian queen, rim light",destination: "bunny-prod",});// url: "https://cdn.your-domain.com/images/img_si1Eywt….webp"

How it works

A destination is a named place your media goes: a provider, credentials, and a path template. Set it up once, then reference it by slug on any generation.

Create once

Pick a provider, give it an immutable slug like bunny-prod, credentials, and a path template. From the dashboard or the API.

POST /destinations

Name it on any request

One extra field on the generate payload. Everything else about the request stays exactly the same.

destination: "bunny-prod"

Delivered in the pipeline

The upload to your storage runs concurrently with Mynth's own — delivery adds no extra hop and no extra wait to the task.

concurrent upload

Your URL in the response

With a url_template set, the image's url is your CDN URL, built from the exact path the file landed on.

url: your domain

Providers

Three providers cover most of the internet's object storage — and the S3 provider takes a custom endpoint, so S3-compatible services work too.

Amazon S3

Any S3 bucket — or anything speaking the S3 API, with a custom endpoint and path-style addressing when you need it.

s3

Cloudflare R2

Account and bucket, with jurisdiction-pinned endpoints (EU, FedRAMP) handled for you. Zero egress on your side.

r2

Bunny Storage

A storage zone in any Bunny region — de, uk, ny, la, sg, se, br, jh, syd — fronted by your pull zone.

bunny

Paths & URLs

You decide where files land. The path template resolves per upload, the file extension is appended from the output format, and doubled slashes are cleaned up for you.

Image id

The Mynth image id — the same one on the task, so files trace back to their run.

{id}

Date parts

Upload date, zero-padded — for the year/month/day folder layouts CDNs like.

{YYYY} {MM} {DD}

Unique ids

A fresh identifier per file, in whichever flavor your system already keys on.

{uuid} {uuidv7} {ulid}

Your metadata

Any string field from the request's metadata object — put your own user id or project id in the path.

{meta.user_id}

URL template

Optional. The resolved path drops into {path} to build the public URL returned on the task — point it at your CDN domain.

https://cdn.you.com/{path}
template → file.webp appended

path_template

/avatars/{meta.user_id}/{YYYY}/{id}

lands on your bucket as

/avatars/usr_812/2026/img_si1EywtFZMvDArkcVSSsN759VFNbHtE_.webp

The fine print

Delivery to storage you don't control has to be predictable — these are the rules it follows, stated plainly.

Secrets stay sealed

Credentials go straight into an encrypted vault on creation. They're never returned by the API and never appear on a destination you read back.

write-only

Failures surface, never substitute

If delivery to your storage fails, the image's url is null and the task carries the error code. We never quietly hand back a Mynth URL where yours was asked for.

url: null on failure

Mynth copy as backstop

Every image is also stored on Mynth and exposed as mynth_url — so a destination outage never loses the generation itself.

mynth_url

Test before you rely on it

A dedicated endpoint pushes a test file through the real provider with your real credentials — verify the wiring before production traffic.

POST /destinations/:id/test

Slugs are immutable

The name you reference in requests never changes after creation, and a destination can't switch providers — no request breaks because config moved.

immutable