Docs API reference
Stories
A story is what a stage plays: chapters (scenes) in order, looping. A chapter can roll a template through a collection, play for a set time (two minutes of TV after the news), or play only at certain times of day. Put a story on a stage with PUT /stages/{id}/idle or POST /bookings.
Every call needs an API key in the Authorization header. New to the API? Start with
the API overview.
List stories
/stories authoringParameters
limitinteger queryPage size, 1–200.
1–200. Default
50cursorstring queryThe
next_cursorof the previous page.
Responses
- 200 A page of stories.
- 401 Missing or invalid API key.
- 403 The key lacks the scope, or the role is read-only.
Response fields (200)
itemsobject[] required5 fields in
itemsidstring requiredtitlestring requireddescriptionstringstatusstringcreated_atinteger or null
next_cursorstring or null requiredPass as
cursorfor the next page;nullon the last page.
curl "https://www.wunderframe.com/api/v1/stories?limit=50" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY"{
"items": [
{
"id": "sto_news_tv",
"title": "News and TV",
"description": "",
"status": "draft",
"created_at": 1789990000000
}
],
"next_cursor": null
}Error example
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key."
}
}Create a story
/stories authoringRequest body required
titlestring requireddescriptionstring
Responses
- 201 The story.
- 400 The request is invalid —
details.fieldnames the field when there is one. - 401 Missing or invalid API key.
- 403 The key lacks the scope, or the role is read-only.
Response fields (201)
idstring requiredtitlestring requireddescriptionstringstatusstringcreated_atinteger or null
curl -X POST "https://www.wunderframe.com/api/v1/stories" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "News and TV"
}'{
"id": "sto_news_tv",
"title": "News and TV",
"description": "",
"status": "draft",
"created_at": 1789990000000
}Error example
{
"error": {
"code": "invalid",
"message": "The request is invalid — `details.field` names the field when there is one."
}
}Get a story with its chapters
/stories/{id} authoringParameters
idstring required pathThe story id.
Responses
- 200 The story.
- 401 Missing or invalid API key.
- 403 The key lacks the scope, or the role is read-only.
- 404 Not found in this workspace.
Response fields (200)
idstring requiredtitlestring requireddescriptionstringstatusstringcreated_atinteger or nullchaptersobject[]5 fields in
chaptersidstring requiredindexinteger required0 = first.
scene_idstring requiredscene_titlestring or nullsettingsobject requiredOnly the given settings change.
play_for_ms: the chapter plays exactly this long — its last moment holds, or it is cut (not on a rolling chapter).shot_duration_ms: every moment’s hold.roll:{ collection_id, per_pass, order: { by: "added"|"field"|"collection", field, direction } }plays the template once per record, per_pass each round; for advertising addweight_field(share of voice),start_field/end_field(a date window, venue time),duration_field(seconds per record, 3–120) anddaypart_field(daypart names) — a roll for the same collection changes only the keys given.pick: a session slot.plays_during:{ daypart_ids, days }.fills_gaps,start_shot_id.detail:{ collection_id }— the chapter never plays in the loop; a visitor opens it by choosing a record of that collection (an agenda board row withopen_detail, or a row of a collection Live list withprops.open_detail), filled with that record. One per collection per story.8 fields in
settingsplay_for_msinteger or nullAt least 1000
shot_duration_msinteger or nullAt least 1000
start_shot_idstring or nullrollobject or nullA roll through a collection (ADR-0020, ADR-0057). Every
*_fieldnames a field of the records; null or "" = not used.11 fields in
rollcollection_idstringper_passinteger1–20. Default
5orderobject3 fields in
orderbystringOne of
added,field,collectionfieldstring or nulldirectionstringOne of
desc,asc
matchmap of stringinclude_stalebooleanDefault
falsemax_age_hnumber or nullweight_fieldstring or nullNumeric field: share of voice. Missing value = 1, 0 = paused, max 1000.
start_fieldstring or nullDate or datetime field: the record plays from then (venue time).
end_fieldstring or nullDate or datetime field: the record plays until then; a date alone = through that day.
duration_fieldstring or nullNumber field (or m:ss): seconds the record plays, clamped 3–120.
daypart_fieldstring or nullText field naming dayparts ("Morning, Evening"): the record plays only then.
pickobject or nullplays_duringobject or nullfills_gapsbooleandetailobject1 fields in
detailcollection_idstring required
curl "https://www.wunderframe.com/api/v1/stories/sto_news_tv" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY"{
"id": "sto_news_tv",
"title": "News and TV",
"description": "",
"status": "draft",
"created_at": 1789990000000,
"chapters": []
}Error example
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key."
}
}Add a chapter
/stories/{id}/chapters authoringCast a scene into the story (at the end, or at index) with optional settings — { roll: { collection_id, per_pass } } rolls a template; { play_for_ms: 120000 } plays it for two minutes.
Parameters
idstring required pathThe story id.
Request body required
scene_idstring requiredsettingsobjectOnly the given settings change.
play_for_ms: the chapter plays exactly this long — its last moment holds, or it is cut (not on a rolling chapter).shot_duration_ms: every moment’s hold.roll:{ collection_id, per_pass, order: { by: "added"|"field"|"collection", field, direction } }plays the template once per record, per_pass each round; for advertising addweight_field(share of voice),start_field/end_field(a date window, venue time),duration_field(seconds per record, 3–120) anddaypart_field(daypart names) — a roll for the same collection changes only the keys given.pick: a session slot.plays_during:{ daypart_ids, days }.fills_gaps,start_shot_id.detail:{ collection_id }— the chapter never plays in the loop; a visitor opens it by choosing a record of that collection (an agenda board row withopen_detail, or a row of a collection Live list withprops.open_detail), filled with that record. One per collection per story.8 fields in
settingsplay_for_msinteger or nullAt least 1000
shot_duration_msinteger or nullAt least 1000
start_shot_idstring or nullrollobject or nullA roll through a collection (ADR-0020, ADR-0057). Every
*_fieldnames a field of the records; null or "" = not used.11 fields in
rollcollection_idstringper_passinteger1–20. Default
5orderobject3 fields in
orderbystringOne of
added,field,collectionfieldstring or nulldirectionstringOne of
desc,asc
matchmap of stringinclude_stalebooleanDefault
falsemax_age_hnumber or nullweight_fieldstring or nullNumeric field: share of voice. Missing value = 1, 0 = paused, max 1000.
start_fieldstring or nullDate or datetime field: the record plays from then (venue time).
end_fieldstring or nullDate or datetime field: the record plays until then; a date alone = through that day.
duration_fieldstring or nullNumber field (or m:ss): seconds the record plays, clamped 3–120.
daypart_fieldstring or nullText field naming dayparts ("Morning, Evening"): the record plays only then.
pickobject or nullplays_duringobject or nullfills_gapsbooleandetailobject1 fields in
detailcollection_idstring required
indexinteger
Responses
- 201 The chapter.
- 400 The request is invalid —
details.fieldnames the field when there is one. - 401 Missing or invalid API key.
- 403 The key lacks the scope, or the role is read-only.
- 404 Not found in this workspace.
Response fields (201)
idstring requiredindexinteger required0 = first.
scene_idstring requiredscene_titlestring or nullsettingsobject requiredOnly the given settings change.
play_for_ms: the chapter plays exactly this long — its last moment holds, or it is cut (not on a rolling chapter).shot_duration_ms: every moment’s hold.roll:{ collection_id, per_pass, order: { by: "added"|"field"|"collection", field, direction } }plays the template once per record, per_pass each round; for advertising addweight_field(share of voice),start_field/end_field(a date window, venue time),duration_field(seconds per record, 3–120) anddaypart_field(daypart names) — a roll for the same collection changes only the keys given.pick: a session slot.plays_during:{ daypart_ids, days }.fills_gaps,start_shot_id.detail:{ collection_id }— the chapter never plays in the loop; a visitor opens it by choosing a record of that collection (an agenda board row withopen_detail, or a row of a collection Live list withprops.open_detail), filled with that record. One per collection per story.8 fields in
settingsplay_for_msinteger or nullAt least 1000
shot_duration_msinteger or nullAt least 1000
start_shot_idstring or nullrollobject or nullA roll through a collection (ADR-0020, ADR-0057). Every
*_fieldnames a field of the records; null or "" = not used.11 fields in
rollcollection_idstringper_passinteger1–20. Default
5orderobject3 fields in
orderbystringOne of
added,field,collectionfieldstring or nulldirectionstringOne of
desc,asc
matchmap of stringinclude_stalebooleanDefault
falsemax_age_hnumber or nullweight_fieldstring or nullNumeric field: share of voice. Missing value = 1, 0 = paused, max 1000.
start_fieldstring or nullDate or datetime field: the record plays from then (venue time).
end_fieldstring or nullDate or datetime field: the record plays until then; a date alone = through that day.
duration_fieldstring or nullNumber field (or m:ss): seconds the record plays, clamped 3–120.
daypart_fieldstring or nullText field naming dayparts ("Morning, Evening"): the record plays only then.
pickobject or nullplays_duringobject or nullfills_gapsbooleandetailobject1 fields in
detailcollection_idstring required
curl -X POST "https://www.wunderframe.com/api/v1/stories/sto_news_tv/chapters" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "scn_tv",
"settings": {
"play_for_ms": 120000
}
}'{
"id": "plc_tv",
"index": 1,
"scene_id": "scn_tv",
"scene_title": "TV",
"settings": {
"play_for_ms": 120000,
"shot_duration_ms": null,
"start_shot_id": null,
"roll": null,
"pick": null,
"plays_during": null,
"fills_gaps": false
}
}Error example
{
"error": {
"code": "invalid",
"message": "The request is invalid — `details.field` names the field when there is one."
}
}Change a chapter
/chapters/{id} authoringIts settings (only the given ones change) and its place in the story.
Parameters
idstring required pathThe chapter id.
Request body required
settingsobjectOnly the given settings change.
play_for_ms: the chapter plays exactly this long — its last moment holds, or it is cut (not on a rolling chapter).shot_duration_ms: every moment’s hold.roll:{ collection_id, per_pass, order: { by: "added"|"field"|"collection", field, direction } }plays the template once per record, per_pass each round; for advertising addweight_field(share of voice),start_field/end_field(a date window, venue time),duration_field(seconds per record, 3–120) anddaypart_field(daypart names) — a roll for the same collection changes only the keys given.pick: a session slot.plays_during:{ daypart_ids, days }.fills_gaps,start_shot_id.detail:{ collection_id }— the chapter never plays in the loop; a visitor opens it by choosing a record of that collection (an agenda board row withopen_detail, or a row of a collection Live list withprops.open_detail), filled with that record. One per collection per story.8 fields in
settingsplay_for_msinteger or nullAt least 1000
shot_duration_msinteger or nullAt least 1000
start_shot_idstring or nullrollobject or nullA roll through a collection (ADR-0020, ADR-0057). Every
*_fieldnames a field of the records; null or "" = not used.11 fields in
rollcollection_idstringper_passinteger1–20. Default
5orderobject3 fields in
orderbystringOne of
added,field,collectionfieldstring or nulldirectionstringOne of
desc,asc
matchmap of stringinclude_stalebooleanDefault
falsemax_age_hnumber or nullweight_fieldstring or nullNumeric field: share of voice. Missing value = 1, 0 = paused, max 1000.
start_fieldstring or nullDate or datetime field: the record plays from then (venue time).
end_fieldstring or nullDate or datetime field: the record plays until then; a date alone = through that day.
duration_fieldstring or nullNumber field (or m:ss): seconds the record plays, clamped 3–120.
daypart_fieldstring or nullText field naming dayparts ("Morning, Evening"): the record plays only then.
pickobject or nullplays_duringobject or nullfills_gapsbooleandetailobject1 fields in
detailcollection_idstring required
indexinteger
Responses
- 200 The chapter.
- 400 The request is invalid —
details.fieldnames the field when there is one. - 401 Missing or invalid API key.
- 403 The key lacks the scope, or the role is read-only.
- 404 Not found in this workspace.
Response fields (200)
idstring requiredindexinteger required0 = first.
scene_idstring requiredscene_titlestring or nullsettingsobject requiredOnly the given settings change.
play_for_ms: the chapter plays exactly this long — its last moment holds, or it is cut (not on a rolling chapter).shot_duration_ms: every moment’s hold.roll:{ collection_id, per_pass, order: { by: "added"|"field"|"collection", field, direction } }plays the template once per record, per_pass each round; for advertising addweight_field(share of voice),start_field/end_field(a date window, venue time),duration_field(seconds per record, 3–120) anddaypart_field(daypart names) — a roll for the same collection changes only the keys given.pick: a session slot.plays_during:{ daypart_ids, days }.fills_gaps,start_shot_id.detail:{ collection_id }— the chapter never plays in the loop; a visitor opens it by choosing a record of that collection (an agenda board row withopen_detail, or a row of a collection Live list withprops.open_detail), filled with that record. One per collection per story.8 fields in
settingsplay_for_msinteger or nullAt least 1000
shot_duration_msinteger or nullAt least 1000
start_shot_idstring or nullrollobject or nullA roll through a collection (ADR-0020, ADR-0057). Every
*_fieldnames a field of the records; null or "" = not used.11 fields in
rollcollection_idstringper_passinteger1–20. Default
5orderobject3 fields in
orderbystringOne of
added,field,collectionfieldstring or nulldirectionstringOne of
desc,asc
matchmap of stringinclude_stalebooleanDefault
falsemax_age_hnumber or nullweight_fieldstring or nullNumeric field: share of voice. Missing value = 1, 0 = paused, max 1000.
start_fieldstring or nullDate or datetime field: the record plays from then (venue time).
end_fieldstring or nullDate or datetime field: the record plays until then; a date alone = through that day.
duration_fieldstring or nullNumber field (or m:ss): seconds the record plays, clamped 3–120.
daypart_fieldstring or nullText field naming dayparts ("Morning, Evening"): the record plays only then.
pickobject or nullplays_duringobject or nullfills_gapsbooleandetailobject1 fields in
detailcollection_idstring required
curl -X PATCH "https://www.wunderframe.com/api/v1/chapters/plc_tv" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"play_for_ms": 180000
},
"index": 1
}'{
"id": "plc_tv",
"index": 1,
"scene_id": "scn_tv",
"scene_title": "TV",
"settings": {
"play_for_ms": 120000,
"shot_duration_ms": null,
"start_shot_id": null,
"roll": null,
"pick": null,
"plays_during": null,
"fills_gaps": false
}
}Error example
{
"error": {
"code": "invalid",
"message": "The request is invalid — `details.field` names the field when there is one."
}
}Remove a chapter
/chapters/{id} authoringThe scene stays in the library.
Parameters
idstring required pathThe chapter id.
Responses
- 204 Removed.
- 401 Missing or invalid API key.
- 403 The key lacks the scope, or the role is read-only.
- 404 Not found in this workspace.
curl -X DELETE "https://www.wunderframe.com/api/v1/chapters/plc_tv" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY"204 — no body.
Error example
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key."
}
}