# Bulk draft session operations
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/bulk-draft-session-operations
/api-reference/openapi.yaml post /v1/event/{eventId}/agenda-drafts/{draftId}/sessions/bulk
Batch create, update, or delete session placements in a draft. Requires the `write:events` scope.
# Commit an agenda draft
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/commit-an-agenda-draft
/api-reference/openapi.yaml post /v1/event/{eventId}/agenda-drafts/{draftId}/commit
Apply all changes in the draft to the live event schedule. Requires the `write:events` scope.
# Create a draft session
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/create-a-draft-session
/api-reference/openapi.yaml post /v1/event/{eventId}/agenda-drafts/{draftId}/sessions/create
Place a session in an agenda draft. Requires the `write:events` scope.
# Create a persona
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/create-a-persona
/api-reference/openapi.yaml post /v1/event/{eventId}/personas/create
Create an attendee persona for schedule evaluation. Requires the `write:events` scope.
# Create an agenda draft
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/create-an-agenda-draft
/api-reference/openapi.yaml post /v1/event/{eventId}/agenda-drafts/create
Create a new agenda draft workspace. Requires the `write:events` scope.
# Create an event rule
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/create-an-event-rule
/api-reference/openapi.yaml post /v1/event/{eventId}/rules/create
Create a scheduling constraint. Requires the `write:events` scope.
# Delete a persona
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/delete-a-persona
/api-reference/openapi.yaml delete /v1/event/{eventId}/personas/{personaId}
Delete a persona. Requires the `write:events` scope.
# Delete an agenda draft
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/delete-an-agenda-draft
/api-reference/openapi.yaml delete /v1/event/{eventId}/agenda-drafts/{draftId}
Delete an agenda draft. Requires the `write:events` scope.
# Delete an event rule
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/delete-an-event-rule
/api-reference/openapi.yaml delete /v1/event/{eventId}/rules/{ruleId}
Delete a scheduling rule. Requires the `write:events` scope.
# Get a persona
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/get-a-persona
/api-reference/openapi.yaml get /v1/event/{eventId}/personas/{personaId}
Retrieve a single persona by ID.
# Get an agenda draft
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/get-an-agenda-draft
/api-reference/openapi.yaml get /v1/event/{eventId}/agenda-drafts/{draftId}
Retrieve a single agenda draft by ID.
# Get an event rule
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/get-an-event-rule
/api-reference/openapi.yaml get /v1/event/{eventId}/rules/{ruleId}
Retrieve a single event rule by ID.
# List agenda drafts
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/list-agenda-drafts
/api-reference/openapi.yaml get /v1/event/{eventId}/agenda-drafts
Returns all agenda drafts for an event.
# List draft sessions
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/list-draft-sessions
/api-reference/openapi.yaml get /v1/event/{eventId}/agenda-drafts/{draftId}/sessions
List session placements within an agenda draft.
# List event rules
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/list-event-rules
/api-reference/openapi.yaml get /v1/event/{eventId}/rules
Returns all scheduling rules for an event.
# List personas
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/list-personas
/api-reference/openapi.yaml get /v1/event/{eventId}/personas
Returns all evaluation personas for an event.
# Preview draft changes
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/preview-draft-changes
/api-reference/openapi.yaml get /v1/event/{eventId}/agenda-drafts/{draftId}/changes
Preview the pending changes in a draft before committing them to the live schedule.
# Remove a draft session
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/remove-a-draft-session
/api-reference/openapi.yaml delete /v1/event/{eventId}/agenda-drafts/{draftId}/sessions/{draftSessionId}
Remove a session from an agenda draft. Requires the `write:events` scope.
# Update a draft session
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/update-a-draft-session
/api-reference/openapi.yaml put /v1/event/{eventId}/agenda-drafts/{draftId}/sessions/{draftSessionId}
Move or update a session placement in a draft. Requires the `write:events` scope.
# Update a persona
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/update-a-persona
/api-reference/openapi.yaml put /v1/event/{eventId}/personas/{personaId}
Update a persona. Requires the `write:events` scope.
# Update an agenda draft
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/update-an-agenda-draft
/api-reference/openapi.yaml put /v1/event/{eventId}/agenda-drafts/{draftId}
Update an agenda draft. Requires the `write:events` scope.
# Update an event rule
Source: https://apidocs.sessionboard.com/api-reference/agenda-planning/update-an-event-rule
/api-reference/openapi.yaml put /v1/event/{eventId}/rules/{ruleId}
Update a scheduling rule. Requires the `write:events` scope.
# Bulk contact operations
Source: https://apidocs.sessionboard.com/api-reference/contact-writes/bulk-contact-operations
/api-reference/openapi.yaml post /v1/event/{eventId}/contacts/bulk
Create, update, or delete multiple contacts in a single request (max 100 operations). Requires the `write:contacts` scope.
# Create a contact
Source: https://apidocs.sessionboard.com/api-reference/contact-writes/create-a-contact
/api-reference/openapi.yaml post /v1/event/{eventId}/contacts/create
Create a new contact in an event. Requires the `write:contacts` scope. Subject to rate limiting (100 req/15min) and daily write quota (10,000/day per token).
# Restore a deleted contact
Source: https://apidocs.sessionboard.com/api-reference/contact-writes/restore-a-deleted-contact
/api-reference/openapi.yaml post /v1/event/{eventId}/contacts/{contactId}/restore
Restore a previously soft-deleted contact. Requires the `write:contacts` scope.
# Soft-delete a contact
Source: https://apidocs.sessionboard.com/api-reference/contact-writes/soft-delete-a-contact
/api-reference/openapi.yaml delete /v1/event/{eventId}/contacts/{contactId}
Soft-delete a contact. Can be restored with the restore endpoint. Requires the `write:contacts` scope.
# Update a contact
Source: https://apidocs.sessionboard.com/api-reference/contact-writes/update-a-contact
/api-reference/openapi.yaml put /v1/event/{eventId}/contacts/{contactId}
Update an existing contact. Requires the `write:contacts` scope. Optionally send `updated_at` for optimistic concurrency control.
# Get a contact's sessions
Source: https://apidocs.sessionboard.com/api-reference/contacts/get-a-contacts-sessions
/api-reference/openapi.yaml get /v1/event/{eventId}/contacts/{contactId}/sessions
Returns all sessions associated with a specific contact within an
event, including linked composition sources. Each session summary
includes `is_abstract` and `composition_status`. The full
`composition` graph is not available on this lightweight endpoint —
use session GET or search with `expand=composition` for details.
# Get an event contact
Source: https://apidocs.sessionboard.com/api-reference/contacts/get-an-event-contact
/api-reference/openapi.yaml get /v1/event/{eventId}/contacts/{contactId}
Retrieve a single contact by ID at the event level.
# Get an org contact's sessions
Source: https://apidocs.sessionboard.com/api-reference/contacts/get-an-org-contacts-sessions
/api-reference/openapi.yaml get /v1/organization/{orgId}/contacts/{contactId}/sessions
Returns all sessions associated with a specific contact across the
organization, including linked composition sources. Each session
summary includes `is_abstract`, `composition_status`, and
`event_id`. The full `composition` graph is not available on this
lightweight endpoint.
# Get an organization contact
Source: https://apidocs.sessionboard.com/api-reference/contacts/get-an-organization-contact
/api-reference/openapi.yaml get /v1/organization/{orgId}/contacts/{contactId}
Retrieve a single contact by ID at the organization level.
# Search event contacts
Source: https://apidocs.sessionboard.com/api-reference/contacts/search-event-contacts
/api-reference/openapi.yaml post /v1/event/{eventId}/contacts
Search and filter contacts within an event.
# Search organization contacts
Source: https://apidocs.sessionboard.com/api-reference/contacts/search-organization-contacts
/api-reference/openapi.yaml post /v1/organization/{orgId}/contacts
Search and filter contacts across the organization.
# Create an org dashboard (convenience)
Source: https://apidocs.sessionboard.com/api-reference/dashboards-&-widgets/create-an-org-dashboard-convenience
/api-reference/openapi.yaml post /v1/dashboards/create
Create a new cross-event dashboard. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# Create an org widget (convenience)
Source: https://apidocs.sessionboard.com/api-reference/dashboards-&-widgets/create-an-org-widget-convenience
/api-reference/openapi.yaml post /v1/dashboards/{dashboardId}/widgets/create
Add a widget to an org-level dashboard. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# Delete an org dashboard (convenience)
Source: https://apidocs.sessionboard.com/api-reference/dashboards-&-widgets/delete-an-org-dashboard-convenience
/api-reference/openapi.yaml delete /v1/dashboards/{id}
Delete a cross-event dashboard. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# Delete an org widget (convenience)
Source: https://apidocs.sessionboard.com/api-reference/dashboards-&-widgets/delete-an-org-widget-convenience
/api-reference/openapi.yaml delete /v1/widgets/{widgetId}
Delete a widget. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# Get an org dashboard (convenience)
Source: https://apidocs.sessionboard.com/api-reference/dashboards-&-widgets/get-an-org-dashboard-convenience
/api-reference/openapi.yaml get /v1/dashboards/{id}
Retrieve a cross-event dashboard with all widget data. Organization is resolved from the API token. No orgId required. Requires the `read:insights` scope.
# List org dashboards (convenience)
Source: https://apidocs.sessionboard.com/api-reference/dashboards-&-widgets/list-org-dashboards-convenience
/api-reference/openapi.yaml get /v1/dashboards
Returns all dashboards across all events in the organization. Organization is resolved from the API token. No orgId required. Requires the `read:insights` scope.
# Update an org dashboard (convenience)
Source: https://apidocs.sessionboard.com/api-reference/dashboards-&-widgets/update-an-org-dashboard-convenience
/api-reference/openapi.yaml put /v1/dashboards/{id}
Update dashboard properties. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# Update an org widget (convenience)
Source: https://apidocs.sessionboard.com/api-reference/dashboards-&-widgets/update-an-org-widget-convenience
/api-reference/openapi.yaml put /v1/widgets/{widgetId}
Update widget configuration. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# List fields
Source: https://apidocs.sessionboard.com/api-reference/event-settings/list-fields
/api-reference/openapi.yaml get /v1/event/{eventId}/fields
Returns all field definitions for an event.
# List formats
Source: https://apidocs.sessionboard.com/api-reference/event-settings/list-formats
/api-reference/openapi.yaml get /v1/event/{eventId}/formats
Returns all session formats for an event.
# List languages
Source: https://apidocs.sessionboard.com/api-reference/event-settings/list-languages
/api-reference/openapi.yaml get /v1/event/{eventId}/languages
Returns all languages for an event.
# List levels
Source: https://apidocs.sessionboard.com/api-reference/event-settings/list-levels
/api-reference/openapi.yaml get /v1/event/{eventId}/levels
Returns all session levels for an event.
# List rooms
Source: https://apidocs.sessionboard.com/api-reference/event-settings/list-rooms
/api-reference/openapi.yaml get /v1/event/{eventId}/rooms
Returns all rooms for an event.
# List session statuses
Source: https://apidocs.sessionboard.com/api-reference/event-settings/list-session-statuses
/api-reference/openapi.yaml get /v1/event/{eventId}/statuses
Returns all session status definitions for an event.
# List tags
Source: https://apidocs.sessionboard.com/api-reference/event-settings/list-tags
/api-reference/openapi.yaml get /v1/event/{eventId}/tags
Returns all tags for an event.
# List tracks
Source: https://apidocs.sessionboard.com/api-reference/event-settings/list-tracks
/api-reference/openapi.yaml get /v1/event/{eventId}/tracks
Returns all tracks for an event.
# Search fields
Source: https://apidocs.sessionboard.com/api-reference/event-settings/search-fields
/api-reference/openapi.yaml post /v1/event/{eventId}/fields
Search and filter field definitions for an event, including standard and custom fields.
# Search formats
Source: https://apidocs.sessionboard.com/api-reference/event-settings/search-formats
/api-reference/openapi.yaml post /v1/event/{eventId}/formats
Returns a paginated list of session formats for an event.
# Search languages
Source: https://apidocs.sessionboard.com/api-reference/event-settings/search-languages
/api-reference/openapi.yaml post /v1/event/{eventId}/languages
Returns a paginated list of languages configured for an event.
# Search levels
Source: https://apidocs.sessionboard.com/api-reference/event-settings/search-levels
/api-reference/openapi.yaml post /v1/event/{eventId}/levels
Returns a paginated list of session levels for an event.
# Search rooms
Source: https://apidocs.sessionboard.com/api-reference/event-settings/search-rooms
/api-reference/openapi.yaml post /v1/event/{eventId}/rooms
Returns a paginated list of rooms for an event.
# Search session statuses
Source: https://apidocs.sessionboard.com/api-reference/event-settings/search-session-statuses
/api-reference/openapi.yaml post /v1/event/{eventId}/session-statuses
Returns a paginated list of custom session status definitions for an event.
# Search tags
Source: https://apidocs.sessionboard.com/api-reference/event-settings/search-tags
/api-reference/openapi.yaml post /v1/event/{eventId}/tags
Returns a paginated list of tags for an event.
# Search tracks
Source: https://apidocs.sessionboard.com/api-reference/event-settings/search-tracks
/api-reference/openapi.yaml post /v1/event/{eventId}/tracks
Returns a paginated list of tracks for an event.
# List events
Source: https://apidocs.sessionboard.com/api-reference/events/list-events
/api-reference/openapi.yaml get /v1/events
Returns a paginated list of events accessible to the authenticated API key.
# Bulk exhibitor operations
Source: https://apidocs.sessionboard.com/api-reference/exhibitor-writes/bulk-exhibitor-operations
/api-reference/openapi.yaml post /v1/event/{eventId}/exhibitors/bulk
Create, update, or delete multiple exhibitors in a single request (max 100 operations). Requires the `write:exhibitors` scope.
# Create an exhibitor
Source: https://apidocs.sessionboard.com/api-reference/exhibitor-writes/create-an-exhibitor
/api-reference/openapi.yaml post /v1/event/{eventId}/exhibitors/create
Create a new exhibitor in an event. Requires the `write:exhibitors` scope. Subject to rate limiting (100 req/15min) and daily write quota (10,000/day per token).
# Restore a deleted exhibitor
Source: https://apidocs.sessionboard.com/api-reference/exhibitor-writes/restore-a-deleted-exhibitor
/api-reference/openapi.yaml post /v1/event/{eventId}/exhibitors/{exhibitorId}/restore
Restore a previously soft-deleted exhibitor. Requires the `write:exhibitors` scope.
# Soft-delete an exhibitor
Source: https://apidocs.sessionboard.com/api-reference/exhibitor-writes/soft-delete-an-exhibitor
/api-reference/openapi.yaml delete /v1/event/{eventId}/exhibitors/{exhibitorId}
Soft-delete an exhibitor. Can be restored with the restore endpoint. Requires the `write:exhibitors` scope.
# Update an exhibitor
Source: https://apidocs.sessionboard.com/api-reference/exhibitor-writes/update-an-exhibitor
/api-reference/openapi.yaml put /v1/event/{eventId}/exhibitors/{exhibitorId}
Update an existing exhibitor. Requires the `write:exhibitors` scope. Optionally send `updated_at` for optimistic concurrency control.
# Get an exhibitor
Source: https://apidocs.sessionboard.com/api-reference/exhibitors/get-an-exhibitor
/api-reference/openapi.yaml get /v1/event/{eventId}/exhibitors/{exhibitorId}
Retrieve a single exhibitor by ID.
# Search exhibitors
Source: https://apidocs.sessionboard.com/api-reference/exhibitors/search-exhibitors
/api-reference/openapi.yaml post /v1/event/{eventId}/exhibitors
Search and filter exhibitors within an event.
# Create a custom field
Source: https://apidocs.sessionboard.com/api-reference/field-writes/create-a-custom-field
/api-reference/openapi.yaml post /v1/event/{eventId}/fields/create
Create a new custom field for an event module. Requires the `write:fields` scope.
# Delete a custom field
Source: https://apidocs.sessionboard.com/api-reference/field-writes/delete-a-custom-field
/api-reference/openapi.yaml delete /v1/event/{eventId}/fields/{fieldId}
# Update a custom field
Source: https://apidocs.sessionboard.com/api-reference/field-writes/update-a-custom-field
/api-reference/openapi.yaml put /v1/event/{eventId}/fields/{fieldId}
# Create a GDPR request
Source: https://apidocs.sessionboard.com/api-reference/gdpr/create-a-gdpr-request
/api-reference/openapi.yaml post /v1/gdpr/requests
Submit a new GDPR data access or erasure request.
# List GDPR requests
Source: https://apidocs.sessionboard.com/api-reference/gdpr/list-gdpr-requests
/api-reference/openapi.yaml get /v1/gdpr/requests
Returns all GDPR data access and erasure requests for the organization.
# Create a dashboard
Source: https://apidocs.sessionboard.com/api-reference/insights/create-a-dashboard
/api-reference/openapi.yaml post /v1/event/{eventId}/dashboards/create
Create a new dashboard with optional inline widgets. Requires the `write:events` scope.
# Create a saved query
Source: https://apidocs.sessionboard.com/api-reference/insights/create-a-saved-query
/api-reference/openapi.yaml post /v1/event/{eventId}/queries/create
Save a SbQL query as a reusable report. Requires the `write:events` scope.
# Create a widget
Source: https://apidocs.sessionboard.com/api-reference/insights/create-a-widget
/api-reference/openapi.yaml post /v1/event/{eventId}/dashboards/{dashboardId}/widgets/create
Add a widget to a dashboard. Requires the `write:events` scope.
# Delete a dashboard
Source: https://apidocs.sessionboard.com/api-reference/insights/delete-a-dashboard
/api-reference/openapi.yaml delete /v1/event/{eventId}/dashboards/{id}
Delete a dashboard. Requires the `write:events` scope.
# Delete a saved query
Source: https://apidocs.sessionboard.com/api-reference/insights/delete-a-saved-query
/api-reference/openapi.yaml delete /v1/event/{eventId}/queries/{queryId}
Delete a saved query. Requires the `write:events` scope.
# Delete a widget
Source: https://apidocs.sessionboard.com/api-reference/insights/delete-a-widget
/api-reference/openapi.yaml delete /v1/event/{eventId}/widgets/{widgetId}
Delete a widget from its dashboard. Requires the `write:events` scope.
# Execute a SbQL query
Source: https://apidocs.sessionboard.com/api-reference/insights/execute-a-sbql-query
/api-reference/openapi.yaml post /v1/insights/execute
Execute a SbQL query against event data and return results. Requires the `read:insights` scope.
# Execute a SbQL query (event-scoped)
Source: https://apidocs.sessionboard.com/api-reference/insights/execute-a-sbql-query-event-scoped
/api-reference/openapi.yaml post /v1/event/{eventId}/insights/execute
Execute a SbQL query scoped to a specific event. Requires the `read:insights` scope.
# Generate a SbQL query from natural language
Source: https://apidocs.sessionboard.com/api-reference/insights/generate-a-sbql-query-from-natural-language
/api-reference/openapi.yaml post /v1/insights/ai/generate
Use AI to translate a natural language prompt into a SbQL query. Requires the `read:insights` scope.
# Generate a SbQL query from natural language (event-scoped)
Source: https://apidocs.sessionboard.com/api-reference/insights/generate-a-sbql-query-from-natural-language-event-scoped
/api-reference/openapi.yaml post /v1/event/{eventId}/insights/ai/generate
Use AI to translate natural language into a SbQL query scoped to a specific event. Requires the `read:insights` scope.
# Get a dashboard
Source: https://apidocs.sessionboard.com/api-reference/insights/get-a-dashboard
/api-reference/openapi.yaml get /v1/event/{eventId}/dashboards/{id}
Retrieve a dashboard with all widget data. Requires the `read:insights` scope.
# Get a dashboard (event-scoped insights)
Source: https://apidocs.sessionboard.com/api-reference/insights/get-a-dashboard-event-scoped-insights
/api-reference/openapi.yaml get /v1/event/{eventId}/insights/dashboards/{id}
Retrieve a dashboard via the insights proxy. Requires the `read:insights` scope.
# Get event-scoped insights schema
Source: https://apidocs.sessionboard.com/api-reference/insights/get-event-scoped-insights-schema
/api-reference/openapi.yaml get /v1/event/{eventId}/insights/schema
Returns the SbQL schema including event-specific custom fields. Requires the `read:insights` scope.
# Get event-scoped query suggestions
Source: https://apidocs.sessionboard.com/api-reference/insights/get-event-scoped-query-suggestions
/api-reference/openapi.yaml get /v1/event/{eventId}/insights/suggestions
Returns contextual query suggestions for a specific event. Requires the `read:insights` scope.
# Get event-specific insights schema
Source: https://apidocs.sessionboard.com/api-reference/insights/get-event-specific-insights-schema
/api-reference/openapi.yaml get /v1/insights/events/{eventId}/schema
Returns the SbQL schema scoped to a specific event, including event-specific custom fields. Requires the `read:insights` scope.
# Get insights schema
Source: https://apidocs.sessionboard.com/api-reference/insights/get-insights-schema
/api-reference/openapi.yaml get /v1/insights/schema
Returns the SbQL schema for the organization, including available entities and fields. Requires the `read:insights` scope.
# Get query suggestions
Source: https://apidocs.sessionboard.com/api-reference/insights/get-query-suggestions
/api-reference/openapi.yaml get /v1/insights/suggestions
Returns contextual SbQL query suggestions. Requires the `read:insights` scope.
# List dashboards
Source: https://apidocs.sessionboard.com/api-reference/insights/list-dashboards
/api-reference/openapi.yaml get /v1/event/{eventId}/dashboards
Returns all dashboards for an event. Requires the `read:insights` scope.
# List saved queries
Source: https://apidocs.sessionboard.com/api-reference/insights/list-saved-queries
/api-reference/openapi.yaml get /v1/insights/queries
Returns a list of saved SbQL queries. Requires the `read:insights` scope.
# List saved queries (event-scoped insights)
Source: https://apidocs.sessionboard.com/api-reference/insights/list-saved-queries-event-scoped-insights
/api-reference/openapi.yaml get /v1/event/{eventId}/insights/queries
Returns saved queries via the insights proxy. Requires the `read:insights` scope.
# List saved queries for an event
Source: https://apidocs.sessionboard.com/api-reference/insights/list-saved-queries-for-an-event
/api-reference/openapi.yaml get /v1/event/{eventId}/queries
Returns saved SbQL queries scoped to an event. Requires the `read:insights` scope.
# Run a saved query
Source: https://apidocs.sessionboard.com/api-reference/insights/run-a-saved-query
/api-reference/openapi.yaml post /v1/insights/queries/{queryId}/run
Execute a previously saved SbQL query by ID. Requires the `read:insights` scope.
# Run a saved query (event-scoped insights)
Source: https://apidocs.sessionboard.com/api-reference/insights/run-a-saved-query-event-scoped-insights
/api-reference/openapi.yaml post /v1/event/{eventId}/insights/queries/{queryId}/run
Execute a saved query via the insights proxy. Requires the `read:insights` scope.
# Run a saved query for an event
Source: https://apidocs.sessionboard.com/api-reference/insights/run-a-saved-query-for-an-event
/api-reference/openapi.yaml post /v1/event/{eventId}/queries/{queryId}/run
Execute a saved SbQL query. Requires the `write:events` scope (reports execute through the write pipeline for quota tracking).
# Update a dashboard
Source: https://apidocs.sessionboard.com/api-reference/insights/update-a-dashboard
/api-reference/openapi.yaml put /v1/event/{eventId}/dashboards/{id}
Update dashboard properties. Requires the `write:events` scope.
# Update a saved query
Source: https://apidocs.sessionboard.com/api-reference/insights/update-a-saved-query
/api-reference/openapi.yaml put /v1/event/{eventId}/queries/{queryId}
Update a saved query. Requires the `write:events` scope.
# Update a widget
Source: https://apidocs.sessionboard.com/api-reference/insights/update-a-widget
/api-reference/openapi.yaml put /v1/event/{eventId}/widgets/{widgetId}
Update widget configuration. Requires the `write:events` scope.
# Abort multipart upload
Source: https://apidocs.sessionboard.com/api-reference/media/abort-multipart-upload
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/media/upload/abort
Requires `write:media`.
# Complete multipart media upload
Source: https://apidocs.sessionboard.com/api-reference/media/complete-multipart-media-upload
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/media/upload/complete
Finalizes the upload and starts automatic transcription. When you upload on a session URL,
transcript lines appear in the session transcription list when processing finishes.
Requires `write:media`.
# Get media item status
Source: https://apidocs.sessionboard.com/api-reference/media/get-media-item-status
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}/media/{mediaItemId}
Check upload and transcription progress after completing an upload. Requires `read:media` (legacy tokens with empty scopes pass).
# Sign multipart upload parts
Source: https://apidocs.sessionboard.com/api-reference/media/sign-multipart-upload-parts
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/media/upload/sign-part
Requires `write:media`.
# Start multipart media upload
Source: https://apidocs.sessionboard.com/api-reference/media/start-multipart-media-upload
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/media/upload/initiate
Begins a multipart upload for a video or audio file on a session. Requires `write:media`.
# Create a format
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/create-a-format
/api-reference/openapi.yaml post /v1/event/{eventId}/formats/create
Create a new session format. Requires the `write:metadata` scope.
# Create a language
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/create-a-language
/api-reference/openapi.yaml post /v1/event/{eventId}/languages/create
Create a new language. Requires the `write:metadata` scope.
# Create a level
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/create-a-level
/api-reference/openapi.yaml post /v1/event/{eventId}/levels/create
Create a new session level. Requires the `write:metadata` scope.
# Create a room
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/create-a-room
/api-reference/openapi.yaml post /v1/event/{eventId}/rooms/create
Create a new room. Requires the `write:metadata` scope.
# Create a session status
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/create-a-session-status
/api-reference/openapi.yaml post /v1/event/{eventId}/statuses/create
Create a new custom session status. Requires the `write:metadata` scope.
# Create a tag
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/create-a-tag
/api-reference/openapi.yaml post /v1/event/{eventId}/tags/create
Create a new tag. Requires the `write:metadata` scope.
# Create a track
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/create-a-track
/api-reference/openapi.yaml post /v1/event/{eventId}/tracks/create
Create a new track. Requires the `write:metadata` scope.
# Delete a format
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/delete-a-format
/api-reference/openapi.yaml delete /v1/event/{eventId}/formats/{id}
Delete a session format. Requires the `write:metadata` scope.
# Delete a language
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/delete-a-language
/api-reference/openapi.yaml delete /v1/event/{eventId}/languages/{id}
Delete a language. Requires the `write:metadata` scope.
# Delete a level
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/delete-a-level
/api-reference/openapi.yaml delete /v1/event/{eventId}/levels/{id}
Delete a session level. Requires the `write:metadata` scope.
# Delete a room
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/delete-a-room
/api-reference/openapi.yaml delete /v1/event/{eventId}/rooms/{id}
Delete a room. Requires the `write:metadata` scope.
# Delete a session status
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/delete-a-session-status
/api-reference/openapi.yaml delete /v1/event/{eventId}/statuses/{id}
Delete a custom session status. Requires the `write:metadata` scope.
# Delete a tag
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/delete-a-tag
/api-reference/openapi.yaml delete /v1/event/{eventId}/tags/{id}
Delete a tag. Requires the `write:metadata` scope.
# Delete a track
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/delete-a-track
/api-reference/openapi.yaml delete /v1/event/{eventId}/tracks/{id}
Delete a track. Requires the `write:metadata` scope.
# Restore a deleted session status
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/restore-a-deleted-session-status
/api-reference/openapi.yaml post /v1/event/{eventId}/statuses/{id}/restore
Restore a previously soft-deleted session status. Requires the `write:metadata` scope.
# Update a format
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/update-a-format
/api-reference/openapi.yaml put /v1/event/{eventId}/formats/{id}
Update a session format. Requires the `write:metadata` scope.
# Update a language
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/update-a-language
/api-reference/openapi.yaml put /v1/event/{eventId}/languages/{id}
Update a language. Requires the `write:metadata` scope.
# Update a level
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/update-a-level
/api-reference/openapi.yaml put /v1/event/{eventId}/levels/{id}
Update a session level. Requires the `write:metadata` scope.
# Update a room
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/update-a-room
/api-reference/openapi.yaml put /v1/event/{eventId}/rooms/{id}
Update a room. Requires the `write:metadata` scope.
# Update a session status
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/update-a-session-status
/api-reference/openapi.yaml put /v1/event/{eventId}/statuses/{id}
Update a custom session status. Requires the `write:metadata` scope.
# Update a tag
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/update-a-tag
/api-reference/openapi.yaml put /v1/event/{eventId}/tags/{id}
Update a tag. Requires the `write:metadata` scope.
# Update a track
Source: https://apidocs.sessionboard.com/api-reference/metadata-writes/update-a-track
/api-reference/openapi.yaml put /v1/event/{eventId}/tracks/{id}
Update a track. Requires the `write:metadata` scope.
# Authorization server metadata
Source: https://apidocs.sessionboard.com/api-reference/oauth/authorization-server-metadata
/api-reference/openapi.yaml get /oauth/.well-known/oauth-authorization-server
Returns OAuth 2.0 Authorization Server Metadata per RFC 8414. Includes supported scopes, grant types, and endpoint URLs.
# Exchange code for tokens
Source: https://apidocs.sessionboard.com/api-reference/oauth/exchange-code-for-tokens
/api-reference/openapi.yaml post /oauth/token
Exchange an authorization code for access and refresh tokens (authorization_code grant), or refresh an expired access token (refresh_token grant). Uses PKCE verification — no client secret required.
# Revoke a token
Source: https://apidocs.sessionboard.com/api-reference/oauth/revoke-a-token
/api-reference/openapi.yaml post /oauth/revoke
Revoke an access or refresh token. Conforms to RFC 7009. Always returns 200 regardless of whether the token was found.
# Validate authorization request
Source: https://apidocs.sessionboard.com/api-reference/oauth/validate-authorization-request
/api-reference/openapi.yaml get /oauth/authorize
Validates OAuth authorization request parameters (client_id, redirect_uri, scopes, PKCE challenge). Returns the validated request for display on the consent page. No authentication required.
# API Reference
Source: https://apidocs.sessionboard.com/api-reference/overview
Complete reference for the Sessionboard Public API
This reference documents every endpoint available in the Sessionboard Public API. Endpoint pages are generated from our OpenAPI specification and include request parameters, response schemas, and example payloads.
## Base URLs
| Region | Base URL |
| ------ | ---------------------------------------- |
| US | `https://public-api.sessionboard.com` |
| EU | `https://public-api-eu.sessionboard.com` |
Use the base URL corresponding to the region where your organization's data is hosted.
## Authentication
All requests require an `x-access-token` header containing a valid API token. See [Authentication](/authentication) for details on generating and managing tokens.
```bash theme={null}
curl -H "x-access-token: YOUR_TOKEN" https://public-api.sessionboard.com/v1/events
```
## Common Patterns
### Pagination
Search endpoints accept `page` and `pageSize` parameters and return a `pagination` object in the response. The default page size is 25 and the maximum is 100.
Session responses include `is_abstract` and `composition_status` for composition-aware integrations. Subsessions inherit these fields from their parent. See [Sessions & composition](/api-reference/sessions-composition) for filters, expand options, and contact session summaries.
### Filtering
POST-based search endpoints accept filter criteria in the request body. Refer to each endpoint's documentation for available filter fields.
### Create vs Search Endpoints
Some resources have two `POST` endpoints at similar paths:
| Path Pattern | Purpose |
| ------------------------------------------ | --------------------------------------------------------- |
| `POST /v1/event/{eventId}/sessions` | **Search** sessions with filters, sorting, and pagination |
| `POST /v1/event/{eventId}/sessions/create` | **Create** a new session |
The `/create` suffix distinguishes write operations from search where both use `POST` on the same collection path (sessions, contacts, exhibitors, sponsors, custom fields, and metadata entities).
Session-scoped **transcriptions**, **recordings**, and **session files** use standard REST — `POST` on the collection path creates a resource; there is no conflicting search endpoint. See [Media & Transcriptions](/guides/uploading-media-and-transcriptions) and [Uploading session files](/guides/uploading-session-files) for upload flows.
### Sorting
POST-based search endpoints accept a `sort` object in the request body to control result ordering. Sort by `createdAt` or `updatedAt` with `asc` or `desc` direction.
### Expanding Records
Some endpoints support an `expand` query parameter (or request-body field) to include additional data in the response.
| Expand value | Endpoints | Description |
| -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `translated_fields` | most read endpoints | Returns translated versions of text fields when your event has translations enabled. |
| `subsession_details` | session search + get | Returns full parent-shape parity (`status`, `custom_status`, `custom_fields`, `chairpersons`, `moderators`, `sponsors`, `exhibitors`, `tags`, `language`, `track`, `level`, `room`, `is_public`, `external_url`, `client_session_id`, `ceu_credits`, `capacity`, `source`) on every subsession inside `parent.subsessions[]`. Nested `language`, `track`, `level`, and `room` objects include the same fields as on parent sessions (see the `Session` schema). Without this expand the array contains the minimal subsession shape (`id`, `friendly_id`, `title`, `description`, `starts_at`, `ends_at`, `speakers`, `participants`, `format`, `content`, timestamps, parent friendly-id keys). Heavy joins are gated behind the flag for query performance. |
### Nested session metadata
Session responses embed assigned metadata as nested objects:
| Field | Populated fields | Notes |
| ---------- | ---------------------------------------------------------------------- | ------------------------------- |
| `language` | `id`, `event_id`, `name`, `order`, `created_at`, `updated_at` | |
| `track` | `id`, `event_id`, `name`, `color`, `order`, `created_at`, `updated_at` | |
| `level` | `id`, `name`, `order`, `created_at`, `updated_at` | No `event_id` on nested objects |
| `format` | `id`, `name` only | |
| `room` | `id`, `name`, `order`, `capacity`, `created_at`, `updated_at` | Only when `location` is `room` |
Unassigned metadata is returned as an empty object `{}` on `POST /v1/event/{eventId}/sessions` (search). CRUD proxy endpoints (`GET` list, create, update, restore) return `null` instead.
### Subsessions
Sessions can have subsessions (child sessions linked to a parent). Subsessions are returned both:
* **Nested**, inside `parent.subsessions[]` on every session response. The default shape is minimal — pass `expand=subsession_details` to receive full parity with the parent session.
* **Top-level**, by calling `GET /v1/event/{eventId}/sessions/{sessionId}` with the subsession's UUID directly. The endpoint always returns the full session shape (including `chairpersons`, `moderators`, `custom_fields`, etc.) plus `parent_session_friendly_id` and `parent_session_friendly_id_raw` keys identifying the parent. The `expand=subsession_details` flag has no effect at the top level.
This means callers can iterate `parent.subsessions[]`, take each subsession id, and call the GET endpoint to retrieve the same shape they would for a parent session — useful for integration patterns that need to walk the session tree.
### Session participants (Sessions 2.0)
Session responses include **both** legacy role arrays and a flat `participants` array:
| Field | Source | When to use |
| ---------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------- |
| `speakers`, `chairpersons`, `moderators` | Legacy junction tables | Existing integrations that expect these arrays |
| `participants` | `Session_Participants` + `Session_Roles` | New integrations; events with custom program roles (Author, Panelist, etc.) |
Each participant object uses the `SessionSpeaker` contact profile shape plus `participant_role` (`slug`, `name`, `name_plural`, `core_role`). Use `participant_role.name` (or `slug`) as the display/program role — for example **Author** or **Panelist**. `core_role` is only the legacy junction mapping (`speaker`, `chairperson`, `moderator`) and is not the role label.
Contact profile fields on embedded participants — `photo_url`, `company_name`, `title`, `address_country`, and other standard contact fields — are included in the event's default language **without** expand. Use `expand=translated_fields` for other locales.
Legacy `speakers` / `chairpersons` / `moderators` entries also include `participant_role` when the event has Sessions 2.0 roles configured.
### Organization-Scoped vs Convenience Routes
Dashboards, widgets, and saved reports support three route patterns:
| Pattern | Example | Notes |
| ------------ | ------------------------------------- | ------------------------------------ |
| Event-scoped | `/v1/event/{eventId}/dashboards` | Scoped to a single event |
| Org-scoped | `/v1/organization/{orgId}/dashboards` | Cross-event, explicit org ID |
| Convenience | `/v1/dashboards` | Cross-event, org resolved from token |
The convenience routes are recommended for org-level operations — they're simpler and don't require you to know the org ID. The org-scoped routes (`/v1/organization/{orgId}/...`) are equivalent but require the org ID in the URL.
## Media & Transcriptions
Sessionboard exposes three related but distinct media workflows. Pick the path that matches what you have:
| Workflow | When to use | Scopes |
| ---------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------- |
| **Transcriptions** | You already have transcript text, summaries, topics, or translations to sync | `read:transcriptions`, `write:transcriptions` |
| **Session recordings** | You have an audio file for a session's recording archive | `read:transcriptions`, `write:transcriptions` |
| **Media upload** | You have a video or audio file and want Sessionboard to transcribe it automatically | `read:media`, `write:media` |
Start with the [Media & Transcriptions guide](/guides/uploading-media-and-transcriptions) for playbooks and examples, or the [API overview](/api-reference/transcriptions-and-media) for resource shapes. Endpoint pages are grouped under **Event — Media** in the sidebar.
## Error Codes
| Status Code | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200` | Success. The response body contains the requested data. |
| `400` | Bad Request. The request body or parameters are invalid. Check the error message for details. |
| `401` | Unauthorized. The `x-access-token` header is missing or the token is invalid. |
| `403` | Forbidden. The token does not have the required scope for this endpoint. |
| `404` | Not Found. The requested resource does not exist. |
| `409` | Conflict. The resource was modified since you last fetched it. Re-fetch the resource to get the current `updated_at` value and retry your update. |
| `429` | Too Many Requests. You are being rate limited. Retry after a short delay with exponential backoff. |
| `500` | Internal Server Error. An unexpected error occurred. Contact support if the issue persists. |
# Create an org saved query (convenience)
Source: https://apidocs.sessionboard.com/api-reference/reports-&-queries/create-an-org-saved-query-convenience
/api-reference/openapi.yaml post /v1/queries/create
Save a cross-event SbQL query. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# Delete an org saved query (convenience)
Source: https://apidocs.sessionboard.com/api-reference/reports-&-queries/delete-an-org-saved-query-convenience
/api-reference/openapi.yaml delete /v1/queries/{queryId}
Delete a saved query. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# List org saved queries (convenience)
Source: https://apidocs.sessionboard.com/api-reference/reports-&-queries/list-org-saved-queries-convenience
/api-reference/openapi.yaml get /v1/queries
Returns all saved SbQL queries across the organization. Organization is resolved from the API token. No orgId required. Requires the `read:insights` scope.
# Run an org saved query (convenience)
Source: https://apidocs.sessionboard.com/api-reference/reports-&-queries/run-an-org-saved-query-convenience
/api-reference/openapi.yaml post /v1/queries/{queryId}/run
Execute a saved cross-event SbQL query. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope (reports execute through the write pipeline for quota tracking).
# Update an org saved query (convenience)
Source: https://apidocs.sessionboard.com/api-reference/reports-&-queries/update-an-org-saved-query-convenience
/api-reference/openapi.yaml put /v1/queries/{queryId}
Update a saved query. Organization is resolved from the API token. No orgId required. Requires the `write:events` scope.
# Session Files
Source: https://apidocs.sessionboard.com/api-reference/session-files
Attach PDFs, PowerPoint decks, and other documents to sessions.
For step-by-step integration flows, start with the [Uploading session files](/guides/uploading-session-files) guide.
Session files are **not** the media or recording upload flow. Use [Media & Transcriptions](/guides/uploading-media-and-transcriptions) for video/audio that should be transcribed or stored as session recordings.
## Upload paths
One multipart call — Sessionboard detects size and MIME type, scans the file, and returns the attached `Content` object.
1. `POST .../files/upload` with multipart field **`file`**
2. Optional form fields: `title`, `assigned_participant_id`
Presigned URL flow for larger files or clients that prefer direct-to-S3 upload:
1. `POST .../files` — JSON with `filename` and `size_bytes`
2. `PUT` bytes to `data.upload.url`
3. `POST .../files/{fileId}/complete`
## Scopes
| Action | Scope |
| ------------------------------------------------------ | ---------------- |
| List files | `read:sessions` |
| Upload / create / complete / replace / update / delete | `write:sessions` |
## Endpoints
POST /v1/event//sessions//files/upload
GET /v1/event//sessions//files
POST /v1/event//sessions//files
POST .../files//complete
POST .../files//replace
PUT /v1/event//sessions//files/
## Response shape
File objects use the `Content` schema (`id`, `url`, `title`, `filename`, `size`, `mimetype`, assigned participant fields, timestamps). Direct-to-storage create/replace responses also include an `upload` object with `url`, `method`, and `headers` for the presigned PUT.
## Related reference
* [Uploading session files](/guides/uploading-session-files) — full playbook
* [Transcriptions & Media](/api-reference/transcriptions-and-media)
* [Authentication & scopes](/authentication)
# Delete a session file
Source: https://apidocs.sessionboard.com/api-reference/session-files/delete-a-session-file
/api-reference/openapi.yaml delete /v1/event/{eventId}/sessions/{sessionId}/files/{fileId}
Soft-deletes the file from the session. Requires `write:sessions`.
# Finalize session file upload
Source: https://apidocs.sessionboard.com/api-reference/session-files/finalize-session-file-upload
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/files/{fileId}/complete
Verifies the object in Sessionboard storage, runs security scanning
(type deny-list + magic-byte checks; SVG sanitization when applicable),
and finalizes the file on the session. Requires `write:sessions`.
# Initiate session file upload
Source: https://apidocs.sessionboard.com/api-reference/session-files/initiate-session-file-upload
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/files
Creates a file record and returns a short-lived S3 upload URL.
Requires `write:sessions`.
Next: `PUT` the file bytes to `data.upload.url`, then call
`POST .../files/{fileId}/complete`. For files up to **50 MB**, prefer
`POST .../files/upload` (one multipart call). This direct-to-storage
path supports up to **500 MB**.
See [Uploading session files](/guides/uploading-session-files).
# List files attached to a session
Source: https://apidocs.sessionboard.com/api-reference/session-files/list-files-attached-to-a-session
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}/files
Returns completed files on the session (latest version per file group).
Incomplete uploads (create/replace without complete) are omitted.
Requires `read:sessions` scope (legacy tokens with empty scopes pass).
# Replace session file bytes
Source: https://apidocs.sessionboard.com/api-reference/session-files/replace-session-file-bytes
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/files/{fileId}/replace
Issues a new upload URL for the same file record. After `PUT`ing the new
bytes, call `complete` again. Requires `write:sessions`. Max **500 MB**
(direct-to-storage flow).
# Update session file metadata
Source: https://apidocs.sessionboard.com/api-reference/session-files/update-session-file-metadata
/api-reference/openapi.yaml put /v1/event/{eventId}/sessions/{sessionId}/files/{fileId}
Updates display title and/or assigned participant. Does not change file
bytes — use `replace` for that. Unknown fields are ignored.
Requires `write:sessions`.
# Upload a session file (simple)
Source: https://apidocs.sessionboard.com/api-reference/session-files/upload-a-session-file-simple
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/files/upload
Upload a file in one multipart request. Sessionboard detects size and
MIME type from the bytes, runs security scanning, and returns the
finalized file. Max **50 MB**. Requires `write:sessions`.
For files larger than 50 MB (up to 500 MB), use the direct-to-storage
flow: `POST .../files` → PUT to signed URL → `POST .../complete`.
See [Uploading session files](/guides/uploading-session-files).
# Finalize session audio upload
Source: https://apidocs.sessionboard.com/api-reference/session-recordings/finalize-session-audio-upload
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/recordings/{recordingId}/complete
Marks the recording as completed and normalizes common audio formats for playback.
Already-completed recordings return 200 without re-processing. Requires `write:transcriptions`.
# Get a session audio recording
Source: https://apidocs.sessionboard.com/api-reference/session-recordings/get-a-session-audio-recording
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}/recordings/{recordingId}
Requires `read:transcriptions` scope (legacy tokens with empty scopes pass).
# Initiate session audio upload
Source: https://apidocs.sessionboard.com/api-reference/session-recordings/initiate-session-audio-upload
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/recordings
Returns a presigned upload URL for the audio file. Requires `write:transcriptions`.
# List session audio recordings
Source: https://apidocs.sessionboard.com/api-reference/session-recordings/list-session-audio-recordings
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}/recordings
Requires `read:transcriptions` scope (legacy tokens with empty scopes pass).
# Bulk session operations
Source: https://apidocs.sessionboard.com/api-reference/session-writes/bulk-session-operations
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/bulk
Create, update, or delete multiple sessions in a single request (max 100 operations). Requires the `write:sessions` scope.
# Create a session
Source: https://apidocs.sessionboard.com/api-reference/session-writes/create-a-session
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/create
Create a new session in an event. Requires the `write:sessions` scope. Subject to rate limiting (100 req/15min) and daily write quota (10,000/day per token).
# Restore a deleted session
Source: https://apidocs.sessionboard.com/api-reference/session-writes/restore-a-deleted-session
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/restore
Restore a previously soft-deleted session. Requires the `write:sessions` scope.
# Soft-delete a session
Source: https://apidocs.sessionboard.com/api-reference/session-writes/soft-delete-a-session
/api-reference/openapi.yaml delete /v1/event/{eventId}/sessions/{sessionId}
Soft-delete a session. Can be restored with the restore endpoint. Requires the `write:sessions` scope.
# Update a session
Source: https://apidocs.sessionboard.com/api-reference/session-writes/update-a-session
/api-reference/openapi.yaml put /v1/event/{eventId}/sessions/{sessionId}
Update an existing session. Requires the `write:sessions` scope. Send `updated_at` from the last-fetched session for optimistic concurrency control.
# Update session custom fields
Source: https://apidocs.sessionboard.com/api-reference/session-writes/update-session-custom-fields
/api-reference/openapi.yaml put /v1/event/{eventId}/sessions/{sessionId}/fields
Update custom field values on a session without touching other session properties. Requires the `write:sessions` scope.
# Sessions & Composition
Source: https://apidocs.sessionboard.com/api-reference/sessions-composition
Abstract vs program sessions, composition_status, and expand options for linked records.
# Sessions, abstracts & composition
Sessions and CFP abstract submissions share the same API resource. Use `is_abstract` to tell them apart.
## `is_abstract`
| Value | Meaning |
| ------- | ------------------------- |
| `false` | Program session (default) |
| `true` | CFP / abstract submission |
Every session response includes `is_abstract`. Filter list/search results with `filters.isAbstract` in `POST /v1/event/{eventId}/sessions`.
Create an abstract on write:
```json theme={null}
POST /v1/event/{eventId}/sessions/create
{
"title": "Novel approach to speaker management",
"is_abstract": true
}
```
Requires the **Sessions 2.0** feature on the event. `is_abstract` cannot be changed after create.
## `composition_status`
Always present on session payloads — a lightweight summary of merge/link state:
```json theme={null}
{
"composition_status": {
"role": "source",
"is_linked": true,
"is_read_only": true,
"source_count": 0,
"target": {
"id": "...",
"friendly_id": "SESS-99",
"title": "Composite session",
"is_abstract": false
}
}
}
```
| `role` | Meaning |
| ------------ | ---------------------------------------------------------- |
| `standalone` | Normal editable record |
| `target` | Composite parent — has linked sources (`source_count > 0`) |
| `source` | Linked into another record — **read-only** via API |
When `role` is `source`, field updates are blocked until the record is unlinked in the admin UI.
## Expand options
Use the existing `expand` array (query param on GET, request body on POST search):
### `linked_sources`
By default, sessions linked as composition sources are **hidden** from list/search (same as the admin content list). Pass `expand=linked_sources` to include them.
```json theme={null}
POST /v1/event/{eventId}/sessions
{
"expand": ["linked_sources"],
"filters": { "isAbstract": true }
}
```
### `composition`
Adds a full `composition` object with target and sources (including `relationship_type`):
```
GET /v1/event/{eventId}/sessions/{sessionId}?expand=composition
```
Relationship types:
| Value | Meaning |
| ----------------------- | -------------------------------------------------- |
| `merged_session` | Program session merged into a composite |
| `merged_abstract` | Abstract merged into a composite abstract |
| `composed_into_session` | Abstract linked or composed into a program session |
Use `expand=composition` on broad searches sparingly — it loads the full graph per row.
## Session participants
Session search and get responses include legacy `speakers`, `chairpersons`, and `moderators` arrays **and** a flat `participants` array from the Sessions 2.0 model (`Session_Participants` + `Session_Roles`).
* Use **`participants`** when you need custom program roles (Author, Panelist, etc.) or a single list of everyone on a session.
* Legacy arrays remain for backwards compatibility; each legacy entry also includes `participant_role` when roles are configured.
Contact profile fields (`photo_url`, `company_name`, `title`, `address_country`, etc.) are hydrated on all embedded contact shapes in the event's default language without expand. See [API overview — Session participants](/api-reference/overview#session-participants-sessions-20) for details.
## Subsessions
Subsessions cannot be composition sources or targets. When a subsession appears in API responses, composition fields are **inherited from the parent session**:
* `GET /v1/event/{eventId}/sessions/{sessionId}` with a subsession UUID returns the parent's `is_abstract`, `composition_status`, and optional `composition` graph (when `expand=composition`).
* Nested entries in `parent.subsessions[]` from session search receive the same inherited fields after the parent row is enriched.
* Contact session endpoints (`GET .../contacts/{contactId}/sessions`) return `is_abstract` and `composition_status` on each linked session summary (not the full `composition` graph).
This matches how organizers think about program blocks: the parent session owns the composition relationship.
## Contact sessions
Speaker-linked session lists include composition summary fields:
```
GET /v1/event/{eventId}/contacts/{contactId}/sessions
GET /v1/organization/{orgId}/contacts/{contactId}/sessions
```
Each session in the response includes `is_abstract` and `composition_status`. Linked composition sources are included (not filtered out). The full `composition` graph is **not** available on these lightweight endpoints — use session GET or search with `expand=composition` when you need source/target details.
## SbQL parity
SbQL exposes separate `Session` and `Abstract` entities over the same table. REST uses `is_abstract` on the unified session resource. See [SbQL reference](/insights/sbql).
# Get a session
Source: https://apidocs.sessionboard.com/api-reference/sessions/get-a-session
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}
Retrieve a single session by ID, optionally expanding related data.
Every session includes `is_abstract` and `composition_status`. Pass
`expand=composition` for full linked target and source details.
Accepts both parent session UUIDs and subsession UUIDs. When called
with a subsession UUID, the response is a full session-shaped DTO
for that subsession (with `parent_session_friendly_id` /
`parent_session_friendly_id_raw` keys and no nested `subsessions`
array). Subsessions inherit the parent session's `is_abstract`,
`composition_status`, and optional `composition` graph (when
`expand=composition` is set) — subsessions cannot participate in
composition directly.
This means callers can iterate `parent.subsessions[]` and then call
this endpoint with each subsession id to retrieve the same shape
as a parent session.
Pass `expand=subsession_details` to receive the full
`SubsessionDetailed` shape on every entry of `parent.subsessions[]`;
the flag has no effect at the top level — the top-level response
always returns the full shape regardless of whether the requested
id is a parent or a subsession.
# List sessions (CRUD proxy)
Source: https://apidocs.sessionboard.com/api-reference/sessions/list-sessions-crud-proxy
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions
Paginated list of top-level sessions via the CRUD proxy. Returns nested
`language`, `track`, `level`, `format`, and `room` metadata using the same
field sets documented on the `Session` schema (`null` when unassigned).
Also includes `is_abstract` and `composition_status`.
Query params: `is_abstract` (`true`/`false`), `expand=linked_sources`,
`expand=composition`, plus standard pagination and filters.
# Search sessions
Source: https://apidocs.sessionboard.com/api-reference/sessions/search-sessions
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions
Search and filter sessions within an event. Supports pagination,
sorting, filtering by status and date ranges, and expanding related
data.
Every session includes `is_abstract` and `composition_status`. Pass
`filters.isAbstract` to return only abstract submissions or only
program sessions. By default, sessions linked as composition sources
are excluded; pass `expand=linked_sources` to include them. Pass
`expand=composition` for full target/source details.
Each session in the response includes a `subsessions` array. By
default each subsession is returned in a minimal shape (`Subsession`).
Pass `expand=subsession_details` in the request body to receive full
parent-shape parity (`SubsessionDetailed`) on every subsession —
including `status`, `custom_status`, `custom_fields`, `chairpersons`,
`moderators`, `sponsors`, `exhibitors`, `tags`, `language`, `track`,
`level`, `room`, etc.
Each subsession inherits the parent session's `is_abstract`,
`composition_status`, and optional `composition` graph (when
`expand=composition` is set).
Nested `language`, `track`, `level`, `format`, and `room` objects on
each session include the field sets documented on the `Session` schema.
Unassigned metadata is returned as `{}`.
Paginated search responses return matching sessions under `results`
(not `data`), alongside a `pagination` object.
# Search sessions by status
Source: https://apidocs.sessionboard.com/api-reference/sessions/search-sessions-by-status
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/status
Returns a lightweight list of session statuses, including deleted
sessions. Supports filtering by `deletedAt` in addition to standard
filters.
Parent rows additionally include a `subsessions` array with the same
minimal status-focused shape for each child subsession
(`SubsessionStatus`). Subsession rows that appear in the flat
results continue to surface with their own row (for back-compat) and
carry an empty `subsessions` array.
# Get a speaker
Source: https://apidocs.sessionboard.com/api-reference/speakers/get-a-speaker
/api-reference/openapi.yaml get /v1/event/{eventId}/speakers/{contactId}
Retrieve a single speaker by contact ID.
# Search speakers
Source: https://apidocs.sessionboard.com/api-reference/speakers/search-speakers
/api-reference/openapi.yaml post /v1/event/{eventId}/speakers
Search and filter speakers within an event.
# Bulk sponsor operations
Source: https://apidocs.sessionboard.com/api-reference/sponsor-writes/bulk-sponsor-operations
/api-reference/openapi.yaml post /v1/event/{eventId}/sponsors/bulk
Create, update, or delete multiple sponsors in a single request (max 100 operations). Requires the `write:sponsors` scope.
# Create a sponsor
Source: https://apidocs.sessionboard.com/api-reference/sponsor-writes/create-a-sponsor
/api-reference/openapi.yaml post /v1/event/{eventId}/sponsors/create
Create a new sponsor in an event. Requires the `write:sponsors` scope. Subject to rate limiting (100 req/15min) and daily write quota (10,000/day per token).
# Restore a deleted sponsor
Source: https://apidocs.sessionboard.com/api-reference/sponsor-writes/restore-a-deleted-sponsor
/api-reference/openapi.yaml post /v1/event/{eventId}/sponsors/{sponsorId}/restore
Restore a previously soft-deleted sponsor. Requires the `write:sponsors` scope.
# Soft-delete a sponsor
Source: https://apidocs.sessionboard.com/api-reference/sponsor-writes/soft-delete-a-sponsor
/api-reference/openapi.yaml delete /v1/event/{eventId}/sponsors/{sponsorId}
Soft-delete a sponsor. Can be restored with the restore endpoint. Requires the `write:sponsors` scope.
# Update a sponsor
Source: https://apidocs.sessionboard.com/api-reference/sponsor-writes/update-a-sponsor
/api-reference/openapi.yaml put /v1/event/{eventId}/sponsors/{sponsorId}
Update an existing sponsor. Requires the `write:sponsors` scope. Optionally send `updated_at` for optimistic concurrency control.
# Get a sponsor
Source: https://apidocs.sessionboard.com/api-reference/sponsors/get-a-sponsor
/api-reference/openapi.yaml get /v1/event/{eventId}/sponsors/{sponsorId}
Retrieve a single sponsor by ID.
# Search sponsors
Source: https://apidocs.sessionboard.com/api-reference/sponsors/search-sponsors
/api-reference/openapi.yaml post /v1/event/{eventId}/sponsors
Search and filter sponsors within an event.
# Transcriptions & Media
Source: https://apidocs.sessionboard.com/api-reference/transcriptions-and-media
Unified transcription API, session recordings, and media upload endpoints.
For step-by-step integration flows, start with the [Media & Transcriptions](/guides/uploading-media-and-transcriptions) guide. To **read** composed transcripts and AI artifacts in an app, see [Consuming session content](/guides/consuming-session-content).
## Five integration paths
| Path | Best for | Sidebar group |
| ---------------------- | ------------------------------------------------------------- | ------------------------------------------- |
| **Content packs** | One-call composed transcript + artifacts for apps | Event — Media → Transcriptions (`/content`) |
| **Transcriptions** | Raw CRUD — fragments, summaries, insights, translations | Event — Media → Transcriptions |
| **Session recordings** | Audio for a session's recording archive | Event — Media → Session recordings |
| **Media upload** | Video or audio files that should be transcribed automatically | Event — Media → Media upload |
| **Session files** | PDFs, PowerPoint, Word docs, and similar attachments | Event — Media → Session files |
**Session files** (slides, handouts, PDFs) support a one-call multipart upload (`POST .../files/upload`, max 50 MB) or direct-to-storage for larger files (up to 500 MB). Scopes: `read:sessions` / `write:sessions`. See [Uploading session files](/guides/uploading-session-files) and the [Session Files API overview](/api-reference/session-files).
## Resource model
Transcription data uses four types, all tied to a session:
| Type | Description |
| ------------- | ----------------------------------------------------------------------------- |
| `fragment` | Transcript text (synced by you or created when media transcription completes) |
| `summary` | Structured summary content |
| `insight` | Topics, entities, or key phrases |
| `translation` | Translated text linked to a source artifact |
Responses use the standard envelope:
```json theme={null}
{
"data": {
"id": "uuid",
"type": "fragment",
"session_id": "uuid",
"transcription": "...",
"created_at": "...",
"updated_at": "..."
}
}
```
List endpoints include `pagination` with `current_page`, `page_size`, `total_pages`, and `total_results`.
## Session & event content
Ready-to-render packs for partners and mobile apps. Not the same as session [composition](/api-reference/sessions-composition) (abstract/parent linking).
GET /v1/event//sessions//content
GET /v1/event//content
GET /v1/event//content/event
GET /v1/event//content/items/
Guide: [Consuming session content](/guides/consuming-session-content).
## Transcriptions
GET /v1/event//transcriptions
GET /v1/event//sessions//transcriptions
GET /v1/event//sessions//transcriptions/
POST /v1/event//sessions//transcriptions
## Session recordings
GET /v1/event//sessions//recordings
POST /v1/event//sessions//recordings
GET /v1/event//sessions//recordings/
POST .../recordings//complete
## Session files
Document attachments (PDF, PowerPoint, Word, images). Full playbook: [Uploading session files](/guides/uploading-session-files). API overview: [Session Files](/api-reference/session-files).
GET /v1/event//sessions//files
POST /v1/event//sessions//files/upload
POST /v1/event//sessions//files
POST .../files//complete
Replace, update metadata, delete
## Media upload
POST .../media/upload/initiate
GET /v1/event//sessions//media/
## Related reference
* [Media & Transcriptions guide](/guides/uploading-media-and-transcriptions) — step-by-step playbooks
* [Uploading session files](/guides/uploading-session-files) — PDF and document attachments
* [Session Files API overview](/api-reference/session-files)
* [Authentication & scopes](/authentication)
# Create a transcription artifact
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/create-a-transcription-artifact
/api-reference/openapi.yaml post /v1/event/{eventId}/sessions/{sessionId}/transcriptions
Requires `write:transcriptions` scope.
# Delete a transcription artifact
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/delete-a-transcription-artifact
/api-reference/openapi.yaml delete /v1/event/{eventId}/sessions/{sessionId}/transcriptions/{transcriptionId}
Requires `write:transcriptions` scope.
# Download a session content document
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/download-a-session-content-document
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}/content/documents/{documentType}
Streams `summary_pdf` or `summary_card`. Requires `read:transcriptions` scope.
# Download an event content document
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/download-an-event-content-document
/api-reference/openapi.yaml get /v1/event/{eventId}/content/documents/{documentType}
Streams `event_report` PDF. Requires `read:transcriptions` scope.
# Get a session transcription by ID
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/get-a-session-transcription-by-id
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}/transcriptions/{transcriptionId}
Requires `read:transcriptions` scope (legacy tokens with empty scopes pass).
# Get a single content item
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/get-a-single-content-item
/api-reference/openapi.yaml get /v1/event/{eventId}/content/items/{itemId}
Resolve one content item. `itemId` may be a session UUID (composed transcription),
a summary/insight/podcast UUID, or a document type (`summary_pdf`, `summary_card`,
`event_report`, `recap`). Document types `summary_pdf` / `summary_card` require
`session_id`. Requires `read:transcriptions` scope.
# Get a transcription by ID
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/get-a-transcription-by-id
/api-reference/openapi.yaml get /v1/event/{eventId}/transcriptions/{transcriptionId}
Requires `read:transcriptions` scope (legacy tokens with empty scopes pass).
# Get composed content for a session
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/get-composed-content-for-a-session
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}/content
Canonical one-call session pack for mobile and partner apps — composed
transcription elements, preferred summary, insights, podcast URL/status,
and summary PDF/card links. Distinct from session **composition**
(abstract/parent-child linking).
Requires `read:transcriptions` scope (legacy tokens with empty scopes pass).
# Get event-level content artifacts
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/get-event-level-content-artifacts
/api-reference/openapi.yaml get /v1/event/{eventId}/content/event
Event report document metadata and recap rollup (quotes, topics, summary excerpts).
Requires `read:transcriptions` scope. Default expand is `document,recap`.
# List composed session content for an event
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/list-composed-session-content-for-an-event
/api-reference/openapi.yaml get /v1/event/{eventId}/content
Paginated list of session content packs (composed transcript, preferred summary,
insights, podcast status, and document links). Prefer this over the raw
polymorphic transcriptions list for mobile and partner apps.
Requires `read:transcriptions` scope (legacy tokens with empty scopes pass).
Default packs are compact (`elements` empty on transcription items). Pass
`expand=items` (plus other types) for full element arrays.
# List transcriptions for a session
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/list-transcriptions-for-a-session
/api-reference/openapi.yaml get /v1/event/{eventId}/sessions/{sessionId}/transcriptions
Requires `read:transcriptions` scope (legacy tokens with empty scopes pass).
# List transcriptions for an event
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/list-transcriptions-for-an-event
/api-reference/openapi.yaml get /v1/event/{eventId}/transcriptions
Paginated list of transcription artifacts across all sessions. Filter by type, session_id, or language_code. Requires `read:transcriptions` scope (legacy tokens with empty scopes pass). Prefer `/content` for composed mobile-friendly packs.
# Update a transcription artifact
Source: https://apidocs.sessionboard.com/api-reference/transcriptions/update-a-transcription-artifact
/api-reference/openapi.yaml put /v1/event/{eventId}/sessions/{sessionId}/transcriptions/{transcriptionId}
Requires `write:transcriptions` scope.
# Authentication
Source: https://apidocs.sessionboard.com/authentication
Authenticate with API tokens or OAuth 2.1
The Sessionboard Public API supports two authentication methods:
1. **API Tokens** — Long-lived tokens for server-to-server integrations and scripts
2. **OAuth 2.1** — For AI assistants (Claude, ChatGPT) and user-authorized connections
API tokens are scoped to your organization and can be generated from the Sessionboard admin dashboard.
## Generate a Token
Log in to the Sessionboard admin dashboard and navigate to **Organization Settings** from the sidebar.
Select the **API Tokens** section within your organization settings.
Click **Generate Token**. Give the token a descriptive name and select the appropriate scopes for your use case.
Copy the generated token immediately. For security reasons, the full token value is only displayed once. Store it securely in your application's environment variables or secrets manager.
## Using the Token
Include the token in the `x-access-token` header on every API request.
```bash cURL theme={null}
curl -X GET https://public-api.sessionboard.com/v1/events \
-H "x-access-token: YOUR_TOKEN"
```
```javascript JavaScript theme={null}
const response = await fetch('https://public-api.sessionboard.com/v1/events', {
headers: {
'x-access-token': 'YOUR_TOKEN'
}
});
const data = await response.json();
```
```python Python theme={null}
import requests
response = requests.get(
'https://public-api.sessionboard.com/v1/events',
headers={'x-access-token': 'YOUR_TOKEN'}
)
data = response.json()
```
Keep your API tokens secure. Never commit tokens to source control, embed them in client-side code, or share them in public channels. If a token is compromised, revoke it immediately from the API Tokens settings page and generate a new one.
## Token Scopes
API tokens can be granted specific scopes to control access:
| Scope | Type | Description |
| ---------------------- | ----- | ------------------------------------------------------------------------------------------------------------ |
| `read:events` | Read | Access event data |
| `read:sessions` | Read | Access session data and list session file attachments |
| `read:contacts` | Read | Access speaker and contact data |
| `read:reports` | Read | Access saved reports |
| `read:dashboards` | Read | Access dashboards |
| `read:insights` | Read | Access Reports, Dashboards, and SbQL query APIs. Required for MCP. |
| `read:transcriptions` | Read | Access session transcriptions and recordings |
| `read:media` | Read | Access uploaded media items and transcription status |
| `write:sessions` | Write | Create, update, delete, and restore sessions; upload and manage session files |
| `write:contacts` | Write | Create, update, delete, and restore contacts |
| `write:exhibitors` | Write | Create, update, delete, and restore exhibitors |
| `write:sponsors` | Write | Create, update, delete, and restore sponsors |
| `write:fields` | Write | Create, update, and delete custom fields |
| `write:metadata` | Write | Create, update, and delete session metadata (rooms, tracks, etc.) |
| `write:transcriptions` | Write | Create, update, and delete transcriptions and session recordings |
| `write:media` | Write | Upload media files for automatic transcription |
| `write:events` | Write | Create, update, and delete agenda drafts, scheduling rules, personas, dashboards, widgets, and saved reports |
Legacy tokens (empty scopes array) get all read scopes implicitly but do **not** get write access. When generating a token, select only the scopes your integration requires.
Scoped read tokens must include the domain-specific read scope for each API area — for example, `read:events` alone does not grant access to transcription, media, or session file endpoints. Those require `read:transcriptions`, `read:media`, or `read:sessions` respectively.
For AI assistants like Claude and ChatGPT, Sessionboard supports OAuth 2.1 with PKCE. This allows users to authorize AI tools to access their event data through a secure consent flow.
See the full [OAuth 2.1 guide](/oauth) for setup instructions, token exchange, and available scopes.
**Quick overview:**
* Users authorize via a consent page at `appv2.sessionboard.com/oauth/consent`
* Tokens are issued by `public-api.sessionboard.com/oauth/token`
* Access tokens expire after 1 hour, refresh tokens after 7 days
* Tokens inherit the authorizing user's permissions (dynamic — changes take effect immediately)
```bash theme={null}
# Using an OAuth access token
curl https://public-api.sessionboard.com/v1/events \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```
# Changelog
Source: https://apidocs.sessionboard.com/changelog
What's new in the Sessionboard Public API
Release notes for the Sessionboard Public API. Entries are grouped by month (newest first). Breaking changes are called out explicitly.
API tokens created before scoped tokens were introduced continue to work with full access when no scopes are set. New tokens should request only the scopes your integration needs — see [Authentication](/authentication) and [OAuth](/oauth).
***
## July 2026
### July 20 — Session & event content packs
**Added — Composed content** (`read:transcriptions`)
One-call packs for mobile and partner apps — composed transcript elements (speaker turns, optional `interval_sec`), preferred summary, insights, podcast status/URL, and summary/event PDF links.
| Method | Path |
| ------ | -------------------------------------------------- |
| `GET` | `/v1/event/{eventId}/sessions/{sessionId}/content` |
| `GET` | `/v1/event/{eventId}/content` |
| `GET` | `/v1/event/{eventId}/content/event` |
| `GET` | `/v1/event/{eventId}/content/items/{itemId}` |
| `GET` | `.../content/documents/{documentType}` |
Raw `.../transcriptions` CRUD is unchanged. Content is not session [composition](/api-reference/sessions-composition).
**Documentation**
* New guide: [Consuming session content](/guides/consuming-session-content)
* Updated: [Transcriptions & Media](/api-reference/transcriptions-and-media)
### July 10 — Session files & upload paths
**Added — Session files** (`read:sessions` / `write:sessions`)
Attach PDFs, PowerPoint decks, Word docs, and similar files to a session.
| Path | Method | Endpoint | Max size |
| ------------------------ | -------- | ------------------------------------------------------- | -------- |
| **Simple upload** | `POST` | `/v1/event/{eventId}/sessions/{sessionId}/files/upload` | 50 MB |
| Direct-to-storage create | `POST` | `/v1/event/{eventId}/sessions/{sessionId}/files` | 500 MB |
| Complete | `POST` | `.../files/{fileId}/complete` | — |
| List | `GET` | `.../files` | — |
| Update | `PUT` | `.../files/{fileId}` | — |
| Replace | `POST` | `.../files/{fileId}/replace` | 500 MB |
| Delete | `DELETE` | `.../files/{fileId}` | — |
**Simple upload** — one multipart request with field `file`. Sessionboard detects size and MIME type, scans the file, and returns the attached file. No presigned URL steps.
**Direct-to-storage** — create → PUT bytes to signed URL → complete. Use for files over 50 MB (up to 500 MB) or when you prefer uploading straight to storage (standard presigned-URL pattern used by AWS, Stripe, and similar APIs).
Session-scoped creates use standard REST (`POST` on the collection path — no `/create` suffix). The `/create` suffix remains only where `POST` on the collection path is search (sessions, contacts, metadata entities, etc.).
**Documentation**
* New guide: [Uploading session files](/guides/uploading-session-files) — two-tab playbook (simple vs direct-to-storage)
* API overview: [Session Files](/api-reference/session-files)
### July 7 — Sessions & scopes
**Fixed**
* Embedded contact fields on session responses (`photo_url`, `company_name`, `title`, `address_country`, and related profile fields) now populate correctly on `speakers[]`, `chairpersons[]`, `moderators[]`, and `participants[]` in the event's default language.
* Participant ordering respects configured role sort order and per-participant `order`.
**Changed**
* Read routes for transcriptions and recordings require the `read:transcriptions` scope when your token has explicit scopes.
* Read routes for media items require the `read:media` scope when your token has explicit scopes.
* `read:transcriptions` and `read:media` added to the OAuth scope catalog.
**Documentation**
* Session participant model documented: `participants[]` vs legacy role arrays, `participant_role` shape, and contact fields available without `expand`.
### July 6 — Transcriptions, recordings & media upload
**Added — Transcriptions** (`read:transcriptions` / `write:transcriptions`)
| Method | Path |
| -------- | -------------------------------------------------------------- |
| `POST` | `/v1/event/{eventId}/sessions/{sessionId}/transcriptions` |
| `GET` | `/v1/event/{eventId}/sessions/{sessionId}/transcriptions` |
| `GET` | `/v1/event/{eventId}/sessions/{sessionId}/transcriptions/{id}` |
| `PUT` | `/v1/event/{eventId}/sessions/{sessionId}/transcriptions/{id}` |
| `DELETE` | `/v1/event/{eventId}/sessions/{sessionId}/transcriptions/{id}` |
| `GET` | `/v1/event/{eventId}/transcriptions` |
| `GET` | `/v1/event/{eventId}/transcriptions/{id}` |
Supports artifact types: `fragment`, `summary`, `insight`, and `translation`. Fragments written via the API appear in the event's Marketing Media transcript view.
**Added — Session recordings** (`read:transcriptions` / `write:transcriptions`)
| Method | Path |
| ------ | ------------------------------------------------------------------- |
| `POST` | `/v1/event/{eventId}/sessions/{sessionId}/recordings` |
| `GET` | `/v1/event/{eventId}/sessions/{sessionId}/recordings` |
| `GET` | `/v1/event/{eventId}/sessions/{sessionId}/recordings/{id}` |
| `POST` | `/v1/event/{eventId}/sessions/{sessionId}/recordings/{id}/complete` |
**Added — Media upload** (`read:media` / `write:media`)
Direct-to-S3 multipart upload for video or audio files, with automatic transcription when processing completes.
| Method | Path |
| ------ | ----------------------------------------------------------------- |
| `POST` | `/v1/event/{eventId}/sessions/{sessionId}/media/upload/initiate` |
| `POST` | `/v1/event/{eventId}/sessions/{sessionId}/media/upload/sign-part` |
| `POST` | `/v1/event/{eventId}/sessions/{sessionId}/media/upload/complete` |
| `POST` | `/v1/event/{eventId}/sessions/{sessionId}/media/upload/abort` |
| `GET` | `/v1/event/{eventId}/sessions/{sessionId}/media/{mediaItemId}` |
**Documentation**
* New guide: [Media & Transcriptions](/guides/uploading-media-and-transcriptions) (three integration playbooks).
* New reference page: [Transcriptions & Media](/api-reference/transcriptions-and-media).
* OpenAPI tags split into **Transcriptions**, **Session Recordings**, and **Media**.
### July 5 — Sessions 2.0 participants
**Added**
* `participants[]` on session search and get — flat list from the Sessions 2.0 model, including custom program roles (Author, Panelist, etc.). Always returned; no expand flag required.
* `participant_role` on legacy `speakers[]`, `chairpersons[]`, and `moderators[]` when the event has Sessions 2.0 roles configured.
* `expand=composition` on session search/get — returns composition status, target session summary, and source counts for abstract-to-session linking.
* Richer nested metadata on `language`, `track`, `level`, `room`, and `format` objects (`color`, `order`, `capacity`, timestamps, etc.) instead of `{ id, name }` only.
**Changed**
* Minimal `parent.subsessions[]` shape now includes `participants` alongside `speakers`.
### July 3 — Session write responses
**Added**
* `is_abstract` on session create and bulk create (requires Sessions 2.0 on the event).
* `expand=composition` on create/update/bulk responses — includes composition status block.
**Changed**
* Create, update, bulk, get, and list responses now share one formatter — write responses match read/search shape (nested metadata, composition, etc.).
* `expand=linked_sources` and `expand=composition` supported consistently across session CRUD handlers.
***
## June 2026
### June 18 — Subsessions
**Fixed**
* `GET /v1/event/{eventId}/sessions/{sessionId}` accepts a subsession UUID directly and returns the full session shape (with parent friendly-id keys).
* `expand=subsession_details` includes `is_public` on every subsession in `parent.subsessions[]`.
***
## May 2026
### May 22 — Subsession field parity
**Added**
* `expand=subsession_details` on session search and get — every item in `parent.subsessions[]` returns full parent-shape parity (`status`, `custom_fields`, `chairpersons`, `moderators`, `sponsors`, `exhibitors`, `tags`, nested metadata, and more). Default subsession shape is unchanged for backward compatibility.
* `GET /v1/event/{eventId}/sessions/{sessionId}` with a subsession UUID returns the full session DTO at the top level.
* `POST /v1/event/{eventId}/sessions/status` returns a minimal `subsessions[]` array on parent rows (id, friendly\_id, status, custom\_status, timestamps) for status-sync integrations.
**Documentation**
* Subsession expand behavior and `SubsessionDetailed` schema documented in the [API overview](/api-reference/overview).
### May 7 — Webhooks
**Documentation**
* Webhook payload schemas updated to match the current event shape.
***
## April 2026
### April 13 — OAuth token lifetimes
**Changed**
* OAuth access tokens expire after **24 hours** (previously shorter).
* OAuth refresh tokens expire after **90 days**.
### April 12 — Deep links & OAuth hardening
**Added**
* `admin_url` on session, contact, exhibitor, and sponsor responses — direct link to the record in the Sessionboard admin UI.
**Changed**
* OAuth Bearer tokens work with all MCP server tools.
* OAuth metadata URLs served correctly over HTTPS behind the load balancer.
### April 11 — OAuth 2.1 & rate limits
**Added**
* OAuth **write scopes** for sessions, contacts, exhibitors, sponsors, fields, metadata, and events.
* RFC 8707 **resource parameter** support on the token endpoint.
* **Per-token rate limit overrides** — contact support to raise limits for high-volume integrations.
* Browser-based OAuth: `/oauth/authorize` redirects to the consent UI.
* OAuth discovery at `/.well-known/oauth-authorization-server`.
**Documentation**
* [OAuth](/oauth) guide and [Rate limiting](/rate-limiting) page published.
### April 10 — Convenience routes & insights
**Added**
* **Convenience routes** for org-level dashboards, widgets, and saved reports at `/v1/dashboards`, `/v1/widgets`, and `/v1/queries` (in addition to event-scoped paths).
* Event-scoped insights, dashboards, widgets, and queries routed through the unified v1 proxy.
**Fixed**
* Widget create no longer returns 404 when `dashboardId` is in the path.
* Rules list handles missing pagination without error.
* Contact create/update returns profile fields correctly when locale casing differs.
### April 9 — Agenda planning & metadata
**Added**
* **Agenda drafts** — full CRUD for drafts, draft sessions, commit, and change history.
* **Scheduling rules** — create, read, update, delete.
* **Personas** — create, read, update, delete.
* **Event metadata CRUD** — rooms, tracks, tags, formats, levels, languages, and session statuses (read and write).
### April 7 — Entity write API (major release)
**Added**
* **Session CRUD** — create, update, delete, restore, bulk operations, and custom field updates.
* **Contact CRUD** — create, update, delete, restore, bulk, and list sessions for a contact.
* **Exhibitor & sponsor CRUD** — create, update, delete, restore, and bulk.
* **Custom field definitions** — create, update, delete.
* **Organization-scoped contact** read endpoints.
* **Bearer token** authentication alongside `X-Access-Token`.
* **Write scopes** enforced on all mutating routes.
**Documentation**
* Full OpenAPI schemas for all CRUD endpoints.
* Sidebar reorganized by org scope, event scope, and convenience routes.
### April 8 — Reliability
**Fixed**
* Error details from the API are forwarded through the proxy (clearer validation messages).
* `204 No Content` responses handled correctly on delete/restore.
* Scheduled smoke tests against the dev environment (ongoing quality monitoring).
***
## March 2026
### March 25 — Organization contacts
**Fixed**
* `GET /v1/organization/{orgId}/contacts/{contactId}` path corrected in the OpenAPI spec (was returning 404 for valid requests).
### March 23 — Documentation site
**Added**
* Public API documentation launched at [apidocs.sessionboard.com](https://apidocs.sessionboard.com) (Mintlify).
* [Insights & AI](/insights/overview) section — MCP server, SbQL, and analytics endpoints.
* EU region base URL documented: `https://public-api-eu.sessionboard.com`.
***
## Earlier capabilities
These endpoints predate 2026 but are part of the current API surface:
* **Session & speaker search** — `POST /v1/event/{eventId}/sessions`, speaker search, and individual session get (with 3-minute cache on get and search).
* **GDPR** — `GET` and `POST /v1/gdpr/requests`.
* **Webhooks** — real-time notifications on data changes ([Webhooks](/webhooks)).
* **Insights** — SbQL execute, AI query generation, saved reports, and dashboards ([Insights overview](/insights/overview)).
# Consuming session content
Source: https://apidocs.sessionboard.com/guides/consuming-session-content
One-call composed transcripts, summaries, insights, podcasts, and PDFs for mobile and partner apps.
Use the **content** endpoints when you want a ready-to-render pack for a session or event — not the raw polymorphic transcriptions list.
**Content** is not the same as session **composition** (abstract → parent/child linking). Composition docs live under [Sessions & Composition](/api-reference/sessions-composition).
## When to use which API
| Goal | Endpoint family |
| ---------------------------------------------------------- | -------------------------------------- |
| Display a full session transcript + AI artifacts in an app | `GET .../sessions/{sessionId}/content` |
| Browse packs across an event | `GET .../content` (paginated) |
| Event report PDF + recap rollup | `GET .../content/event` |
| Create/update raw fragments, summaries, insights | `.../transcriptions` CRUD |
Scope: `read:transcriptions` (legacy tokens with empty scopes still pass for reads).
## Session pack (canonical)
```bash theme={null}
curl --request GET \
--url 'https://public-api.sessionboard.com/v1/event/6046/sessions/{sessionId}/content' \
--header 'x-access-token: YOUR_TOKEN'
```
Response shape (proxy envelope):
```json theme={null}
{
"data": {
"id": "session-uuid",
"event_id": 6046,
"title": "Keynote",
"speakers": [{ "id": "0", "label": "Speaker 0", "name": null }],
"has_transcription": true,
"has_summary": true,
"has_podcast": false,
"items": [
{
"type": "transcription",
"text": "Full joined transcript…",
"elements": [
{
"value": "Speaker turn text…",
"speaker": { "id": "0", "label": "Speaker 0", "name": null },
"start_time": 2.23,
"end_time": 51.88,
"fragment_ids": ["…"]
}
]
},
{ "type": "summary", "provider": "openai", "content": { "summary": "…", "key_points": [] } },
{ "type": "insight", "insight_type": "thought", "name": "…" },
{ "type": "podcast", "status": "none", "url": null },
{ "type": "document", "document_type": "summary_pdf", "url": "https://…/sessions/{sessionId}/content/documents/summary_pdf" }
]
}
}
```
### Join transcript text
```js theme={null}
const transcription = data.items.find((i) => i.type === "transcription");
const fullText =
transcription?.text ??
transcription?.elements?.map((e) => e.value).join(" ") ??
"";
```
`elements.map(e => e.value).join(' ')` always equals `text` when elements are present.
### Speaker turns vs time windows
* Default: consecutive same-speaker fragments → one element (speaker turns).
* `?interval_sec=60`: rechunk same-speaker blocks into \~60s windows (speaker changes still split).
### Slim the payload
```bash theme={null}
# Transcript + summary only
.../content?expand=transcription,summary
```
### Prefer a summary provider
```bash theme={null}
.../content?provider=claude
```
When multiple rolling summaries exist, the newest is returned unless `provider` matches.
## Event list
```bash theme={null}
curl --request GET \
--url 'https://public-api.sessionboard.com/v1/event/6046/content?page=1&page_size=25' \
--header 'x-access-token: YOUR_TOKEN'
```
Returns `{ data: [ SessionContent, … ], pagination: { current_page, page_size, total_pages, total_results } }`.
List packs are **compact** by default (transcription `text` without full `elements`). Pass `expand=items` (with other types) for full element arrays.
## Event-level artifacts
```bash theme={null}
GET /v1/event/{eventId}/content/event
```
Includes `document` (`event_report`) and `recap` (quotes, topics, summary excerpts).
## Podcasts and PDFs
| Item | Behavior |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `podcast` | `status`: `none` \| `queued` \| `generating` \| `ready` \| `failed`. When ready, `url` is a time-limited download link; refresh before `expires_at`. |
| `document` | Metadata + `url` pointing at authenticated download routes (`summary_pdf`, `summary_card`, `event_report`). |
Generation of podcasts/PDFs is not triggered by the public API — content endpoints are read-only.
## Single item
```bash theme={null}
GET /v1/event/{eventId}/content/items/{itemId}
```
| `itemId` | Result |
| -------------------------------- | ------------------------------------------- |
| Session UUID | Composed `transcription` item |
| Summary / insight / podcast UUID | That item |
| `summary_pdf` / `summary_card` | Document metadata (`?session_id=` required) |
| `event_report` / `recap` | Event-level item |
## Related
* [Transcriptions & Media overview](/api-reference/transcriptions-and-media)
* [Uploading media and transcriptions](/guides/uploading-media-and-transcriptions)
# Media & Transcriptions
Source: https://apidocs.sessionboard.com/guides/uploading-media-and-transcriptions
Step-by-step playbooks for syncing transcript text, uploading media files, adding session audio, and pulling composed content.
Use this guide to pick the right workflow, then follow the steps. All paths are session-scoped unless noted.
## Pick your playbook
**You already have the words** (full transcript, summary, topics, or translation) and want them on a session.
Requires `write:transcriptions` to create; `read:transcriptions` to list or verify.
**You have a video or audio file** (MP4, MOV, MP3, etc.) and want Sessionboard to transcribe it automatically.
Requires `write:media` to upload; `read:media` to check status. If you upload on a session URL, transcript lines appear in the session transcription list when processing finishes — no separate fragment upload needed.
**You have an audio file for a session’s recording archive** (live capture, imported audio, or segments to stitch later).
Requires `write:transcriptions`. Accepts common audio formats; Sessionboard normalizes the file when you mark the upload complete.
**You want a ready-to-render pack** for a mobile app or partner integration — composed transcript, summary, insights, podcast, and PDF links in one call.
Requires `read:transcriptions`. Prefer this over the raw polymorphic transcriptions list.
Not sure which to use? **Playbook 1** is for text you generate elsewhere. **Playbook 2** is for files you want transcribed inside Sessionboard (same flow as Import → Upload in the admin UI). **Playbook 3** is for audio tied to the session recording archive, not the media library. **Playbook 4** is for reading composed session/event content into an app.
For **PDFs, PowerPoint, and other session attachments** (slides, handouts), use the separate [Uploading session files](/guides/uploading-session-files) guide — different scopes (`write:sessions`) and endpoints.
***
## Before you begin
Replace `{eventId}` and `{sessionId}` with your event and session IDs. Send your API token on every request:
```http theme={null}
X-Access-Token: {your-token}
```
Create tokens and scopes in [Authentication](/authentication). Writes always need an explicit scope; legacy tokens with empty scopes can read but cannot create or upload.
***
## Playbook 1 — Sync transcript text
### When to use it
* You produced a transcript outside Sessionboard and want it on a session.
* You need summaries, topic insights, or translations alongside transcript text.
### Transcription types
| `type` | What to send |
| ------------- | ----------------------------------------------------------------------------------------------------------- |
| `fragment` | Transcript text (`transcription`). Use one fragment for a full session transcript, or many for timed lines. |
| `summary` | Summary content (`content`). |
| `insight` | Topics or entities (`name`, `insight_type`). Optionally link to fragments with `fragment_ids`. |
| `translation` | Translated text (`translated_text`) linked to a source fragment or summary. |
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/transcriptions
Content-Type: application/json
```
**Example — full session transcript as one fragment:**
```json theme={null}
{
"type": "fragment",
"transcription": "Welcome everyone to today's keynote...",
"provider": "my-platform",
"is_partial": false,
"language_code": "en"
}
```
Set `is_partial` to `false` when the text is final. The response includes the new `id`.
```http theme={null}
GET /v1/event/{eventId}/sessions/{sessionId}/transcriptions
GET /v1/event/{eventId}/sessions/{sessionId}/transcriptions/{transcriptionId}
```
```http theme={null}
PUT /v1/event/{eventId}/sessions/{sessionId}/transcriptions/{transcriptionId}
DELETE /v1/event/{eventId}/sessions/{sessionId}/transcriptions/{transcriptionId}
```
### Event-wide listing
To search across all sessions in an event:
```http theme={null}
GET /v1/event/{eventId}/transcriptions?page=1&page_size=25&type=fragment
```
By default, in-progress live-capture lines (`is_partial=true`) are hidden. Add `include_partial=true` to include them.
***
## Playbook 2 — Upload a media file
### When to use it
* You have a **video or audio file** and want automatic transcription.
* The file should appear in Sessionboard’s media hub for the session.
### What happens
1. You upload the file in parts (large files supported, up to **50 GB**).
2. Sessionboard processes the file and runs transcription.
3. You poll until `transcript_status` is `ready`.
4. If the upload URL includes `{sessionId}`, transcript **fragments** are added to that session automatically. You do **not** need Playbook 1 for the same content.
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/media/upload/initiate
Content-Type: application/json
```
```json theme={null}
{
"filename": "keynote-recording.mp4",
"content_type": "video/mp4",
"size_bytes": 524288000
}
```
Response includes `key`, `upload_id`, and part sizing. Keep these for the next steps.
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/media/upload/sign-part
Content-Type: application/json
```
```json theme={null}
{
"key": "{key from initiate}",
"upload_id": "{upload_id from initiate}",
"part_numbers": [1, 2, 3]
}
```
Response returns a URL per part number.
`PUT` the file bytes to each URL from the previous step. Save the `ETag` header from each response — you need it to finish the upload.
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/media/upload/complete
Content-Type: application/json
```
```json theme={null}
{
"key": "{key}",
"upload_id": "{upload_id}",
"filename": "keynote-recording.mp4",
"size_bytes": 524288000,
"parts": [
{ "part_number": 1, "etag": "\"abc123\"" },
{ "part_number": 2, "etag": "\"def456\"" }
]
}
```
Response includes `mediaItemId`. The session is taken from the URL — do not send `session_id` in the body.
```http theme={null}
GET /v1/event/{eventId}/sessions/{sessionId}/media/{mediaItemId}
```
Check `transcript_status`:
| Status | Meaning |
| ------------ | ----------------------------------------------------------------------- |
| `queued` | Waiting to process |
| `processing` | Transcription in progress |
| `ready` | Done — session fragments are available if you uploaded on a session URL |
| `failed` | Processing failed — inspect the item or retry upload |
Then list session transcriptions to read the generated fragments:
```http theme={null}
GET /v1/event/{eventId}/sessions/{sessionId}/transcriptions?type=fragment
```
To cancel an in-progress upload, call `POST .../media/upload/abort` with `key` and `upload_id`.
***
## Playbook 3 — Upload session audio
### When to use it
* You have **audio for a session’s recording archive** (not the media library flow in Playbook 2).
* You need audio available for session playback, stitching, or downstream transcription inside Sessionboard.
### Supported file types
`wav`, `mp3`, `m4a`, `aac`, `flac`, `ogg`, `pcm`
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/recordings
Content-Type: application/json
```
```json theme={null}
{
"filename": "session-audio.wav",
"content_type": "audio/wav",
"size_bytes": 1048576
}
```
Response includes a recording `id` and an `upload.url`. Use that URL for the next step.
`PUT` the audio bytes to `upload.url` using the `Content-Type` from the response headers.
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/recordings/{recordingId}/complete
Content-Type: application/json
```
```json theme={null}
{
"duration_seconds": 3600,
"file_size_bytes": 1048576
}
```
Both fields are optional but help accuracy. Sessionboard accepts common formats and prepares the file for the recording pipeline when you complete.
Calling **complete** again on an already-completed recording returns success without duplicating work.
```http theme={null}
GET /v1/event/{eventId}/sessions/{sessionId}/recordings/{recordingId}
GET /v1/event/{eventId}/sessions/{sessionId}/recordings
```
***
## Playbook 4 — Pull composed content
### When to use it
* You are building a **mobile app, partner integration, or site** that needs a ready-to-render transcript plus AI artifacts.
* You want **one call per session** (or a paginated event list) instead of paging the mixed raw `.../transcriptions` list and stitching fragments yourself.
This is **not** session [composition](/api-reference/sessions-composition) (abstract → parent/child linking). Content packs live under `/content`.
Requires `read:transcriptions` (legacy tokens with empty scopes still pass for reads).
### What you get
Each session pack returns an `items[]` array. Filter by `type`:
| `type` | Meaning |
| --------------- | ------------------------------------------------------------- |
| `transcription` | Composed speaker turns (`elements[]`) plus full joined `text` |
| `summary` | Preferred rolling/final summary |
| `insight` | Thoughts, themes, topics, key phrases, etc. |
| `podcast` | Digest audio status + time-limited `url` when ready |
| `document` | Links to summary PDF / summary card downloads |
Event-level packs add `event_report` and a `recap` rollup.
```http theme={null}
GET /v1/event/{eventId}/sessions/{sessionId}/content
```
Optional query params:
| Param | Purpose |
| -------------- | ------------------------------------------------------------------------------- |
| `expand` | Slim the pack, e.g. `expand=transcription,summary` |
| `interval_sec` | Rechunk same-speaker elements into \~N-second windows (default = speaker turns) |
| `provider` | Prefer a summary provider (`claude` or `openai`) when multiple exist |
Example response shape:
```json theme={null}
{
"data": {
"id": "{sessionId}",
"event_id": 6046,
"title": "Keynote",
"speakers": [{ "id": "0", "label": "Speaker 0", "name": null }],
"has_transcription": true,
"has_summary": true,
"has_podcast": false,
"items": [
{
"type": "transcription",
"text": "Full joined transcript…",
"elements": [
{
"value": "Speaker turn text…",
"speaker": { "id": "0", "label": "Speaker 0", "name": null },
"start_time": 2.23,
"end_time": 51.88
}
]
},
{ "type": "summary", "provider": "openai", "content": { "summary": "…", "key_points": [] } },
{ "type": "insight", "insight_type": "thought", "name": "…" },
{ "type": "podcast", "status": "none", "url": null },
{
"type": "document",
"document_type": "summary_pdf",
"url": "https://public-api.sessionboard.com/v1/event/{eventId}/sessions/{sessionId}/content/documents/summary_pdf"
}
]
}
}
```
Join transcript text in your client:
```js theme={null}
const transcription = data.items.find((i) => i.type === "transcription");
const fullText =
transcription?.text ??
transcription?.elements?.map((e) => e.value).join(" ") ??
"";
```
```http theme={null}
GET /v1/event/{eventId}/content?page=1&page_size=25
```
Returns `{ data: [ SessionContent, … ], pagination: { current_page, page_size, total_pages, total_results } }`.
List packs are **compact** by default (transcription `text` without full `elements`). Pass `expand=items` (with other types) for full element arrays:
```http theme={null}
GET /v1/event/{eventId}/content?page=1&page_size=25&expand=transcription,summary,insight,podcast,document,items
```
```http theme={null}
GET /v1/event/{eventId}/content/event
```
Returns the event report document metadata and a recap rollup (quotes, topics, summary excerpts). Default expand is `document,recap`.
Use the `url` on a `document` item, or call directly:
```http theme={null}
GET /v1/event/{eventId}/sessions/{sessionId}/content/documents/summary_pdf
GET /v1/event/{eventId}/sessions/{sessionId}/content/documents/summary_card
GET /v1/event/{eventId}/content/documents/event_report
```
These stream binary PDF/PNG. Send the same `X-Access-Token`. Podcast `url` values are time-limited — refresh the content pack before `expires_at`.
Full reference, item catalog, and single-item fetch (`GET .../content/items/{itemId}`) live in [Consuming session content](/guides/consuming-session-content). Keep using Playbooks 1–3 (or live capture) to **write** data; use Playbook 4 to **read** the composed view.
***
## Scopes quick reference
| Scope | Use it for |
| ---------------------- | --------------------------------------------------------------- |
| `read:transcriptions` | List/get transcriptions, recordings, and composed content packs |
| `write:transcriptions` | Create, update, delete transcriptions; upload session audio |
| `read:media` | Check media upload and transcription status |
| `write:media` | Multipart media upload |
Scoped read tokens must include the matching read scope. For example, `read:events` alone does **not** allow transcription or media GET endpoints.
***
## Related reference
* [Consuming session content](/guides/consuming-session-content) — content packs in depth
* [Transcriptions & Media API overview](/api-reference/transcriptions-and-media)
* [Uploading session files](/guides/uploading-session-files) — PDFs, PowerPoint, and document attachments
* [Authentication & scopes](/authentication)
* [OpenAPI — transcriptions endpoints](/api-reference/openapi.yaml)
# Uploading session files
Source: https://apidocs.sessionboard.com/guides/uploading-session-files
Attach PDFs, PowerPoint decks, and other documents to a session via the Public API.
Use this guide to upload documents to a session — the same Session Files you manage in the admin UI and speaker portal (slides, handouts, PDFs, and similar).
This is **not** the media or recording upload flow. Use [Media & Transcriptions](/guides/uploading-media-and-transcriptions) for video/audio that should be transcribed or stored as session recordings.
## Pick your upload path
**Best for:** most integrations — one API call, no S3 steps. Sessionboard detects file size and MIME type from the bytes you send.
| | |
| ------------ | ------------------------------------------------------------ |
| **Endpoint** | `POST /v1/event/{eventId}/sessions/{sessionId}/files/upload` |
| **Max size** | **50 MB** |
| **Scope** | `write:sessions` |
Optional form fields: `title`, `assigned_participant_id` (contact UUID on the session).
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/files/upload
Content-Type: multipart/form-data
X-Access-Token: {your-token}
```
**curl**
```bash theme={null}
curl -X POST "https://public-api.sessionboard.com/v1/event/{eventId}/sessions/{sessionId}/files/upload" \
-H "X-Access-Token: $TOKEN" \
-F "file=@handout.pdf" \
-F "title=Session handout"
```
**Node.js (form-data)**
```js theme={null}
import fs from 'node:fs';
import FormData from 'form-data';
const form = new FormData();
form.append('file', fs.createReadStream('./handout.pdf'));
form.append('title', 'Session handout');
const res = await fetch(uploadUrl, {
method: 'POST',
headers: { 'X-Access-Token': token, ...form.getHeaders() },
body: form
});
```
The multipart field name must be **`file`**. You do **not** send `filename`, `size_bytes`, or `content_type` — Sessionboard infers them from the upload.
On success (`201`) you get the finalized file `Content` object — same shape as after the direct-to-storage **complete** step:
```json theme={null}
{
"data": {
"id": "a1b2c3d4-....",
"filename": "handout.pdf",
"title": "Session handout",
"size": 512000,
"mimetype": "application/pdf",
"url": "https://content.sessionboard.com/..."
}
}
```
Security scanning runs before the response is returned. No follow-up call is required.
```http theme={null}
GET /v1/event/{eventId}/sessions/{sessionId}/files
```
**Best for:** files **larger than 50 MB** (up to **500 MB**), or when you prefer uploading bytes straight to Sessionboard storage (same pattern as [session recordings](/guides/uploading-media-and-transcriptions#playbook-3-%E2%80%94-upload-session-audio)).
| | |
| ------------ | ------------------------------------- |
| **Flow** | create → PUT to signed URL → complete |
| **Max size** | **500 MB** |
| **Scope** | `write:sessions` |
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/files
Content-Type: application/json
```
```json theme={null}
{
"filename": "large-deck.pptx",
"size_bytes": 52428800,
"title": "Full slide archive"
}
```
`size_bytes` must match the file on disk. `content_type` is optional — inferred from the filename when omitted.
Response includes `data.id` and `data.upload.url` for the next step.
Upload the raw file to `data.upload.url` with the `Content-Type` from `data.upload.headers`. Do **not** send your API token to the storage URL.
```http theme={null}
POST /v1/event/{eventId}/sessions/{sessionId}/files/{fileId}/complete
```
Sessionboard verifies the object, scans the bytes, and attaches the file.
***
## Before you begin
* API token with **`write:sessions`** (list/read also needs **`read:sessions`** when your token uses explicit scopes)
* Your `{eventId}` and `{sessionId}`
Send your token on every API request:
```http theme={null}
X-Access-Token: {your-token}
```
### Common file types
| Kind | Examples |
| ------------- | ------------------------ |
| Documents | PDF, DOC, DOCX |
| Presentations | PPT, PPTX |
| Spreadsheets | XLS, XLSX |
| Images | PNG, JPG, GIF, WEBP, SVG |
Executable and installer files (for example `.exe`, `.msi`, `.dmg`, `.sh`) are rejected on all paths.
***
## Update metadata
Change the display title or assigned participant without re-uploading:
```http theme={null}
PUT /v1/event/{eventId}/sessions/{sessionId}/files/{fileId}
Content-Type: application/json
```
```json theme={null}
{
"title": "Updated slide deck",
"assigned_participant_id": "contact-uuid-or-null"
}
```
***
## Replace or delete
**Replace** (direct-to-storage flow only today): `POST .../files/{fileId}/replace` → PUT bytes → `POST .../complete`.
**Delete:** `DELETE .../files/{fileId}` → `204 No Content`.
***
## Common errors
| Situation | What you'll see |
| ------------------------------------------------- | ----------------------------------- |
| Simple upload over 50 MB | `400` — use direct-to-storage flow |
| Direct create over 500 MB | `400` — file too large |
| Missing multipart `file` field | `400` `VALIDATION_ERROR` |
| Missing `filename` / `size_bytes` (direct create) | `400` `VALIDATION_ERROR` |
| Executable / installer type | `400` — file type not allowed |
| Called **complete** before PUT | `400` — upload not found in storage |
| Missing `write:sessions` | `403` |
| Unknown `fileId` / session | `404` |
***
## Scopes quick reference
| Action | Scope |
| ------------------------------------------------------ | ---------------- |
| List files | `read:sessions` |
| Upload / create / complete / replace / update / delete | `write:sessions` |
## Related reference
* [Session Files API overview](/api-reference/session-files)
* [Transcriptions & Media](/api-reference/transcriptions-and-media)
* [Authentication & scopes](/authentication)
# MCP Server
Source: https://apidocs.sessionboard.com/insights/mcp-server
Connect AI assistants to Sessionboard via Model Context Protocol
**Early Access** — The MCP Server is currently available to select organizations. Reach out to your Sessionboard account manager to get early access to this feature.
The Sessionboard MCP (Model Context Protocol) server allows AI assistants like Claude to query and manage your event data directly. Built on the [Model Context Protocol](https://modelcontextprotocol.io/) standard by Anthropic, the MCP server exposes 27 consolidated tools covering read access, write operations, analytics, and agenda planning.
## What is MCP?
Model Context Protocol is an open standard that enables AI assistants to securely connect to external data sources and tools. Instead of copying data into prompts, MCP lets the AI query and update your data on demand through a structured interface.
## Prerequisites
Three things must be enabled before the MCP server will accept requests:
1. **AI must be enabled for your organization** — Contact Sessionboard support or your account manager to enable AI features for your organization.
2. **MCP access must be enabled on your organization** — This is a separate feature flag that grants access to the MCP server and Reports / Dashboards query endpoints (`/v1/insights/...`).
3. **MCP must be enabled on your API token** — When generating or editing an API token, ensure the **MCP Access** toggle is turned on and the **read:insights** scope is granted. For write operations, add the appropriate write scopes (e.g., `write:sessions`, `write:contacts`, `write:events`).
If any of these are missing, MCP requests will return a `403 Forbidden` error.
## Setup
Create an API token in the Sessionboard admin dashboard with the **read:insights** scope and **MCP Access** enabled. Add write scopes if you want the AI to create or update data. See [Authentication](/authentication) for detailed instructions.
Add the Sessionboard MCP server to your AI client's configuration. The exact setup depends on your client.
**Remote connection (Claude Desktop, Claude Code, ChatGPT, etc.):**
```json theme={null}
{
"mcpServers": {
"sessionboard": {
"url": "https://mcp.sessionboard.com/mcp"
}
}
}
```
When you connect, the MCP server will walk you through OAuth authorization automatically — no need to configure tokens manually.
For EU-hosted organizations, use `https://mcp-eu.sessionboard.com/mcp` instead.
Ask your AI assistant questions about your event data in natural language. The assistant will use the MCP tools to query Sessionboard and return results.
## Available Tools (27)
The MCP server exposes 27 tools organized into 3 categories. Write operations use a `manage_*` pattern — one tool per entity with an `action` parameter to pick the operation (e.g., `action: "create"`).
All tools include [MCP annotations](https://modelcontextprotocol.io/docs/concepts/tools#tool-annotations) for safe AI behavior — read tools are marked `readOnlyHint: true`, write tools are marked `destructiveHint: false`, and all are `openWorldHint: false`.
### Search & Analytics (8 tools)
Find events, ask questions about your data, and explore your schema.
| Tool | Description |
| -------------------- | ----------------------------------------------------------------------------- |
| `list_events` | List all events in the organization |
| `find_event` | Search events by name |
| `get_event_overview` | Event summary — session counts, speakers, tracks, status breakdown |
| `get_schema` | Browse your data model — entities, fields, and relationships |
| `query_data` | Ask a question in plain English and get results (AI writes the query for you) |
| `execute_sbql` | Run a SbQL query directly with pagination |
| `get_suggestions` | Get suggested queries based on your data |
| `get_widget_schema` | Widget types, configs, and grid layout rules for dashboards |
### Read Details (4 tools)
Fetch sessions and contacts. All read-only and paginated.
| Tool | Description |
| --------------- | ---------------------------------------------------------- |
| `list_sessions` | List sessions for an event (paginated, up to 100 per page) |
| `get_session` | Get a single session by ID with full details |
| `list_contacts` | List contacts for an event (paginated, up to 100 per page) |
| `get_contact` | Get a single contact by ID with full details |
### Create & Manage (15 tools)
Each `manage_*` tool handles all operations for an entity — create, update, delete, and more — using an `action` parameter. For example, `manage_session` with `action: "create"` creates a session, while `action: "update"` updates one.
| Tool | Actions | Scope | Description |
| ------------------------ | -------------------------------------------------------------------- | --------------------------------- | ---------------------------------------------------------------------------- |
| `manage_metadata` | `list`, `create`, `update` | `write:metadata` / `write:fields` | Rooms, tracks, tags, formats, levels, languages, statuses, and custom fields |
| `manage_session` | `create`, `update`, `restore`, `update_fields` | `write:sessions` | Session CRUD + custom field values |
| `manage_contact` | `create`, `update`, `restore` | `write:contacts` | Contact CRUD (find-or-create by email) |
| `manage_exhibitor` | `create`, `update`, `restore` | `write:exhibitors` | Exhibitor CRUD |
| `manage_sponsor` | `create`, `update`, `restore` | `write:sponsors` | Sponsor CRUD |
| `manage_agenda_draft` | `list`, `get`, `create`, `update`, `delete`, `get_changes`, `commit` | `write:events` | Agenda draft lifecycle |
| `manage_draft_sessions` | `list`, `create`, `update`, `delete`, `bulk` | `write:events` | Session placements in drafts |
| `manage_event_rules` | `list`, `get`, `create`, `update`, `delete` | `write:events` | Scheduling rules and constraints |
| `manage_personas` | `list`, `get`, `create`, `update`, `delete` | `write:events` | Evaluation personas |
| `manage_event_dashboard` | `list`, `get`, `create`, `update`, `delete` | `write:events` | Event-scoped dashboards |
| `manage_event_widget` | `create`, `update`, `delete` | `write:events` | Event dashboard widgets |
| `manage_event_report` | `list`, `run`, `create`, `create_from_nl`, `update`, `delete` | `write:events` | Event-scoped saved reports |
| `manage_org_dashboard` | `list`, `get`, `create`, `update`, `delete` | `write:events` | Org-level dashboards (cross-event) |
| `manage_org_widget` | `create`, `update`, `delete` | `write:events` | Org-level dashboard widgets |
| `manage_org_report` | `list`, `run`, `create`, `create_from_nl`, `update`, `delete` | `write:events` | Org-level saved reports (cross-event) |
## Parameter Conventions
* **Event scoping** — All event-scoped tools require `event_id` (snake\_case string).
* **Action selection** — Consolidated tools use `action` to pick the operation (e.g., `action: "create"`).
* **Entity IDs** — snake\_case: `session_id`, `contact_id`, `entity_id`, `draft_id`, `widget_id`, `query_id`.
* **Optimistic concurrency** — Update actions require `updated_at` (ISO 8601 timestamp from the last read). Returns `409 Conflict` if the entity was modified since.
## Result Size Safety
All results are automatically truncated to prevent context window overflow:
* **List results** — Capped at 50 items. When truncated, the response includes `truncated: true`, `total_count`, and a `hint` with guidance on pagination.
* **Query results** — Capped at 100 rows with truncation metadata.
* **SbQL queries** — `execute_sbql` and `query_data` default to a 50-row limit. Use the `limit` parameter for more.
## Resources
The MCP server also exposes two [MCP resources](https://modelcontextprotocol.io/docs/concepts/resources) that AI clients can load into context:
| URI | Description |
| --------------- | ----------------------------------------------------------------------- |
| `sbql://schema` | The SbQL schema — entities, fields, relationships, and format functions |
| `sbql://events` | List of events in the organization with metadata |
## Prompt Templates
Pre-built templates that structure the AI's approach to common report types:
| Prompt | Description |
| -------------------- | ------------------------------------------------------------------- |
| `speaker_roster` | Generate a speaker roster with contact info and session assignments |
| `session_schedule` | Generate a day-by-day session schedule grid |
| `evaluation_summary` | Generate an evaluation/review score analysis |
| `task_status` | Show outstanding tasks across speakers and exhibitors |
## Security
* **Org isolation** — The SbQL compiler injects `org_id` into every query from the authenticated token. Prompt injection cannot access other organizations' data.
* **PII obfuscation** — Enabled by default. Emails become `j***@a***.com`, phone numbers become `***-***-4567`. Org admins can toggle this per-token.
* **Scoped access** — Tokens are restricted to specific scopes and optionally to specific events.
* **Audit logging** — Every API call is recorded with source, method, response time, and token ID.
## Example Conversations
Once connected, you can ask questions like:
* "How many sessions are accepted for this year's conference?"
* "Show me the top 10 speakers by number of sessions."
* "What's the breakdown of sessions by track and status?"
* "List all sessions that don't have a room assigned yet."
* "Create a new track called 'AI & Machine Learning' with color #4F46E5."
* "Build a dashboard showing session counts by status and track."
* "Create a draft agenda and schedule the keynote in the Main Hall at 9am."
# Reports & Dashboards
Source: https://apidocs.sessionboard.com/insights/overview
API access to Sessionboard Reports, Dashboards, and SbQL queries
**Early Access** — Reports, Dashboards, and related query APIs are currently available to select organizations. Reach out to your Sessionboard account manager to get early access.
These endpoints power **Reports** and **Dashboards** in Sessionboard — the same surfaces organizers use in the product to explore session and speaker data, run saved reports, and view dashboard widgets.
Under the hood, queries use **SbQL** (Sessionboard Query Language). You can also convert natural language into SbQL, discover the query schema, and connect AI assistants via the [MCP Server](/insights/mcp-server).
API tokens need the **`read:insights`** scope (the scope name is historical; it gates Reports, Dashboards, and SbQL access). See [Authentication](/authentication).
## Prerequisites
1. **Organization-level:** AI / analytics features must be enabled for your organization. Contact your Sessionboard account manager.
2. **Token-level:** Grant **`read:insights`**, and turn on **MCP Access** on the token if you will use the MCP server or Insights-prefixed query routes.
## What this covers
| Capability | Product mapping | Description |
| -------------------- | ------------------------- | -------------------------------------------------- |
| **Saved reports** | Reports | List and run saved queries created in Sessionboard |
| **Dashboards** | Dashboards | Retrieve dashboard configs and widget data |
| **Execute SbQL** | Reports / ad-hoc analysis | Run SbQL against your event data |
| **Generate SbQL** | AI assist | Turn natural language into SbQL |
| **Schema discovery** | Query builder | Entities, fields, and relationships you can query |
| **Suggestions** | Query assist | Contextual query suggestions |
Endpoint paths still use the `/v1/insights/...` prefix (for example `POST /v1/insights/execute`, `GET /v1/insights/queries`). That prefix is the public API namespace — not a separate product called Insights.
## Learn more
Query language syntax, entities, and examples.
Connect Claude and other AI assistants to your event data.
# SbQL Reference
Source: https://apidocs.sessionboard.com/insights/sbql
Sessionboard Query Language reference
**Early Access** — SbQL and the Reports / Dashboards query APIs are currently available to select organizations. Reach out to your Sessionboard account manager to get early access.
SbQL (Sessionboard Query Language) is a SQL-like query language purpose-built for querying Sessionboard event data. It provides a familiar syntax for selecting, filtering, joining, and aggregating data across sessions, speakers, contacts, and other event entities.
## Basic Syntax
SbQL follows standard SELECT-FROM-WHERE patterns:
```sql theme={null}
SELECT session.title, session.status
FROM sessions
WHERE session.status = 'accepted'
```
## Joins and Aggregations
Join entities to combine related data and use aggregate functions for analytics:
```sql theme={null}
SELECT speaker.full_name, COUNT(session.id) AS session_count
FROM speakers
JOIN sessions
GROUP BY speaker.full_name
ORDER BY session_count DESC
```
## Filtering with Conditions
Use standard comparison operators and logical connectives:
```sql theme={null}
SELECT session.title, session.start_date, track.name
FROM sessions
JOIN tracks
WHERE session.status = 'accepted'
AND track.name = 'Keynotes'
ORDER BY session.start_date ASC
```
## Schema Discovery
Use the Insights schema endpoints to discover the entities and fields available for your organization:
* **Organization schema:** `GET /v1/insights/schema` returns all available entities and their fields.
* **Event schema:** `GET /v1/insights/event/{eventId}/schema` returns entities and fields scoped to a specific event.
The schema response includes entity names, field names, data types, and relationships between entities that you can use in JOIN clauses.
For event-scoped schema (`GET /v1/insights/event/{eventId}/schema`), the payload also includes **`session_participant_roles`**: each event’s configured session roles (`name`, `name_plural`, `slug`, `core_role`). Use **`participant_contacts.role_slug`** in SbQL to filter custom roles (e.g. panelists); match user-facing labels to the **`slug`** from this list.
**`Session` vs `Abstract`:** Both use the same underlying sessions table. **`FIND Session`** returns only **program** sessions (non-abstract). **`FIND Abstract`** returns only **abstract / CFP** submissions. Prefer these entities over filtering on `is_abstract` in queries.
The REST Sessions API exposes the same distinction via `is_abstract` on every session payload, plus `composition_status` for merge/link state. Linked composition sources are excluded from default list/search unless you pass `expand=linked_sources`. See [Sessions & Composition](/api-reference/sessions-composition).
Relationship entries may include a `description` flagging **legacy** evaluation paths (`ratings`, `criteria_ratings`, etc.).
**Sessions 2.0 / Evaluation Plan 2.0:** When an event has the Sessions 2.0 feature enabled, evaluation **performance** for sessions and speakers (scores, grades, reviewer workload) is primarily stored in the **Evaluation Plan 2.0** data model. Current SbQL evaluation relationships read **legacy** `Evaluation_Plan_Ratings` (and related) tables. For v2-only evaluation activity, those queries may not match product UI or exports—use **Evaluation Plan 2.0** reports and CSV/XLSX exports as the source of truth, and see the internal `sbql-reference.md` *Sessions 2.0* section for full detail.
## Natural Language to SbQL
If you prefer to write queries in plain English, use the `POST /v1/insights/ai/generate` endpoint to convert natural language into SbQL. For example, sending "How many sessions are in each track?" will return a valid SbQL query that you can execute directly.
# Build an Integration
Source: https://apidocs.sessionboard.com/integrations
Methods for syncing Sessionboard data to your platform
Sessionboard offers several methods for getting your event data into external platforms. Choose the approach that best fits your technical requirements and use case.
**Best for:** Real-time sync with full metadata access.
Use the Public API to query sessions, speakers, contacts, sponsors, and exhibitors on demand. Combine with webhooks to receive push notifications when data changes, eliminating the need to poll for updates.
[Authentication →](/authentication) | [Webhooks →](/webhooks) | [API Reference →](/api-reference/overview)
**Best for:** One-off integrations and website embeds.
Sessionboard provides JSON, XML, and HTML feed URLs for your event data. Embed feeds are refreshed every 60 minutes and require no authentication. Use them to display session listings, speaker directories, or schedules on your website.
Configure embed feeds from **Event Settings > Integrations > Embeds** in the Sessionboard admin dashboard.
**Best for:** Connecting to thousands of apps without code.
The Sessionboard Zapier integration (currently in beta) lets you trigger workflows in tools like Slack, Google Sheets, HubSpot, and more when data changes in Sessionboard.
Contact [support@sessionboard.com](mailto:support@sessionboard.com) to enable Zapier for your organization.
**Best for:** One-time data snapshots and reporting.
Export XLSX or CSV files directly from any list view in the Sessionboard admin dashboard. Exports include all visible columns and can be filtered before downloading.
Use the export button in the top-right corner of any list view (sessions, speakers, contacts, etc.).
## Choosing the Right Method
| Requirement | Recommended Method |
| ---------------------------------- | ------------------ |
| Real-time data sync | API + Webhooks |
| Display data on a website | Embeds |
| Connect to third-party SaaS tools | Zapier |
| Ad-hoc reporting or auditing | Data Exports |
| Custom mobile app or internal tool | API + Webhooks |
| Low-code / no-code workflow | Zapier or Embeds |
# Introduction
Source: https://apidocs.sessionboard.com/introduction
Get started with the Sessionboard Public API
The Sessionboard Public API provides access to your event data including sessions, speakers, contacts, sponsors, and exhibitors. Use it to build integrations, sync data to external platforms, or power custom experiences for your events.
## Base URL
Sessionboard operates in two regions. Use the base URL corresponding to where your organization's data is hosted.
```
https://public-api.sessionboard.com
```
```
https://public-api-eu.sessionboard.com
```
## Quick Links
Learn how to authenticate requests using API tokens.
Receive real-time notifications when data changes.
Explore methods for syncing Sessionboard data to your platform.
Browse the full endpoint reference with request and response schemas.
Sync transcript text, upload media files, or add session audio recordings.
Attach PDFs and documents — simple upload (≤50 MB) or direct-to-storage (≤500 MB).
See what's new — endpoints, scopes, and response shape updates.
## Pagination
All search endpoints return paginated results. The response body includes a `pagination` object alongside the `results` array.
```json theme={null}
{
"data": [],
"pagination": {
"currentPage": 1,
"pageSize": 25,
"totalPages": 10,
"totalResults": 250
}
}
```
Some legacy search endpoints return a `results` key instead of `data`. Check each endpoint's response schema for the exact shape.
Use the `page` and `pageSize` query parameters (or body parameters on POST search endpoints) to navigate through results. The default page size is 25 and the maximum is 100.
## Rate Limiting
The API enforces rate limits to ensure fair usage — see [Rate Limiting](/rate-limiting) for details. Build your integration to handle `429 Too Many Requests` responses with exponential backoff.
## Caching
To ensure fast response times, the following endpoints are cached for **3 minutes**:
* `GET /v1/event/{eventId}/sessions/{sessionId}` — individual session retrieval
* `POST /v1/event/{eventId}/sessions` — session search
If you update data in Sessionboard and immediately query the API, you may see stale results for up to 3 minutes. Webhook notifications are delivered in real time and are not subject to caching.
# OAuth 2.1 (AI Clients)
Source: https://apidocs.sessionboard.com/oauth
Authenticate AI assistants like Claude and ChatGPT using OAuth 2.1 with PKCE
Sessionboard supports OAuth 2.1 with PKCE for authenticating AI assistants (Claude, ChatGPT, and other MCP-compatible clients). This enables users to authorize AI tools to query their event data through a secure, permission-based flow.
## How It Works
```
1. AI client redirects user to Sessionboard consent page
2. User logs in, selects organization, approves requested scopes
3. Sessionboard redirects back with an authorization code
4. AI client exchanges the code for access + refresh tokens
5. AI client uses the access token for MCP queries
```
## Endpoints
All OAuth endpoints are on `public-api.sessionboard.com` (US) or `public-api-eu.sessionboard.com` (EU).
| Endpoint | Method | Description |
| ----------------------------------------------- | ------ | --------------------------------------------- |
| `/oauth/authorize` | GET | Validate authorization request parameters |
| `/oauth/authorize/consent` | POST | User approves — generates authorization code |
| `/oauth/eligible-orgs` | GET | List orgs where user has AI Access permission |
| `/oauth/token` | POST | Exchange code for tokens, refresh tokens |
| `/oauth/revoke` | POST | Revoke access or refresh tokens |
| `/oauth/.well-known/oauth-authorization-server` | GET | RFC 8414 server metadata |
## Authorization Request
Redirect the user to the authorization endpoint with these parameters:
```
GET /oauth/authorize?
client_id=your-client-id&
redirect_uri=https://your-app.com/callback&
response_type=code&
scope=read:events+read:sessions+read:contacts&
code_challenge=&
code_challenge_method=S256&
state=
```
| Parameter | Required | Description |
| ----------------------- | ----------- | --------------------------------------------------------------- |
| `client_id` | Yes | Your registered OAuth client ID |
| `redirect_uri` | Yes | Must match a registered redirect URI |
| `response_type` | Yes | Must be `code` |
| `scope` | No | Space-separated scopes (defaults to client's registered scopes) |
| `code_challenge` | Yes | PKCE challenge (S256 method) |
| `code_challenge_method` | Yes | Must be `S256` |
| `state` | Recommended | Opaque value for CSRF protection |
## Token Exchange
Exchange the authorization code for tokens:
```bash cURL theme={null}
curl -X POST https://public-api.sessionboard.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"code": "AUTHORIZATION_CODE",
"redirect_uri": "https://your-app.com/callback",
"client_id": "your-client-id",
"code_verifier": "YOUR_PKCE_VERIFIER"
}'
```
**Response:**
```json theme={null}
{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "...",
"scope": "read:events read:sessions read:contacts"
}
```
## Refresh Tokens
Access tokens expire after 1 hour. Use the refresh token to get a new one:
```bash theme={null}
curl -X POST https://public-api.sessionboard.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "refresh_token",
"refresh_token": "YOUR_REFRESH_TOKEN",
"client_id": "your-client-id"
}'
```
Refresh tokens expire after 7 days and are rotated on each use (the old token is revoked).
## Using the Token
Include the access token as a Bearer token on API requests:
```bash theme={null}
curl https://public-api.sessionboard.com/v1/events \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```
Bearer tokens work on all `/v1/` endpoints alongside the existing `x-access-token` header authentication.
## Token Revocation
Revoke a token when the user disconnects:
```bash theme={null}
curl -X POST https://public-api.sessionboard.com/oauth/revoke \
-H "Content-Type: application/json" \
-d '{
"token": "TOKEN_TO_REVOKE",
"token_type_hint": "access_token"
}'
```
## Available Scopes
| Scope | Description |
| --------------------- | --------------------------------------------------------------- |
| `read:events` | View events and event details |
| `read:sessions` | View session data including titles, times, tracks, and statuses |
| `read:contacts` | View contact, participant, exhibitor, and sponsor information |
| `read:reports` | View and run saved custom reports |
| `read:dashboards` | View dashboards and widget data |
| `read:insights` | Query Reports / Dashboards data with SbQL and natural language |
| `read:transcriptions` | View session transcriptions and audio recordings |
| `read:media` | View uploaded media items and transcription status |
OAuth tokens currently support **read-only** scopes. For write operations (creating sessions, updating contacts, managing agendas), use [API tokens](/authentication) with the appropriate `write:*` scopes.
## Permission Model
OAuth tokens inherit the authorizing user's permissions:
* **Organization admin with AI Access** → token can query all events in the org
* **Event-only user with AI Access** → token scoped to their permitted events
* **AI Access revoked** → token stops working immediately (checked on every request)
* **AI features disabled for org** → all OAuth tokens for that org are blocked
The "AI Access" permission (under Data & Insights) controls who can authorize OAuth connections. It is enabled by default for Admin roles.
## Server Metadata
Discover OAuth server capabilities at:
```
GET /oauth/.well-known/oauth-authorization-server
```
Returns supported response types, grant types, scopes, and endpoint URLs per [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
# Rate Limiting
Source: https://apidocs.sessionboard.com/rate-limiting
Understand API rate limits and how to handle them
The Sessionboard Public API enforces rate limits to ensure fair usage and platform stability. Rate limits are applied per API token with separate counters for each category.
## Limits by Endpoint
Rate-limited endpoints are grouped into independent buckets. Each bucket tracks its own counter, so hitting the limit on writes won't block your reads.
| Category | Limit | Window | Endpoints |
| ------------------------------------ | ----- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Entity reads** | 100 | 15 minutes | `GET` single session, contact, exhibitor, sponsor; `GET` field, room, track, tag, format, level, language, status lists |
| **Session writes** | 100 | 15 minutes | `POST /sessions/create`, `PUT`, `DELETE`, `POST /restore`, `POST /bulk` for sessions; `POST .../files/upload`, `POST` / `PUT` / `DELETE` on session files (`write:sessions`) |
| **Transcription & recording writes** | 100 | 15 minutes | `POST` / `PUT` / `DELETE` on session transcriptions; `POST` on session recordings and `POST /complete` (`write:transcriptions`) |
| **Media upload writes** | 100 | 15 minutes | Multipart media upload initiate, sign-part, complete, abort (`write:media`) |
| **Contact writes** | 100 | 15 minutes | `POST /create`, `PUT`, `DELETE`, `POST /restore`, `POST /bulk` for contacts |
| **Exhibitor writes** | 100 | 15 minutes | `POST /create`, `PUT`, `DELETE`, `POST /restore`, `POST /bulk` for exhibitors |
| **Sponsor writes** | 100 | 15 minutes | `POST /create`, `PUT`, `DELETE`, `POST /restore`, `POST /bulk` for sponsors |
| **Field writes** | 100 | 15 minutes | `POST /create`, `PUT`, `DELETE` for custom fields |
| **Metadata writes** | 100 | 15 minutes | `POST /create`, `PUT`, `DELETE` for rooms, tracks, tags, formats, levels, languages, statuses |
| **Event management writes** | 100 | 15 minutes | Agenda drafts, draft sessions, scheduling rules, personas, dashboards, widgets, saved reports |
| **Insights & SbQL** | 100 | 15 minutes | All `/insights/*` and `/event/{eventId}/insights/*` endpoints |
### Endpoints without rate limits
The following endpoints do not enforce rate limits. They are legacy endpoints that query the database directly:
* `GET /v1/events` — list events
* `POST /v1/event/{eventId}/sessions` — search sessions
* `POST /v1/event/{eventId}/contacts` — search contacts
* `POST /v1/event/{eventId}/sponsors` — search sponsors
* `POST /v1/event/{eventId}/exhibitors` — search exhibitors
* `POST /v1/event/{eventId}/speakers` — search speakers
* `GET /v1/event/{eventId}/speakers/{contactId}` — get speaker
* `POST /v1/event/{eventId}/fields` — search fields
* `POST /v1/event/{eventId}/{rooms,tracks,tags,formats,levels,languages}` — search metadata
* `POST /v1/event/{eventId}/sessions/status` — search sessions by status
* `POST /v1/event/{eventId}/session-statuses` — search session statuses
* `GET/POST /v1/gdpr/requests` — GDPR endpoints
* `GET /v1/event/{eventId}/contacts/{contactId}/sessions` — contact sessions
* `GET /v1/organization/{orgId}/contacts/*` — org-level contact endpoints
Even though these endpoints don't enforce rate limits today, we recommend building your integration to handle `429` responses gracefully in case limits are added in the future.
## Response Headers
Rate-limited endpoints include these headers on every response (both successful and rate-limited):
| Header | Description |
| --------------------- | ----------------------------------------------- |
| `RateLimit-Limit` | Maximum requests allowed in the current window |
| `RateLimit-Remaining` | Requests remaining in the current window |
| `RateLimit-Reset` | Unix timestamp (seconds) when the window resets |
## Exceeding the Limit
When you exceed the rate limit, the API returns a `429` status with a `Retry-After` header:
```
HTTP/1.1 429 Too Many Requests
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 1711900800
Retry-After: 45
```
```json theme={null}
{
"error": "TooManyRequestsError",
"message": "Error while trying to reach the endpoint: Too many requests"
}
```
## Custom Rate Limits
By default, each API token is limited to **100 requests per 15 minutes** per category. If your integration requires a higher throughput, contact Sessionboard support to request an elevated rate limit for your token.
Custom limits are applied per token and override the default for all rate-limited buckets. The 15-minute window stays the same — only the request count changes. For example, a token with a custom limit of 1,000 can make up to 1,000 requests per 15 minutes in each category.
When a custom rate limit is active, the `RateLimit-Limit` header reflects the token's custom value, not the default 100.
## Best Practices
Cache API responses locally to reduce the number of requests. Many endpoints return data that doesn't change frequently.
Use `page` and `pageSize` parameters to fetch only the data you need instead of requesting large datasets.
When you receive a 429 response, wait for the `Retry-After` duration before making another request. Implement exponential backoff for retries.
Where possible, use bulk endpoints instead of making many individual requests. Bulk operations count as a single request against the rate limit.
## Rate Limits by Auth Method
| Auth Method | Limit | Notes |
| ---------------------------- | ---------------- | ------------------------------------ |
| API Token (`x-access-token`) | 100 req / 15 min | Per token, per category |
| OAuth Bearer Token | 100 req / 15 min | Per token, per category |
| Unauthenticated | Blocked | All endpoints require authentication |
# Webhooks
Source: https://apidocs.sessionboard.com/webhooks
Receive real-time notifications when data changes
Webhooks allow your application to receive real-time HTTP callbacks when data changes in Sessionboard. Instead of polling the API for updates, you can subscribe to specific events and receive notifications as they happen.
## Event Catalog
Subscribe to any combination of the following webhook events.
| Event | Description |
| ----------------------------- | ---------------------------------------------- |
| `contact.created` | A new contact was created in the organization. |
| `contact.updated` | A contact's details were updated. |
| `contact.deleted` | A contact was deleted from the organization. |
| `contact.event.associated` | A contact was associated with an event. |
| `contact.event.disassociated` | A contact was removed from an event. |
\| Event | Description | | --- | --- | | `session.created` | A new session was
created. | | `session.updated` | A session's details were updated. | |
`session.deleted` | A session was deleted. | | `session.speaker.attached` | A
speaker was attached to a session. | | `session.speaker.detached` | A speaker
was detached from a session. |
\| Event | Description | | --- | --- | | `exhibitor.created` | A new exhibitor
was created. | | `exhibitor.updated` | An exhibitor's details were updated. |
\| `exhibitor.deleted` | An exhibitor was deleted. | |
`exhibitor.event.associated` | An exhibitor was associated with an event. | |
`exhibitor.event.disassociated` | An exhibitor was removed from an event. |
| Event | Description |
| ----------------------------- | --------------------------------------- |
| `sponsor.created` | A new sponsor was created. |
| `sponsor.updated` | A sponsor's details were updated. |
| `sponsor.deleted` | A sponsor was deleted. |
| `sponsor.event.associated` | A sponsor was associated with an event. |
| `sponsor.event.disassociated` | A sponsor was removed from an event. |
## Payload Structure
Every webhook delivery sends a JSON payload with two top-level keys: `data` (the full resource that changed) and `metadata` (information about the event itself).
The `data` field contains the **full resource object** for the affected entity
(Session, Contact, Sponsor, or Exhibitor). Its shape matches the corresponding
response schema in the [API Reference](/api-reference/overview).
Example delivery for a `session.updated` event:
```json theme={null}
{
"data": {
"id": "fd4e0275-f018-40bc-909a-f8cdfa0df354",
"sourceOfChange": "user"
},
"metadata": {
"action": "session.updated",
"actor_id": 7,
"event_id": 4001,
"org_id": "757e8d5b-ce66-45f5-ab36-273414f8ab2f",
"resource_url": "https://public-api.sessionboard.com/v1/event/4001/sessions/fd4e0275-f018-40bc-909a-f8cdfa0df354",
"version": 1,
"datetime": "2026-04-28T16:00:00Z"
}
}
```
The `data` object above is abbreviated — production payloads include every field of the resource. Refer to the `Session`, `Contact`, `Sponsor`, and `Exhibitor` response schemas in the [API Reference](/api-reference/overview) for the complete shape.
### Payload Attributes
| Field | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------- |
| `data.sourceOfChange` | Changes were performed by a user or an agent. |
| `data.id` | Unique identifier of the affected resource. Always present at the top of `data`. |
| `metadata.action` | The webhook event type (e.g., `session.updated`). |
| `metadata.actor_id` | ID of the user who performed the action. `null` for system-generated events. |
| `metadata.event_id` | The Sessionboard event ID associated with the change. `null` for organization-level events. |
| `metadata.org_id` | Your organization's unique identifier. |
| `metadata.resource_url` | Direct URL to fetch the full resource from the Public API. |
| `metadata.version` | Payload schema version. Currently `1`. New non-breaking fields may be added without bumping this. |
| `metadata.datetime` | UTC ISO 8601 timestamp of when the event occurred in Sessionboard. |
**Forward compatibility:** Sessionboard may add new fields to `data` and
`metadata` at any time. Webhook consumers should ignore unknown fields rather
than fail on them. Removed or renamed fields will trigger a `metadata.version`
bump.
## Creating a Webhook
In the Sessionboard admin dashboard, navigate to **Settings > Integrations > Webhooks**.
Click **Add Endpoint** and enter the URL where you want to receive webhook deliveries. This must be a publicly accessible HTTPS endpoint. Select which events you want to subscribe to for this endpoint.
Save the webhook configuration. Sessionboard will begin sending events to your endpoint immediately. You can also add custom headers for additional security (e.g., passing a token that your server validates to ensure the request is from Sessionboard).
## Testing Webhooks
Use the **Testing** tab on any endpoint to send a sample payload without triggering a real action. You can also use [Svix Play](https://play.svix.com) to capture and inspect deliveries in a temporary sandbox.
## Monitoring
Sessionboard provides delivery logs for each webhook endpoint in the admin dashboard. You can view recent deliveries, inspect payloads, and check response status codes. Failed deliveries are retried automatically with exponential backoff.