GPT Image 2.5 is live — OpenAI's newest image model, targeted edits that leave the rest of the frame alone
rreAPI Docs

Tasks

GET /api/v1/tasks/{id} reference — universal task polling for image, video, and audio generation.

Generation on reAPI is asynchronous. Every submission endpoint — /api/v1/images/generations, /api/v1/videos/generations, and any future /api/v1/audio/generations — returns a task id, and you poll GET /api/v1/tasks/{id} until the task reaches a terminal state.

This page is the canonical reference for the polling endpoint. The request shape, status values, error codes, polling cadence, and refund semantics are the same regardless of which submission endpoint produced the task; only the contents of output differ by media kind.

GET /api/v1/tasks/{id}

Retrieve the current state of a task.

Request

GET /api/v1/tasks/{id}
Authorization: Bearer rk_live_xxx

{id} is the id returned by the submitting POST. Polling does not consume credits.

For exact GPT Image token evidence, opt in without changing the legacy polling response used by existing clients:

GET /api/v1/tasks/{id}?include=billing
Authorization: Bearer rk_live_xxx

Prefer not to poll at all? Pass a webhook_url when you submit and reAPI POSTs this same response to you when the task finishes — see Webhooks. This endpoint stays the guaranteed path: if a webhook delivery fails, the result is still here, and ?include=webhook returns the delivery record so you can see what happened.

Response

200 OK — image task example:

{
  "id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
  "model": "gpt-image-2",
  "status": "completed",
  "created_at": 1735000000,
  "output": {
    "image_urls": [
      "https://cdn.reapi.ai/media/tasks/018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e/0.png",
      "https://cdn.reapi.ai/media/tasks/018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e/1.png"
    ]
  },
  "usage": { "credits": 56 },
  "error": null
}

200 OK — video task example:

{
  "id": "task_01k9s419324drezfbwnsvxyr6h",
  "model": "doubao-seedance-2.0",
  "status": "completed",
  "created_at": 1762853430,
  "output": {
    "video_urls": [
      "https://cdn.reapi.ai/media/tasks/01k9s419324drezfbwnsvxyr6h/0.mp4"
    ]
  },
  "usage": { "credits": 189 },
  "error": null
}

usage

Backward-compatible whole-credit settlement summary.

"usage": { "credits": 189 }

usage is always present and credits is always an integer, in every state, so a polling client can read usage.credits without guarding the access. This legacy wire type is unchanged for existing generated clients.

Stateusage.credits
processing0 — nothing settled yet
completedthe amount charged
failed0 — fully refunded (or the amount kept, if any)

0 appears in two different situations, so pair it with status: processing + 0 means the task has not been billed yet, while failed + 0 means it was billed and refunded.

This is the rounded-up settled summary, not the reservation. Submitting a request places a hold based on the parameters you sent. Once the task settles, the reservation is replaced by the final amount: excess reserve is returned, while an amount above the reserve is deducted from the remaining balance.

How far the two diverge is model-specific. The cases below are examples, not universal behaviour — check the model's own page for its billing table:

  • Seedance 2.5 with duration: -1 holds the 30-second ceiling and then settles against the video actually produced.
  • Wan 3.0 with duration: -1 is charged at the 30-second ceiling. The length the model picks does not bring it down, so pass an explicit duration when cost matters.
  • Reference-video jobs, on the models that accept them, bill input seconds plus output seconds, and some tiers bill a minimum window — a short clip can settle above its literal duration.

For legacy integer-priced models, read usage.credits instead of recomputing any of this client-side. Token-metered models additionally expose their settlement source under billing.

For gpt-image-2-official, polling with ?include=billing adds a top-level billing object with the exact image-token meters and settled amount. Without that query parameter, the response keeps the legacy field set exactly:

"usage": { "credits": 39 },
"billing": {
  "source": "openai_token_usage",
  "credits_exact": 38.966,
  "cost_usd": 0.038966,
  "text_input_tokens": 396,
  "image_input_tokens": 2482,
  "image_output_tokens": 571
}

