On this page
Returns a page of approved creatives of your organisation, each as a full data record. Use it to sync creatives into your marketing systems, incrementally with updated_since.
GET /api/delivery/v1/creativesScope: creatives:export
Description
Returns creatives of your organisation with status approved or pushed, ordered by updated_at ascending and then by ID. Records never contain a signed media URL. Successful responses are wrapped in the {code, message, data, server_time} envelope; errors use the same envelope without data, except 429 and 400 unsupported_version, which use the flat format. See Creatives.
Request parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Authorization |
header | string | Yes | Bearer <API key> for a key with the creatives:export scope. |
updated_since |
query | integer | No | Unix epoch seconds (up to 11 digits). Returns only records whose exact update time is strictly after this second (>, not >=). |
cursor |
query | string | No | The next_cursor from the previous page. Opaque; pass it back unchanged. |
limit |
query | integer | No | Records per page, 1 to 100. Default 50. |
Wandura-Version |
header | string | No | Optional. A dated API version (YYYY-MM-DD) to use for this request instead of the version pinned to your API key. Unknown or retired values answer 400 with error_code unsupported_version. |
You can combine updated_since and cursor. Keep the same updated_since on every page of one sync. Because updated_at in each record is rounded down to the second, passing the largest updated_at you received usually returns the last records again; overwrite them by creative_id.
Request example
curl -s "https://www.wandura.ai/api/delivery/v1/creatives?updated_since=1790600000&limit=2" \
-H "Authorization: Bearer $WANDURA_API_KEY"Response
200 OK
| Field | Type | Description |
|---|---|---|
code |
integer | 0. |
message |
string | "ok". |
data.items |
array | The creative records on this page. |
data.next_cursor |
string or null | Pass it as cursor to get the next page. null on the last page. |
server_time |
integer | Server time in Unix epoch seconds. |
links |
object | Ready-made absolute URLs of this page — follow links.next instead of building the next-page URL. |
links.self |
string | This request. |
links.next |
string or null | The next page, or null on the last page. |
The creative record
The same record is returned by Get a creative. final.file_url is the creative's public share link: no API key needed, durable, and revocable in the portal. Each open redirects to a fresh download link valid for 15 minutes, so you can hand it to Meta's video upload. It is null until final.ready is true, and null when an admin of your organisation revoked the link. See Downloading the final file; to download with your API key instead, use Download a creative's final file.
| Field | Type | Description |
|---|---|---|
links |
object | Ready-made absolute URL of this creative's own endpoint (an API link, not a media URL). |
schema_version |
integer | Record schema version. Currently 1. Additive fields do not change it. |
creative_id |
string (UUID) | Stable creative ID. |
creative_code |
string or null | Immutable human-readable code. Treat it as opaque. |
name |
string | Creative name. |
status |
string | approved, or pushed once delivered. |
created_at |
integer | Creation time, Unix seconds. |
approved_at |
integer or null | Approval time, Unix seconds. |
updated_at |
integer | Last update, Unix seconds, rounded down. |
org.slug |
string | Your organisation's slug. |
created_by |
object or null | The user who created the creative. null when the creator is unknown, for example a creative made by the system or by a user whose account was deleted. |
created_by.email |
string | Email of the creator. |
created_by.name |
string or null | Display name of the creator. null when the creator has not set a name. |
film |
object or null | The film the creative is cut from. |
film.code |
string or null | Film code. |
film.title |
string or null | Film title. |
film.language |
string or null | Film language. |
film.genres |
array of strings | Film genres. Can be empty. |
episodes |
array of integers | Episode numbers used, without duplicates. |
placement |
string or null | reels_9x16, feed_4x5 or square_1x1. |
aspect |
string or null | 9:16, 4:5 or 1:1, matching placement. |
duration_ms |
integer | Total length of the film clips used, in milliseconds. Can be shorter than the final video, because scenes lists only clips taken from film episodes. |
scenes |
array | The film clips used, in order. |
scenes[].episode_no |
integer or null | Episode the clip comes from. |
scenes[].start_ms |
integer | Clip start in the episode, milliseconds. |
scenes[].end_ms |
integer | Clip end in the episode, milliseconds. |
scenes[].duration_ms |
integer | Clip length, milliseconds. |
scenes[].action |
string or null | Action label of the scene, for example reveal, argue, slap, kiss, embrace, cry, kneel, walk_away or violence. null when the scene has no notable action. New labels may be added. |
scenes[].line |
string or null | The spoken line or standout line of the scene. |
hook |
object or null | action and line of the first scene. null when there are no scenes. |
formula |
object or null | The formula the creative was built with. |
formula.name |
string | Formula name. |
rights.ends_at |
integer or null | Last day of your export rights for the film, as Unix seconds at 00:00 UTC of that day. Your rights include that whole day: stop using the creative after that UTC day ends, that is at ends_at + 86400. null when Wandura has no end date on record for your export rights. |
lineage.parent_creative_id |
string (UUID) or null | The creative this one was derived from. |
final.ready |
boolean | Whether the final render exists. A creative in status pushed has one. |
final.file_url |
string or null | Public, durable download link (no API key needed) — revocable in the portal; each open redirects to a fresh 15-minute download link. Safe to hand to Meta's video upload. Format https://www.wandura.ai/api/c/{token}.mp4; every open re-checks that the creative is still approved and your export rights for the film are active (410 otherwise). The file is the clean final, with your company's brand mark if your org has one. null until ready is true, and null when an admin of your organisation revoked the link: ask your admin, or create a new share link in the portal. Anyone holding the link can download the file, so treat it like a password. To download with your API key instead, call GET /api/delivery/v1/creatives/{id}/file. |
final.target |
object | Target render spec: width, height, fps, codec. Today it is the same for every creative (1080 × 1920, 30 fps, h264) and does not follow placement, so do not derive the frame size from it. |
scenes lists only clips taken from film episodes. Other elements of the creative are not listed, so duration_ms can be shorter than the final video.
Response example
{
"code": 0,
"message": "ok",
"data": {
"items": [
{
"schema_version": 1,
"creative_id": "5e1b7c3a-2d4f-4a6b-9c8d-0e1f2a3b4c5d",
"creative_code": "ACV001-FILM0001-EP1-2-F1-TEAM",
"name": "Heiress returns - wedding hook",
"status": "approved",
"created_at": 1790500000,
"approved_at": 1790590000,
"updated_at": 1790610000,
"org": { "slug": "your-org" },
"created_by": { "email": "maker@example.com", "name": "Alex Tran" },
"film": { "code": "FILM0001", "title": "The Heiress Returns", "language": "en", "genres": ["romance", "revenge"] },
"episodes": [1, 2],
"placement": "reels_9x16",
"aspect": "9:16",
"duration_ms": 21500,
"scenes": [
{
"episode_no": 1,
"start_ms": 12000,
"end_ms": 19500,
"duration_ms": 7500,
"action": "reveal",
"line": "You threw me out. Now watch me take it all back."
},
{ "episode_no": 2, "start_ms": 40000, "end_ms": 54000, "duration_ms": 14000, "action": null, "line": null }
],
"hook": { "action": "reveal", "line": "You threw me out. Now watch me take it all back." },
"formula": { "name": "Cliffhanger opener" },
"rights": { "ends_at": 1798675200 },
"lineage": { "parent_creative_id": null },
"final": {
"ready": true,
"file_url": "https://www.wandura.ai/api/c/Q3vh0xAbCdEfGhIjKlMnOpQrStUvWx9f.mp4",
"target": { "width": 1080, "height": 1920, "fps": 30, "codec": "h264" }
}
}
],
"next_cursor": "eyJwIjoiZXhhbXBsZS1jdXJzb3IifQ"
},
"server_time": 1790679032
}Response headers
| Header | Responses | Description |
|---|---|---|
Wandura-API-Status |
all | API status. beta today, on every response, success or error. |
Wandura-Version |
all | The dated API version (YYYY-MM-DD) this response was produced in: the version pinned to your API key, or the one you sent in the Wandura-Version request header. Keys created before dated versions existed use 2026-10-02. |
Wandura-Request-Id |
all | An opaque id for this request (req_ followed by 26 characters). Every response carries it, errors included, and error bodies repeat it as request_id. Log it, and quote it when you contact Wandura about a request: it finds the exact request in our logs. Do not parse it. |
Deprecation |
200 | Present only when this endpoint, or the dated version serving this response, is deprecated (RFC 9745): @<unix seconds> of the deprecation date. Log it in your monitoring. |
Sunset |
200 | Present only when a deprecated endpoint or dated version has a date when it stops working (RFC 8594), as an HTTP date. |
Link |
200 | Present with Deprecation: <https://docs.wandura.ai/…>; rel="deprecation" (and rel="sunset") pointing to the page that explains what to use instead. |
Cache-Control |
all | Always no-store. Do not cache these responses in shared caches. |
Retry-After |
429 | Seconds to wait before retrying. Sent with 429 and with retryable 503 responses. |
X-RateLimit-Limit |
429 | Requests (for playback, tickets) allowed per window for this endpoint group and your organisation. |
X-RateLimit-Window |
429 | Window length in seconds. |
Errors
| Status | code |
When |
|---|---|---|
| 400 | none | The Wandura-Version header, or the version pinned to your key, is unknown or retired. The body adds supported_versions and latest_version (and upgrade_to when your pin was retired). |
| 401 | 4010 | The Authorization: Bearer header is missing. |
| 401 | 4011 | The key is unknown or revoked. |
| 403 | 4030 | The key lacks the creatives:export scope. |
| 403 | 4031 | Your organisation's access is suspended. |
| 422 | 4220 | limit is not an integer between 1 and 100. |
| 422 | 4221 | updated_since is not epoch seconds. |
| 422 | 4222 | cursor is not valid. |
| 429 | none | Rate limit reached. Flat body with error_code rate_limited, not the envelope. |
| 503 | 5030 | The feed is temporarily unavailable. Retry with backoff. |
| 503 | 5031 | Wandura could not verify the API key in time. The key is not wrong: retry with backoff. |
See Errors for what to do in each case.
Updated 19 Oct 2026 · Change history (9)