Presenters

Docs API reference

Presenters

The people who present live on your screens. Import them from a speaker portal or CRM with your own ref, keep them in sync with an idempotent upsert, and upload their photos.

List presenters

GET /presenters presenters

Sorted by name. Filter by your ref, search q in name, title and organization, or fetch only changes with updated_since.

Parameters

  • ref string query

    Only the presenter with this ref.

  • q string query

    Search name, title and organization.

  • updated_since integer query

    Epoch ms: only presenters changed since.

  • limit integer query

    Page size, 1–200.

    1–200. Default 50

  • cursor string query

    The next_cursor of the previous page.

Responses

  • 200 A page of presenters.
  • 400 The request is invalid — details.field names 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)
  • items object[] required
    11 fields in items
    • id string required read-only
    • ref string or null

      Your own id for the presenter. Unique in the workspace.

      Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

    • name string required

      Up to 200 characters

    • title string

      Shown in the lower third.

      Up to 200 characters

    • organization string

      Up to 200 characters

    • email string (email)
    • bio string

      Up to 4000 characters

    • photo_asset_id string or null read-only
    • photo_url string or null read-only

      A signed URL, valid for about an hour.

    • created_at integer read-only
    • updated_at integer read-only
  • next_cursor string or null required

    Pass as cursor for the next page; null on the last page.

curl "https://www.wunderframe.com/api/v1/presenters?limit=50" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY"
Response 200
{
  "items": [
    {
      "id": "wkFRBzMq6POZ_qYJHvgQf",
      "ref": "speakerportal/1234",
      "name": "Ada Lovelace",
      "title": "Head of Research",
      "organization": "Analytical Engines Ltd",
      "email": "ada@example.com",
      "bio": "Writes the first programs.",
      "photo_url": "https://…signed…",
      "photo_asset_id": "a1b2c3",
      "created_at": 1789372800000,
      "updated_at": 1789372800000
    }
  ],
  "next_cursor": null
}
Error example
Response 400
{
  "error": {
    "code": "invalid",
    "message": "The request is invalid — `details.field` names the field when there is one."
  }
}

Create a presenter

POST /presenters presenters

Prefer the upsert by ref for syncs: calling it twice is safe.

Request body required

  • ref string or null

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string

    Required when creating.

    Up to 200 characters

  • title string

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_url string (uri)

    A public https image (JPEG, PNG, WebP, GIF, ≤ 10 MB) that Wunderframe fetches and stores as the photo. Sending the same URL again later does not fetch it again, so repeated imports are cheap; use a new URL (or the photo endpoint) to replace the image.

Responses

  • 201 Created.
  • 400 The request is invalid — details.field names the field when there is one.
  • 401 Missing or invalid API key.
  • 403 The key lacks the scope, or the role is read-only.
  • 409 Conflicts with the current state.
  • 413 Too large.
  • 415 Unsupported media type.
Response fields (201)
  • id string required read-only
  • ref string or null

    Your own id for the presenter. Unique in the workspace.

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string required

    Up to 200 characters

  • title string

    Shown in the lower third.

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_asset_id string or null read-only
  • photo_url string or null read-only

    A signed URL, valid for about an hour.

  • created_at integer read-only
  • updated_at integer read-only
curl -X POST "https://www.wunderframe.com/api/v1/presenters" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "ref": "speakerportal/1234",
  "name": "Ada Lovelace",
  "title": "Head of Research",
  "organization": "Analytical Engines Ltd",
  "email": "ada@example.com",
  "bio": "Writes the first programs.",
  "photo_url": "https://example.com/photos/ada.jpg"
}'
Response 201
{
  "id": "wkFRBzMq6POZ_qYJHvgQf",
  "ref": "speakerportal/1234",
  "name": "Ada Lovelace",
  "title": "Head of Research",
  "organization": "Analytical Engines Ltd",
  "email": "ada@example.com",
  "bio": "Writes the first programs.",
  "photo_url": "https://…signed…",
  "photo_asset_id": "a1b2c3",
  "created_at": 1789372800000,
  "updated_at": 1789372800000
}
Error example
Response 400
{
  "error": {
    "code": "invalid",
    "message": "The request is invalid — `details.field` names the field when there is one."
  }
}

