Sidekick API
App Bridge isn't versioned with Polaris. App Bridge APIs and web components are identical in every App Home reference version.
App Bridge isn't versioned with Polaris. App Bridge APIs and web components are identical in every App Home reference version.
Use the Sidekick API in embedded apps in the Shopify admin to start a Sidekick conversation for the merchant with a prompt your app provides. Call shopify.sidekick.launch() to open the Sidekick panel and send the prompt as the merchant's message.
You can also check whether Sidekick is available, open the panel without sending a prompt, and listen for panel visibility changes.
Anchor to Use casesUse cases
- Ask Sidekick from a report: Add an Ask Sidekick button next to a report so the merchant can ask Sidekick to summarize or explain the data shown in your app.
- Setup help: Start a conversation that helps the merchant with a step in your app's setup flow.
- In-app explanations: Help merchants understand campaign performance, churn, or other data shown in your app.
Anchor to MethodsMethods
| Method | Type | Description |
|---|---|---|
launch | LaunchFunction | Opens Sidekick and sends a message as the merchant's prompt. |
isEnabled | IsEnabledFunction | Checks whether Sidekick is available to the app on this store. |
isOpen | IsOpenFunction | Checks whether the Sidekick panel is open. |
open | OpenFunction | Opens the Sidekick panel without sending a prompt. |
There is no close method. Closing Sidekick is the merchant's decision.
Anchor to [object Object]LaunchFunction
LaunchFunction| Parameter | Type | Description |
|---|---|---|
request | {message: string} | string | The prompt to send to Sidekick as the merchant's message. A string is shorthand for {message}. |
Returns: Promise<{id: string}>. Resolves with the new conversation ID.
The message field is required, must be non-empty after trimming, and can be at most 5,500 characters. Leading and trailing whitespace is trimmed. launch ignores any other field, and doesn't treat it as an error. Hidden context or instructions, scenario, conversation IDs, and features aren't supported.
Anchor to [object Object]IsEnabledFunction
IsEnabledFunctionChecks whether Sidekick is available to the app on this store.
Returns: Promise<boolean>
If the API isn't available, then shopify.sidekick methods reject. The shopify.sidekick object can still exist on the global, so feature-detect by calling isEnabled() and treating a rejection as unavailable:
Always check isEnabled() before you show a launch entry point or call any other method, and render the entry point only when it resolves true. The API isn't available in the Shopify mobile app yet, or on stores where Sidekick isn't available.
Anchor to [object Object]IsOpenFunction
IsOpenFunctionChecks whether the Sidekick panel is open.
Returns: Promise<boolean>
Anchor to [object Object]OpenFunction
OpenFunctionOpens the Sidekick panel without sending a prompt.
Returns: Promise<void>
Anchor to EventsEvents
App Bridge dispatches shopify:sidekick:visibilitychange on window when the Sidekick panel opens or closes.
| Property | Type | Description |
|---|---|---|
event.detail.visibilityState | 'visible' | 'hidden' | Whether the Sidekick panel is open or hidden. |
Anchor to Requirements and availabilityRequirements and availability
The Sidekick API is available to apps embedded in the web Shopify admin that load App Bridge from https://cdn.shopify.com/shopifycloud/app-bridge.js. The API isn't available inside the Shopify mobile app or when Sidekick isn't available on the store.
The @shopify/app-bridge-types package doesn't include shopify.sidekick yet.
A launched conversation can use only your app's tools from its Sidekick app extensions, not other apps' tools. Prompts that ask to act across several apps or move data into another app are refused. If the merchant has turned your app off in Sidekick, then Shopify rejects launch.
Anchor to Prompt guidelinesPrompt guidelines
Before Shopify sends anything, Shopify screens the prompt. The check fails closed. If screening can't complete, then Shopify rejects the launch. The screening step adds latency, so launch is slower than typing into Sidekick. Shopify rate limits launches for each merchant, for each app, and across apps. Call launch in response to a merchant action, such as a button click. Don't call launch on page load or on a timer.
Allowed prompts include questions, reads, searches, summaries, explanations, drafts, content fixes on named resources, and changes inside your own app. Content fixes can include titles, descriptions, SEO fields, alt text, tags, metafields, and translations on specific products, collections, pages, or blog posts.
Shopify refuses prompts that:
- Are harmful or contain a URL or link.
- Try to steer Sidekick, such as asking it to ignore rules, prefer your app, hide things from the merchant, claim the merchant already approved something, or impersonate Shopify or Sidekick.
- Try to harvest store, customer, or financial data for the app.
- Ask for a risky store change, such as deleting or bulk-editing resources, moving money or changing prices, acting on orders, changing permissions, publishing themes or domains, changing settings, or sending marketing.
- Ask to act across several apps or move data into another app.
Sidekick shows the merchant that the conversation was started by your app. Sidekick never applies a store change from a launched prompt on its own. It proposes the change and only makes it after the merchant asks in their own message.
Anchor to ErrorsErrors
Shopify throws the following errors before sending anything. Each Error.message starts with sidekick.launch:.
| Error message | Cause |
|---|---|
sidekick.launch: message is required and must be a non-empty string. | No usable message. |
sidekick.launch: message must be at most 5500 characters. | The prompt is too long. |
sidekick.launch: the calling app could not be identified. | Shopify couldn't identify the calling app. |
sidekick.launch: the calling app is turned off in Sidekick. | The merchant turned your app off in Sidekick. |
sidekick.launch: whether the calling app is turned on in Sidekick could not be determined. | Shopify couldn't read the merchant's Sidekick app settings. Try again later. |
sidekick.launch: message was rejected. | The prompt didn't pass screening. The reason isn't disclosed. |
sidekick.launch: the prompt safety check could not be completed. | Screening errored or was rate limited. |
sidekick.launch: Sidekick is unavailable for maintenance. | Sidekick is in maintenance. |
Errors without the sidekick.launch: prefix happen after screening, while Shopify creates or sends the conversation. Shopify might already have sent the prompt, so don't retry those errors automatically.
js
Examples
Launch a conversation
Description
Launch a Sidekick conversation from a merchant action. The button only appears when `isEnabled()` resolves `true`. Shopify sends the prompt as the merchant's message, and the Sidekick panel opens.
js
const button = document.getElementById('ask-sidekick'); const available = await shopify.sidekick?.isEnabled().catch(() => false); button.hidden = !available; if (available) { button.addEventListener('click', async () => { const conversation = await shopify.sidekick.launch({ message: 'Summarize my subscription churn for last month', }); console.log('Started Sidekick conversation', conversation.id); }); }Check availability
Description
Check whether Sidekick is available before showing your launch entry point. Treat a rejected `isEnabled()` call as unavailable.
js
const button = document.getElementById('ask-sidekick'); const available = await shopify.sidekick?.isEnabled().catch(() => false); button.hidden = !available; if (available) { button.addEventListener('click', () => { shopify.sidekick.launch( 'Which of my email campaigns performed best last month?', ); }); }Handle rejections
Description
Handle launch rejections after checking `isEnabled()`. Errors that start with `sidekick.launch:` happen before Shopify sends anything.
js
const button = document.getElementById('ask-sidekick'); const available = await shopify.sidekick?.isEnabled().catch(() => false); button.hidden = !available; if (available) { button.addEventListener('click', async () => { try { await shopify.sidekick.launch({ message: 'Summarize my subscription churn for last month', }); } catch (error) { const message = error instanceof Error ? error.message : String(error); if (message.startsWith('sidekick.launch:')) { shopify.toast.show(message, {isError: true}); return; } shopify.toast.show('Sidekick could not start the conversation.', { isError: true, }); } }); }Open Sidekick and listen for visibility changes
Description
Check `isEnabled()`, then open the Sidekick panel without sending a prompt and listen for `shopify:sidekick:visibilitychange` events.
js
const button = document.getElementById('open-sidekick'); const status = document.getElementById('sidekick-status'); const available = await shopify.sidekick?.isEnabled().catch(() => false); button.hidden = !available; if (available) { window.addEventListener('shopify:sidekick:visibilitychange', (event) => { status.textContent = event.detail.visibilityState === 'visible' ? 'Sidekick is open' : 'Sidekick is hidden'; }); button.addEventListener('click', async () => { await shopify.sidekick.open(); }); }Use Sidekick with React
Description
Use `useAppBridge` to render a button when Sidekick is available.
jsx
import {useEffect, useState} from 'react'; import {useAppBridge} from '@shopify/app-bridge-react'; export function AskSidekickButton() { const shopify = useAppBridge(); const [available, setAvailable] = useState(false); useEffect(() => { let mounted = true; shopify.sidekick?.isEnabled() .then((enabled) => { if (mounted) setAvailable(enabled); }) .catch(() => { if (mounted) setAvailable(false); }); return () => { mounted = false; }; }, [shopify]); if (!available) return null; return ( <button onClick={() => shopify.sidekick.launch( 'Which of my email campaigns performed best last month?', ) } > Ask Sidekick </button> ); }