> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://contentful.com/developers/docs/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://contentful.com/_mcp/server. # Experience Canvas Toolbar SDK Reference > The sdk.experiences reference for the Experience Canvas Toolbar location | Experience context | Experience API | Experience Node API | Selection API | Data Assembly This page is the method-and-property reference for `sdk.experiences`, available in [`locations.LOCATION_EXPERIENCE_TOOLBAR`](/extensibility/app-framework/locations#locations). For the concepts behind this location, see the [Experience Canvas Toolbar overview](/extensibility/app-framework/experience-canvas-toolbar-overview). For a walkthrough of building an app for this location, see [Get started with the Experience Canvas Toolbar](/extensibility/app-framework/experience-canvas-toolbar-getting-started). ## Experiences `sdk.experiences` Only available in [`locations.LOCATION_EXPERIENCE_TOOLBAR`](/extensibility/app-framework/locations#locations). Exposes context and data about the experience or fragment currently open in the experience canvas or fragment canvas, and provides methods for reading and updating its content. *Since 4.63.0* ### Getting the experience context `sdk.experiences.context: ExperienceContext` Returns the current editing context: ```javascript { type: 'experience' | 'fragment' | 'experienceFragment', entityId: string } ``` The toolbar location serves both editing contexts — check `context.type` to determine whether the app is running in the context of an experience or a fragment. > **Info** > > **Note:** `'experienceFragment'` is reserved for an upcoming rename of the Fragment entity. The host does not emit it yet — code defensively against it, but expect only `'experience'` or `'fragment'` today. ### Receiving notifications when the experience context changes `sdk.experiences.onContextChanged(callback): function` Calls the callback every time the experience context changes. The method returns a function you can call to stop listening to changes. ```javascript const detachHandler = sdk.experiences.onContextChanged((context) => { console.log(context.type, context.entityId); }); ``` *Since 4.63.0* ### The Experience API `sdk.experiences.experience` Gives access to the experience or fragment entity being edited. #### Getting the experience snapshot `experience.get(): ExperienceSnapshot` Returns the current experience snapshot. Its shape depends on whether the entity is an experience or a fragment: ```javascript // Experience { sys: { id, type: 'Experience', version, template? }, metadata?: { tags?, concepts?, name? } } // Fragment { sys: { id, type: 'Fragment', version, componentType }, metadata?: { tags?, concepts?, name? } } ``` > **Info** > > **Note:** The type also accepts a third, reserved shape — `sys: { id, type: 'ExperienceFragment', version, component }` — for an upcoming rename of the Fragment entity. The host does not emit it yet. #### Receiving notifications when the experience changes `experience.onChange(callback): function` Calls the callback with the updated `ExperienceSnapshot` every time the experience changes. The method returns a function you can call to stop listening to changes. #### Getting experience metadata `experience.getMetadata(): ExperienceMetadata | undefined` Returns the experience's metadata (`tags`, `concepts`, `name`), or `undefined` if no metadata has been set. #### Setting experience metadata `experience.setMetadata(patch): Promise` Merges `patch` into the experience's existing metadata and persists the change. #### Receiving notifications when experience metadata changes `experience.onMetadataChanged(callback): function` Calls the callback with the updated `ExperienceMetadata` (or `undefined`) every time the experience's metadata changes. The method returns a function you can call to stop listening to changes. *Since 4.63.0* #### Saving the experience `experience.save(): Promise` Saves the current experience or fragment. #### Publishing the experience `experience.publish(): Promise` Publishes the current experience or fragment. #### Getting an experience node `experience.getNode(nodeId): ExperienceNodeAPI | null` Returns the node with the given ID, or `null` if no node with that ID exists. #### Getting the root nodes `experience.getRootNodes(): Promise` Resolves with the top-level nodes of the experience or fragment tree. Use this as the entry point for enumerating an experience whose node IDs you don't already know. There is no dedicated `getChildren()` method — descend the tree from a root node by reading a `Slot` node's [slot descriptor](#the-experience-node-api) (`node.getSlotDescriptor()`), whose `currentItems` list the child `nodeId`s, then resolve each with `getNode(nodeId)`. *Since 4.64.0* **Selection** `experience.selection: ExperienceSelectionAPI` See [Selection API](#selection-api) below. **Data Assembly** `experience.dataAssembly: DataAssemblyAPI` See [Data Assembly](#data-assembly) below. *Since 4.63.0* ### The Experience Node API `ExperienceNodeAPI` — returned by `experience.getNode(nodeId)`. * `node.id: string` — the node's ID. * `node.nodeType: 'Component' | 'Fragment' | 'ExperienceFragment' | 'InlineFragment' | 'InlineExperienceFragment' | 'Slot'` — the type of the node. The `ExperienceFragment`/`InlineExperienceFragment` values are reserved for an upcoming rename of the Fragment entity; the host does not emit them yet. * `node.get(): ExperienceNodeSnapshot` — returns the current node snapshot. * `node.onChange(callback): function` — calls `callback` with the updated node snapshot every time the node changes; returns a function you can call to stop listening to changes. * `node.dataAssembly: DataAssemblyParameterAPI` — node-scoped Data Assembly parameter access. See [Data Assembly](#data-assembly). * `node.getDesignProperty(key): Promise` — resolves with the value of the design property `key`. * `node.setDesignProperty(key, value): Promise` — sets the design property `key` to `value`. * `node.onDesignPropertyChanged(key, callback): function` — calls `callback` with the updated value every time the design property `key` changes; returns a function you can call to stop listening to changes. * `node.getProperties(): Promise` — resolves with the node's property descriptors. These are read-only. * `node.getSlotDescriptor(): Promise` — resolves with the node's slot descriptor, or `null` if the node is not a slot. > **Info** > > **Note:** Node content is written through the node-scoped [Data Assembly](#data-assembly) parameter API, not through a content-property setter — there is no `setContentProperty` method. Only design properties (`setDesignProperty`) have setters. *Since 4.63.0* ### Selection API `experience.selection` Exposes the current canvas selection. * `selection.get(): { nodeId: string | null; nodeType?: ExperienceNodeType }` — returns the currently selected node, if any. * `selection.onChange(callback): function` — calls `callback` with the updated selection every time it changes; returns a function you can call to stop listening to changes. * `selection.set(nodeId): void` — sets the selected node. Synchronous. * `selection.highlight(nodeId, options?): void` — highlights a node on the canvas. Synchronous. `options` may include `flash` (boolean) and `scrollIntoView` (boolean). *Since 4.63.0* ### Data Assembly Data Assembly parameters are exposed at two scopes: * `experience.dataAssembly: DataAssemblyAPI` — experience-scoped; includes the full set of methods below plus `get()`, `getAvailable()`, and `onChange()`. * `node.dataAssembly: DataAssemblyParameterAPI` — node-scoped; the four parameter methods only. Both scopes share: * `dataAssembly.getParameterDefinitions(): Promise>` — resolves with all parameter definitions. * `dataAssembly.getParameterDefinition(parameterId): Promise` — resolves with a single parameter definition, or `null` if it doesn't exist. * `dataAssembly.setParameterValue(parameterId, value): Promise` — sets a single parameter's value. * `dataAssembly.setParameterValues(updates): Promise` — sets multiple parameter values at once. The experience-scoped `DataAssemblyAPI` additionally provides: * `dataAssembly.get(): DataAssemblySnapshot` — returns the current Data Assembly snapshot. * `dataAssembly.getAvailable(): Promise` — resolves with the list of Data Assemblies available to the experience. * `dataAssembly.onChange(callback): function` — calls `callback` with the updated snapshot every time it changes; returns a function you can call to stop listening to changes. > **Info** > > **Note:** Data Assembly is definition-only in this release — there is no support for resolvers or nested Data Assemblies. *Since 4.63.0* ## Window `sdk.window` The shared [window API](/extensibility/app-framework/sdk#window) — `startAutoResizer()`, `stopAutoResizer()`, `updateHeight()` — for reporting the toolbar app's content height to the host. Also available in this location since app-sdk 4.67.0. > The sdk.experiences reference for the Experience Canvas Toolbar location | Experience context | Experience API | Experience Node API | Selection API | Data Assembly