Product2 min read

The model name is the address

Every model, one URL scheme, and no model field in any request body.

There is no model field in an Auray request body. The model is the path.

POST https://queue.auray.run/auray-ai/krea-2-turbo/text-to-image
                             └────┬────┘ └──────┬──────┘ └───┬───┘
                              namespace       model        task

The namespace first, then the model, and usually the task — two to six segments in all. No v1 in front of the model, no per-model client library.

#What this buys

A name you read anywhere is immediately callable. Someone mentions an address in a changelog entry or a support thread; you can curl it without looking anything up first. The name and the URL are the same string, so there is nothing to translate.

A request body is only parameters. Nothing in it identifies what is running. Switching models means changing the URL — not rewriting the payload around a different model value and hoping the rest of the fields still apply.

The shape does not change between addresses. Whatever you learn calling one applies to the next: the same auth, the same job lifecycle, the same webhook signature, the same error vocabulary. 401 addresses across 16 namespaces, reached identically.

#The version we did not add

The usual next step is a version of our own on every address — …/text-to-image/v2 — and it is a trap worth naming.

A version of ours in the path means every caller has to decide when to move, which means the old version has to keep running, which means a catalogue that only grows. It also means the interesting question — is this address still the right one? — is answered by a number rather than by the service.

A vendor's own version is a different thing. veed/lipsync/v2 is that vendor's name for its second lip-sync model, and it sits beside veed/lipsync the way two models with different names do: each is an address, each is described on its own. We add no version of ours on top of either.

Instead, an address we retire answers:

410 Gone
{
  "error": "model_deprecated",
  "successor": "auray-ai/krea-2-turbo/text-to-image",
  "deprecated_at": "2026-09-10T00:00:00Z",
  "docs": "https://auray.ai/docs/api/errors#model_deprecated",
  "request_id": "54b4754a-3e17-4629-adb1-7d3f067e97d3"
}

An integration written against something withdrawn fails loudly with the fix in the body. The failure mode we were avoiding is the other one: a model quietly changing underneath an address that still returns 200, so the output drifts and nothing anywhere says why.

#Finding out what an address accepts

Every address publishes its own parameter list — types, defaults, bounds — so you can validate a request before spending anything on it:

curl "https://api.auray.ai/v1/models/auray-ai/krea-2-turbo/text-to-image/openapi.json" \
  -H "Authorization: Bearer $AURAY_API_KEY"

353 of the 401 addresses have a published shape today. The rest are named and reserved: the address exists, and it refuses rather than guessing at your body.

#The one thing to be careful about

GET /v1/models reports which addresses are generating right now, and that answer changes as capacity switches on. It is the only current answer — do not cache it for long, and do not treat "described" as "available". The catalogue tells you which is which on every request.

More in Addresses.

Filed under Product on All posts

Build on what you just read

Open the app to try the generators, or read the API reference and call them from your own code — one key, one balance of credits.