Docs

Get started

Quickstart

From no account to a finished render.

Every request here is drawn in cURL, both client libraries and the other languages a docs site usually carries — with the MCP call an agent makes wherever a tool does the same thing. Pick yours once and every example in these docs follows it. Every response below is one the API actually sent, request ids and all.

#1. Get a key

Open app.auray.ai, then Account → API Keys → New key.

Two things are decided at mint time and matter later:

  • Scopes. A key may only reach the products you tick. A key with photo:write cannot submit a video job — it is refused before anything is charged.
  • Ceiling. An optional cap on what this key may spend in one calendar month, counted in UTC and starting again on the 1st. Useful for a key that lives in something you do not fully control.

The key is shown once. It starts with auray_sk_ and is 71 characters long.

#2. Submit a job

The model's name is the URL. Nothing else identifies it. prompt, aspect_ratio and resolution are the three fields this address requires; its contract lists the rest.

Submit an image job
curl -X POST https://queue.auray.run/auray-ai/krea-2-turbo/text-to-image \
  -H "Authorization: Bearer $AURAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: docs-mtpb1vnh" \
  -d '{
    "prompt": "a brass orrery on a walnut desk, morning light from a window to the left, shallow depth of field",
    "aspect_ratio": "16:9",
    "resolution": 1024
  }'

You get the job back immediately, before anything has rendered. The charge is already made — it is reversed if the job fails — and three URLs tell you where to go next:

200 OK
{
  "status": "IN_QUEUE",
  "request_id": "photo_docs-mtpb1vnh",
  "job_id": "photo_docs-mtpb1vnh",
  "queue_position": 0,
  "logs": [],
  "metrics": {},
  "product": "photo",
  "provider_job_id": "f30c5f765770468097181c2bcb31fd4d",
  "model": "auray-ai/krea-2-turbo/text-to-image",
  "engine": "Krea 2 Turbo",
  "attribution": "Powered by Krea 2",
  "credits_charged": 4,
  "credits_remaining": 38807,
  "expected_seconds": 39,
  "replayed": false,
  "status_url": "https://queue.auray.run/auray-ai/krea-2-turbo/text-to-image/requests/photo_docs-mtpb1vnh/status",
  "response_url": "https://queue.auray.run/auray-ai/krea-2-turbo/text-to-image/requests/photo_docs-mtpb1vnh",
  "cancel_url": "https://queue.auray.run/auray-ai/krea-2-turbo/text-to-image/requests/photo_docs-mtpb1vnh/cancel"
}

request_id is the job's name everywhere else: photo_ plus the idempotency key you sent — the same string as job_id beside it, which is what every host calls a job, and id on GET /v1/jobs/{id}. model is the address you submitted to; engine is the service's own name for what ran. Send the same key again and you get this same job back with "replayed": true and nothing charged — see Idempotency.

#3. Collect the result

Poll status_url until it says COMPLETED, then fetch response_url:

Poll
curl "https://queue.auray.run/auray-ai/krea-2-turbo/text-to-image/requests/photo_docs-mtpb1vnh/status?logs=1" \
  -H "Authorization: Bearer $AURAY_API_KEY"
200 OK, a few seconds later
{
  "status": "COMPLETED",
  "request_id": "photo_docs-mtpb1vnh",
  "job_id": "photo_docs-mtpb1vnh",
  "logs": [],
  "metrics": { "inference_time": 2.32 },
  "error": null,
  "error_type": null,
  "status_url": "…/requests/photo_docs-mtpb1vnh/status",
  "response_url": "…/requests/photo_docs-mtpb1vnh",
  "cancel_url": "…/requests/photo_docs-mtpb1vnh/cancel"
}

The result names what was made; the signed URL to download it comes from the assets route on api.auray.ai, because signing it costs no credits but counts the files' size against the egress rate-limit bucket, and a status poll does not. The link can be fetched again until it expires; asking for it again counts the size again:

Signed URLs, good for fifteen minutes
curl https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets \
  -H "Authorization: Bearer $AURAY_API_KEY"
200 OK
{
  "id": "photo_docs-mtpb1vnh",
  "object": "asset_list",
  "product": "photo",
  "expires_at": "2026-09-06T04:37:47.701Z",
  "megabytes_charged": 2,
  "assets": [
    {
      "index": 0,
      "kind": "image",
      "filename": "0.png",
      "content_type": "image/png",
      "bytes": 1065131,
      "url": "https://…/0.png?…"
    }
  ],
  "request_id": "bc0cab07-ee23-40ea-b977-8b9cce022e9c"
}

Asset URLs expire. Download what you want to keep.

For anything longer than a few seconds, prefer a webhook — you get a signed POST the moment the job settles, and you never hold a connection open. See Webhooks.

#4. Check what it cost

Balance and the key's own spend
curl https://api.auray.ai/v1/me \
  -H "Authorization: Bearer $AURAY_API_KEY"
200 OK
{
  "object": "account",
  "id": "86e97633-…",
  "plan": "ultimate",
  "credits": { "balance": 38807, "plan_credits": 3807, "purchased_credits": 35000, "granted_credits": 0, "monthly_allowance": 5000, "period": "2026-09" },
  "key": {
    "id": "55oy2jFo5cmq",
    "scopes": ["jobs:read", "assets:read", "image:write", "video:write", "audio:write", "3d:write", "text:write"],
    "credit_ceiling": 500,
    "credits_spent_period": 332
  },
  "request_id": "961dd3b6-59b4-4e26-bb8b-e4c28f1cbf96"
}

A refused job is not charged. A job that fails after it starts is refunded automatically — you do not file anything. Every other case — stopped, stalled, partly withheld — is in the settlement table.

#Next

Start typing to search every page of the documentation.

Up arrow Down arrow to moveEnter to openEscape to close