Get a presenter

GET /presenters/{id} presenters

Parameters

  • id string required path

    The presenter id.

Responses

  • 200 The presenter.
  • 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)
  • id string required read-only
  • ref string or null

    Your own id for the presenter. Unique in the workspace.

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string required

    Up to 200 characters

  • title string

    Shown in the lower third.

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_asset_id string or null read-only
  • photo_url string or null read-only

    A signed URL, valid for about an hour.

  • created_at integer read-only
  • updated_at integer read-only
curl "https://www.wunderframe.com/api/v1/presenters/wkFRBzMq6POZ_qYJHvgQf" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY"
Response 200
{
  "id": "wkFRBzMq6POZ_qYJHvgQf",
  "ref": "speakerportal/1234",
  "name": "Ada Lovelace",
  "title": "Head of Research",
  "organization": "Analytical Engines Ltd",
  "email": "ada@example.com",
  "bio": "Writes the first programs.",
  "photo_url": "https://…signed…",
  "photo_asset_id": "a1b2c3",
  "created_at": 1789372800000,
  "updated_at": 1789372800000
}
Error example
Response 401
{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid API key."
  }
}

Update a presenter

PATCH /presenters/{id} presenters

Only the fields you send change. Send photo_url to replace the photo.

Parameters

  • id string required path

    The presenter id.

Request body required

  • ref string or null

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string

    Required when creating.

    Up to 200 characters

  • title string

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_url string (uri)

    A public https image (JPEG, PNG, WebP, GIF, ≤ 10 MB) that Wunderframe fetches and stores as the photo. Sending the same URL again later does not fetch it again, so repeated imports are cheap; use a new URL (or the photo endpoint) to replace the image.

Responses

  • 200 Updated.
  • 400 The request is invalid — details.field names 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.
  • 409 Conflicts with the current state.
Response fields (200)
  • id string required read-only
  • ref string or null

    Your own id for the presenter. Unique in the workspace.

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string required

    Up to 200 characters

  • title string

    Shown in the lower third.

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_asset_id string or null read-only
  • photo_url string or null read-only

    A signed URL, valid for about an hour.

  • created_at integer read-only
  • updated_at integer read-only
curl -X PATCH "https://www.wunderframe.com/api/v1/presenters/wkFRBzMq6POZ_qYJHvgQf" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Chief Scientist"
}'
Response 200
{
  "id": "wkFRBzMq6POZ_qYJHvgQf",
  "ref": "speakerportal/1234",
  "name": "Ada Lovelace",
  "title": "Head of Research",
  "organization": "Analytical Engines Ltd",
  "email": "ada@example.com",
  "bio": "Writes the first programs.",
  "photo_url": "https://…signed…",
  "photo_asset_id": "a1b2c3",
  "created_at": 1789372800000,
  "updated_at": 1789372800000
}
Error example
Response 400
{
  "error": {
    "code": "invalid",
    "message": "The request is invalid — `details.field` names the field when there is one."
  }
}

Delete a presenter

DELETE /presenters/{id} presenters

Refused with 409 conflict while the presenter is in a session that has not finished. Their photo stays in the media library.

Parameters

  • id string required path

    The presenter id.

Responses

  • 204 Deleted.
  • 401 Missing or invalid API key.
  • 403 The key lacks the scope, or the role is read-only.
  • 404 Not found in this workspace.
  • 409 Conflicts with the current state.
curl -X DELETE "https://www.wunderframe.com/api/v1/presenters/wkFRBzMq6POZ_qYJHvgQf" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY"

204 — no body.

Error example
Response 401
{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid API key."
  }
}

Get a presenter by your ref

GET /presenters/by-ref/{ref} presenters

