Docs API reference
Event sync
For an event system that owns the program — Maravilla Studio’s Event Suite, or your own: send the whole event (rooms, speakers, sessions, tracks, translations) and Wunderframe makes or updates the agenda records, presenters, rooms, live sessions and shows, idempotently by your keys. Set the workspace brand from the event’s brand kit.
Every call needs an API key in the Authorization header. New to the API? Start with
the API overview.
Apply an event
/events/apply authoringThe event’s whole program for one day (ref without a slash; one ref per day of a multi-day event). Rooms, speakers and sessions are addressed by your keys ([A-Za-z0-9_-], up to 64), so a second call with the same keys updates and a session that is gone keeps its record (see notes). Sessions take optional track, track_color (#RRGGBB), studio_path and extra — translated columns <field>_<de|en|fr|it> written into the agenda record. language: de, en, fr or it. dry_run: true writes nothing and returns what would change. Needs authoring, data, presenters, sessions and shows.
Request body required
eventobject requiredThe EventPlan (see the description).
dry_runbooleanDefault
falseoriginstringOne of
studio,api
Responses
- 200 What was (or would be) made.
- 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 (200)
dry_runboolean requiredcountsobject required3 fields in
countscreateintegerupdateintegerkeepinteger
stepsobject[] required6 fields in
stepskindstringrefstringtitlestringactionstringOne of
create,update,keepnotestringidstring
clashesobject[]3 fields in
clashesroomstringastringbstring
notesstring[]stagesobject[]4 fields in
stageskeystringnamestringidstring or nullplayer_urlstring or null
curl -X POST "https://www.wunderframe.com/api/v1/events/apply" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event": {
"ref": "st-0123456789abcdef",
"title": "Digital Forum",
"date": "2026-11-05",
"time_zone": "Europe/Zurich",
"language": "de",
"rooms": [
{
"key": "a1b2c3d4e5f60718",
"name": "Saal A",
"label": "EG"
}
],
"speakers": [
{
"key": "9f8e7d6c5b4a3210",
"name": "Ada Lovelace",
"title": "Head of Research",
"organization": "Analytical Engines Ltd",
"photo_url": "https://example.com/ada.jpg"
}
],
"sessions": [
{
"key": "0f1e2d3c4b5a6978",
"title": "Keynote",
"room": "all",
"start": "09:00",
"end": "09:45",
"kind": "plenary",
"speakers": [
"9f8e7d6c5b4a3210"
],
"track": "Digital",
"track_color": "#1fb6ff",
"takeaway": "Where AI meets the venue",
"studio_path": "/events/digital-forum/agenda/keynote",
"extra": {
"title_fr": "Discours d’ouverture",
"title_en": "Keynote"
}
}
]
},
"dry_run": true,
"origin": "studio"
}'{
"dry_run": true,
"counts": {
"create": 9,
"update": 0,
"keep": 0
},
"steps": [
{
"kind": "record",
"ref": "st-0123456789abcdef/agenda/0f1e2d3c4b5a6978",
"title": "Keynote",
"action": "create"
}
],
"clashes": [],
"notes": [],
"stages": []
}Error example
{
"error": {
"code": "invalid",
"message": "The request is invalid — `details.field` names the field when there is one."
}
}Set the brand
/brand brandThe workspace brand guest pages and screens share. primary_color (or accent_color) becomes the accent, with the words on it picked for contrast; logo_url (public https) is fetched once as the logo for light backgrounds. What is not sent stays.
Request body required
namestringUp to 200 characters
primary_colorstringPattern
^#[0-9a-fA-F]{3,6}$accent_colorstringPattern
^#[0-9a-fA-F]{3,6}$logo_urlstring (uri)
Responses
- 200 The brand as saved, and contrast warnings.
- 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 (200)
brandobject4 fields in
brandcolorsmap of stringfontsobject2 fields in
fontsheadingstringbodystring
logo_asset_idstring or nulllogo_on_dark_asset_idstring or null
warningsstring[]
curl -X PUT "https://www.wunderframe.com/api/v1/brand" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Digital Forum",
"primary_color": "#e4007c",
"accent_color": "#1fb6ff",
"logo_url": "https://example.com/logo.png"
}'{
"brand": {
"colors": {
"background": "#0b1020",
"surface": "#151b33",
"text": "#ffffff",
"muted": "#a3a9c2",
"accent": "#e4007c",
"accent_text": "#ffffff"
},
"fonts": {
"heading": "outfit",
"body": "outfit"
},
"logo_asset_id": "ast_1",
"logo_on_dark_asset_id": null
},
"warnings": [
"string"
]
}Error example
{
"error": {
"code": "invalid",
"message": "The request is invalid — `details.field` names the field when there is one."
}
}Exchange a connect code
/connect/token noneAfter a workspace owner approved your site at /connect/studio?redirect_uri=…&state=…&code_challenge=… (PKCE S256), exchange the one-minute code for an API key. No API key needed: the code and its verifier are the credential.
Request body required
codestring requiredcode_verifierstring requiredredirect_uristring (uri) required
Responses
- 200 The key, shown once.
- 400 The request is invalid —
details.fieldnames the field when there is one.
Response fields (200)
api_keystring requiredShown once:
wfi.<id>.<secret>, with the connector’s scopes.workspace_idstring requiredworkspace_namestring required
curl -X POST "https://www.wunderframe.com/api/v1/connect/token" \
-H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "wfc_…",
"code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
"redirect_uri": "https://studio.example.com/settings/wunderframe"
}'{
"api_key": "wfi.0123456789abcdef.…",
"workspace_id": "ws_team_1a2b3c",
"workspace_name": "Digital Forum"
}Error example
{
"error": {
"code": "invalid",
"message": "The request is invalid — `details.field` names the field when there is one."
}
}