# 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. Sessionboard integration workflow **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**. Webhook settings panel 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. Adding a webhook 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. Testing a webhook endpoint ## 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. Webhook delivery logs