Guides

Getting results

Wait for a generation, read its status, and save the file before the link dies.

Read as Markdown

A submit answers when the job is accepted, not done. You wait on it, then fetch a short-lived link.

Wait for it

GET /generations/{id}/wait blocks up to 20 seconds. It answers the moment the job ends. Still going? It returns still_running: true. Call again right away.

const BASE = "https://app.riffads.com/api/v1";
const headers = { Authorization: `Bearer ${process.env.RIFFADS_API_KEY}` };

async function waitFor(generationId: string, maxAgeSeconds = 1800) {
  for (;;) {
    const res = await fetch(`${BASE}/generations/${generationId}/wait`, { headers });
    const body = await res.json();
    if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
    if (!body.still_running) return body.generation;
    if (body.age_seconds > maxAgeSeconds) {
      throw new Error(`${generationId} still running after ${body.age_seconds}s`);
    }
  }
}
  • Branch on still_running, not status. It can end before status looks final.
  • A timeout is a normal 200, never 408 or 504.
  • Log age_seconds. It tells stuck from slow.

Statuses

StatusMeansDone?
queuedAccepted, not startedNo
renderingWorkingNo
post_processingSaving the outputNo
completedEvery output deliveredYes
failedDid not deliver. Read error.code and error.messageYes

There is no canceled status. A canceled job reads failed. More: statuses and ids.

Variants

Sent variants: 3? The submit returns a batch_group_id (bg_). Watching one id is not enough. Wait on one sibling, then read GET /batches/{id}. Batch status is running, completed, failed or partial.

Every output sits in generation.outputs[]:

FieldNotes
indexStable position. Name files after it
kindimage, video or audio
urlSigned link, or null until the job is completed and settled
width, heightPixels, or null
  • Links live 600 seconds (output_urls_expire_in_seconds).
  • There is no refresh endpoint. Every read signs new links. Expired? Read the generation again.
  • A link is a credential. Anyone holding it gets the file. Don't store it, log it or queue it.
  • Compare outputs_delivered to outputs_expected, not the array length.
  • Text capabilities (AI Writer, Transcribe) return no file.

Download

Terminal
BASE=https://app.riffads.com/api/v1
GEN=gen_0193c8f0a1b24e7f9d3c5a6b7e8f0033

curl -s "$BASE/generations/$GEN" -H "Authorization: Bearer $RIFFADS_API_KEY" \
  | jq -r '.generation.outputs[] | select(.url != null) | [.index, .url] | @tsv' \
  | while IFS=$'\t' read -r index url; do
      curl -sS --fail -o "$GEN-$index" "$url"
    done

A 403 on download usually means the link expired

Don't retry the same URL. Read the generation again for a fresh link, then fetch.

Fetch each link right after the read that signed it. Name saved files from generation_id, index and kind, not file_name. The download has no Content-Disposition, so browsers play it instead of saving it.

Webhooks

There are none. No webhook_url, no callback, no stream. Sending a callback field is a 400. Use the wait loop.

Keep your generation_id. There is no list endpoint, so it is your only way back to the file.

On this page