The submitted request reserves the Playground/model-page estimate. A successful task replaces it with:

actual_usd =
  text_input_tokens  x $5 / 1,000,000
  + image_input_tokens  x $8 / 1,000,000
  + image_output_tokens x $30 / 1,000,000

actual_micro_usd =
  text_input_tokens x 5
  + image_input_tokens x 8
  + image_output_tokens x 30

final_micro_usd =
  ceil(actual_micro_usd x factor_basis_points / 10,000)

billing.cost_usd = final_micro_usd / 1,000,000
billing.credits_exact = final_micro_usd / 1,000
charged_micro_usd = final_micro_usd - shortfall_micro_usd
usage.credits = ceil(charged_micro_usd / 1,000)

The balance and public billing values retain final_micro_usd precision; the factor is rounded upward only once at that boundary. usage.credits remains the rounded-up whole-credit compatibility field; do not use it to reconcile token-metered tasks. Use billing.credits_exact or billing.cost_usd.

If a successful generation does not return all three trustworthy usage meters, the task still completes and the admission reservation becomes the final whole-credit charge. With ?include=billing, that fallback is explicit and never presented as exact:

"usage": { "credits": 56 },
"billing": {
  "source": "reservation_estimate",
  "credits_charged": 56,
  "cost_usd_charged": 0.056
}

Only source: "openai_token_usage" carries formula-derived exact token fields.

In the rare case that the actual amount exceeds both the reservation and the remaining balance, the successful task still completes and the balance is reduced to zero. reAPI records the unpaid remainder internally as a billing shortfall; billing.credits_exact and billing.cost_usd continue to report the full formula-derived actual amount, while usage.credits remains the rounded whole-credit summary of the amount actually collected.

Status values

StatusMeaning
processingSubmitted, provider is generating
completedDone — output populated
failederror populated; usage.credits shows whether the reservation was refunded or a post-generation charge was retained

Output shape

The shape of output depends on the media kind of the task:

Media kindFieldType
Imageimage_urlsstring[]
Videovideo_urlsstring[]
Audioaudio_urlsstring[]

Some video models add an extra last_frame_url (string) when the request opted into a return-last-frame capability.

URLs returned in output are rehosted to reAPI's CDN. If you need long-term archival, copy them to your own storage as soon as the task completes — bucket lifecycle policies are configured per-deployment and not guaranteed by this contract.

Errors

HTTPcodeWhen
40110001 – 10005Auth missing / invalid / revoked
40440001Task doesn't exist or belongs to another user
42950001Per-user request rate limit exceeded — retry after Retry-After seconds

Polling pattern

Recommended:

attempt 1: wait 2s
attempt 2: wait 2s
...
the worker keeps a task alive up to a wall-clock cap before it self-reports
an 80002 timeout: 1 hour for image and audio, 48 hours for video. Most tasks
finish far sooner (image/audio usually under a minute, video in minutes), so
size your client-side give-up to your own tolerance, not the cap.

The polling endpoint is cached for 5 seconds while a task is in-flight, so polling faster than every 2–3 seconds returns the same state and just consumes rate-limit budget. Video tasks routinely take several minutes; pace your polling accordingly.

Refund behavior

Provider failures, timeouts, and persistence failures are automatically refunded by the worker when the workflow ends. Missing token evidence after a successful GPT Image generation is not a task failure: the image is delivered and the reserved amount is charged. Any credit return happens atomically with the status flip, before a poll observes it, and re-polling never refunds twice.

Some model-specific post-generation safety policies can retain the generation charge even though the output is hidden and the task status is failed. Always read usage.credits: failed + 0 means fully refunded, while a positive value is the retained amount documented by that model.

A failed task surfaces the failure code under error:

{
  "id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
  "status": "failed",
  "output": null,
  "error": {
    "code": 80006,
    "message": "Request violates content policy"
  }
}

The code here is one of the 8xxxx workflow-execution codes — see Errors → 8xxxx.

Table of Contents