Parameters

  • ref string required path

    Your ref. May contain slashes: /presenters/by-ref/speakerportal/1234.

Responses

  • 200 The presenter.
  • 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)
  • id string required read-only
  • ref string or null

    Your own id for the presenter. Unique in the workspace.

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string required

    Up to 200 characters

  • title string

    Shown in the lower third.

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_asset_id string or null read-only
  • photo_url string or null read-only

    A signed URL, valid for about an hour.

  • created_at integer read-only
  • updated_at integer read-only
curl "https://www.wunderframe.com/api/v1/presenters/by-ref/speakerportal/1234" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY"
Response 200
{
  "id": "wkFRBzMq6POZ_qYJHvgQf",
  "ref": "speakerportal/1234",
  "name": "Ada Lovelace",
  "title": "Head of Research",
  "organization": "Analytical Engines Ltd",
  "email": "ada@example.com",
  "bio": "Writes the first programs.",
  "photo_url": "https://…signed…",
  "photo_asset_id": "a1b2c3",
  "created_at": 1789372800000,
  "updated_at": 1789372800000
}
Error example
Response 401
{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid API key."
  }
}

Create or update a presenter by your ref

PUT /presenters/by-ref/{ref} presenters

The sync endpoint. Creates the presenter when no presenter has this ref (then name is required), otherwise updates the fields you send. Safe to repeat.

Parameters

  • ref string required path

    Your ref. May contain slashes.

Request body required

  • ref string or null

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string

    Required when creating.

    Up to 200 characters

  • title string

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_url string (uri)

    A public https image (JPEG, PNG, WebP, GIF, ≤ 10 MB) that Wunderframe fetches and stores as the photo. Sending the same URL again later does not fetch it again, so repeated imports are cheap; use a new URL (or the photo endpoint) to replace the image.

Responses

  • 200 Updated.
  • 201 Created.
  • 400 The request is invalid — details.field names the field when there is one.
  • 401 Missing or invalid API key.
  • 403 The key lacks the scope, or the role is read-only.
  • 409 Conflicts with the current state.
  • 413 Too large.
  • 415 Unsupported media type.
Response fields (200)
  • id string required read-only
  • ref string or null

    Your own id for the presenter. Unique in the workspace.

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string required

    Up to 200 characters

  • title string

    Shown in the lower third.

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_asset_id string or null read-only
  • photo_url string or null read-only

    A signed URL, valid for about an hour.

  • created_at integer read-only
  • updated_at integer read-only
Response fields (201)
  • id string required read-only
  • ref string or null

    Your own id for the presenter. Unique in the workspace.

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string required

    Up to 200 characters

  • title string

    Shown in the lower third.

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_asset_id string or null read-only
  • photo_url string or null read-only

    A signed URL, valid for about an hour.

  • created_at integer read-only
  • updated_at integer read-only
curl -X PUT "https://www.wunderframe.com/api/v1/presenters/by-ref/speakerportal/1234" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Ada Lovelace",
  "title": "Head of Research",
  "organization": "Analytical Engines Ltd"
}'
Response 200
{
  "id": "wkFRBzMq6POZ_qYJHvgQf",
  "ref": "speakerportal/1234",
  "name": "Ada Lovelace",
  "title": "Head of Research",
  "organization": "Analytical Engines Ltd",
  "email": "ada@example.com",
  "bio": "Writes the first programs.",
  "photo_url": "https://…signed…",
  "photo_asset_id": "a1b2c3",
  "created_at": 1789372800000,
  "updated_at": 1789372800000
}
Error example
Response 400
{
  "error": {
    "code": "invalid",
    "message": "The request is invalid — `details.field` names the field when there is one."
  }
}

Import presenters in bulk

POST /presenters/import presenters

Up to 500 upserts by ref in one call. Every item needs a ref. A row that fails is reported in failed and never stops the others.

