The raw surface is a faithful passthrough — request and response bodies are shape-identical (with task identifiers Aurous-native), and the Ark SDK works by swapping base_url + key. But a passthrough that runs on a multi-tenant platform has a handful of documented differences. Here is the complete list, so nothing surprises you in production.
Model identifiers
You address models by model id or alias (seedance-2.0, seedance-2.0-fast, seedance-2.0-mini, or the full provider slug). Endpoint-style ids are not accepted — passing one, or any unknown model, returns 404 model_not_found. See Create a task → model.
Rate & concurrency limits
Limits are per team, sized to protect shared capacity:
- Request rate: roughly 30 requests / minute sustained across
POST and DELETE (a burst bucket sits above that). Over the limit → too_many_requests (429).
- Active-task cap: at most 5 concurrent non-terminal raw tasks (queued or running) per team. Over the cap →
concurrency_limit_exceeded (429).
The request-rate 429 (too_many_requests) and any 503 carry a Retry-After header — sleep that many seconds and retry. The active-task 429 (concurrency_limit_exceeded) is count-based, so it carries no Retry-After: retry once an in-flight task reaches a terminal state, or cancel a queued/pending task to free a slot. See Rate limits for headers and how buckets refill. Need a higher tier? Email support@aurous-labs.com.
Callbacks
Your callback_url is accepted and relayed through Aurous — you do not have to poll. The relayed callback differs from a bare provider callback in a few honest ways:
-
Body shape. Aurous POSTs a JSON object
{ "event", "data" }, where event is video.completed, video.failed, or video.cancelled, and data is the normalized task object — the same shape Retrieve a task returns. The task id is data.id (the Aurous vid_… value); on this unsigned relay there is no separate task_id field — the id already is the vid_… handle (the signed-webhook path is different — see Signed webhooks for raw tasks). A task that reaches the terminal expired status arrives as a video.failed callback (there is no video.expired event) — the provider status is preserved verbatim on data.status, so read that (or the authoritative retrieve) to tell expired apart from a plain failed. Both charge 0.
-
Unsigned. The relayed POST carries only
Content-Type: application/json — there is no Aurous-Webhook-Signature and no other Aurous-* headers. This is not the signed registered-webhook-endpoints envelope, so do not attempt signature verification on it.
-
At-least-once, best-effort. Delivery is attempted up to 3 times (5-second timeout per attempt), and the upstream may itself re-post — so you can receive duplicates. De-duplicate on
data.id. Aurous never bills from the posted body; the charge always settles from a trusted server-side read-back.
Because the callback is unsigned and arrives over the public internet, treat it
as a hint to fetch authoritative status, not as trusted data. On each
callback, read the record with
GET /v1/contents/generations/tasks/{id}
— that GET is the source of truth for status and result.
Signed webhooks for raw tasks
Raw tasks also fire your signed registered webhook endpoints (created with POST /v1/webhook_endpoints) — separately from, and in addition to, the inline callback_url relay above. The events are video.completed, video.failed, and video.cancelled, each carrying the Aurous-Webhook-Signature header and verified exactly like every other Aurous webhook (see Webhooks for the signature mechanics — they are identical for raw and platform events).
Correlate terminal webhooks via the data.id field (a vid_… task identifier).
Safety identifier
Your safety_identifier is namespaced per team before it reaches the provider — this keeps per-end-user abuse attribution scoped to your team and prevents collisions across tenants. It is echoed back unchanged on every retrieve and list item, so you always read your own original value. See Create a task → parameters.
List & retention supersets
- No 7-day list cutoff. The native list only returns the last 7 days; the Aurous list has no such window and is served from your own team-scoped records (never proxied).
- Records outlive the provider purge. A task stays retrievable on Aurous past the provider’s 7-day history purge. The catch:
video_url / last_frame_url inside a record still expire 24 hours after generation (a provider constraint), so an old record remains readable but its media links go stale. Download what you keep.
- Output URLs are Aurous-proxied.
video_url and last_frame_url point at Aurous streaming endpoints (…/v1/contents/generations/tasks/{id}/output[/last_frame]?token=…), not an upstream object store — the bytes stream through Aurous, so the underlying storage host is never exposed. They stay valid ~24 h after generation.
Idempotency
The raw POST accepts an Idempotency-Key header (a bonus over the native API) — reuse the same key to make a create safe to retry. A replay returns the original result and carries the same Aurous-Credits-Held header, so you are never double-held or double-charged. A same-key retry with a different body returns idempotency_key_in_use (409). See Idempotency.
Error envelope
Aurous checks some conditions before your request reaches the provider (auth, scope, balance, rate, request shape, model resolution). Those are returned with Aurous snake_case codes inside the standard envelope:
This is a strict superset of the provider’s { "error": { "code", "message" } }: same two keys, plus type, param, doc_url, and request_id.
If your integration switches on the provider’s PascalCase codes
(InvalidParameter, MissingParameter, …), you will meet these snake_case
codes first — they fire before the provider is called. Match on
error.code and handle both vocabularies.
The three error classes in full:
- Aurous pre-dispatch gates — snake_case codes, superset envelope (the shape above).
- Provider request-faults — things only the provider can catch (
InvalidParameter, MissingParameter, the *SensitiveContentDetected family). Returned with the provider’s exact status and body. This is the raw contract.
- Account / infrastructure faults — remapped to
provider_unavailable (503, Retry-After: 30) or, for unrecognized upstream errors, provider_unknown_error (502).
See Create a task → errors for the per-code table and the Errors catalog for everything else.
Reference-file budget
A multimodal-reference request accepts up to 12 reference files: 9 images + 3 videos (each 2–15 s, ≤15 s total) + up to 3 audio clips (≤15 s total, never alone). Details in Create a task → generation modes.