Request body required

  • items object[] required

    Up to 500 items

    7 fields in items
    • ref string or null

      Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

    • name string

      Required when creating.

      Up to 200 characters

    • title string

      Up to 200 characters

    • organization string

      Up to 200 characters

    • email string (email)
    • bio string

      Up to 4000 characters

    • photo_url string (uri)

      A public https image (JPEG, PNG, WebP, GIF, ≤ 10 MB) that Wunderframe fetches and stores as the photo. Sending the same URL again later does not fetch it again, so repeated imports are cheap; use a new URL (or the photo endpoint) to replace the image.

Responses

  • 200 What happened to each row.
  • 400 The request is invalid — details.field names 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)
  • created integer required
  • updated integer required
  • failed object[] required
    3 fields in failed
    • index integer
    • ref string or null
    • error object
      2 fields in error
      • code string
      • message string
curl -X POST "https://www.wunderframe.com/api/v1/presenters/import" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "ref": "speakerportal/1234",
      "name": "Ada Lovelace",
      "organization": "Analytical Engines Ltd"
    },
    {
      "ref": "speakerportal/1235",
      "name": "Grace Hopper",
      "title": "Rear Admiral",
      "photo_url": "https://example.com/grace.jpg"
    }
  ]
}'
Response 200
{
  "created": 41,
  "updated": 3,
  "failed": [
    {
      "index": 7,
      "ref": null,
      "error": {
        "code": "invalid",
        "message": "\"ref\" is required for import."
      }
    }
  ]
}
Error example
Response 400
{
  "error": {
    "code": "invalid",
    "message": "The request is invalid — `details.field` names the field when there is one."
  }
}

Upload a presenter photo

PUT /presenters/{id}/photo presenters

Send the image itself as the body with Content-Type: image/jpeg (or png, webp, gif; ≤ 10 MB) and optionally X-Filename, or JSON { "url": "https://…" } for Wunderframe to fetch. The photo is stored in the media library.

Parameters

  • id string required path

    The presenter id.

Request body required

JSON, or the file itself as the body with one of image/jpeg, image/png, image/webp as its Content-Type.

  • url string (uri) required

Responses

  • 200 The presenter with its new photo.
  • 400 The request is invalid — details.field names 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.
  • 413 Too large.
  • 415 Unsupported media type.
Response fields (200)
  • id string required read-only
  • ref string or null

    Your own id for the presenter. Unique in the workspace.

    Pattern ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$

  • name string required

    Up to 200 characters

  • title string

    Shown in the lower third.

    Up to 200 characters

  • organization string

    Up to 200 characters

  • email string (email)
  • bio string

    Up to 4000 characters

  • photo_asset_id string or null read-only
  • photo_url string or null read-only

    A signed URL, valid for about an hour.

  • created_at integer read-only
  • updated_at integer read-only
curl -X PUT "https://www.wunderframe.com/api/v1/presenters/wkFRBzMq6POZ_qYJHvgQf/photo" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/photos/ada.jpg"
}'
Response 200
{
  "id": "wkFRBzMq6POZ_qYJHvgQf",
  "ref": "speakerportal/1234",
  "name": "Ada Lovelace",
  "title": "Head of Research",
  "organization": "Analytical Engines Ltd",
  "email": "ada@example.com",
  "bio": "Writes the first programs.",
  "photo_url": "https://…signed…",
  "photo_asset_id": "a1b2c3",
  "created_at": 1789372800000,
  "updated_at": 1789372800000
}
Error example
Response 400
{
  "error": {
    "code": "invalid",
    "message": "The request is invalid — `details.field` names the field when there is one."
  }
}

Remove a presenter photo

DELETE /presenters/{id}/photo presenters

Parameters

  • id string required path

    The presenter id.

Responses

  • 204 Removed. The image stays in the media library.
  • 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/presenters/wkFRBzMq6POZ_qYJHvgQf/photo" \
  -H "Authorization: Bearer $WUNDERFRAME_API_KEY"

204 — no body.

Error example
Response 401
{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid API key."
  }
}