### Install SDK Source: https://extensions.stripchat.com/docs/getting-started/quick-start Install the required helper library for Stripchat extensions. ```bash npm install @stripchatdev/ext-helper ``` -------------------------------- ### Full settings implementation example Source: https://extensions.stripchat.com/docs/getting-started/settings A complete workflow demonstrating loading and saving settings within the extension iframe. ```typescript import { createExtHelper } from '@stripchatdev/ext-helper'; const ext = createExtHelper(); // Load saved settings on mount const res = await ext.makeRequest('v1.model.ext.settings.get', null); const savedSettings = res.settings; // populate your form with savedSettings ... // Save settings when the model clicks "Save" ext.subscribe('v1.model.ext.settings.set.requested', async () => { // gather your form state const settings = { /* ... */ }; // run your own validation const isError = false; await ext.makeRequest('v1.model.ext.settings.set', { settings, isError, }); }); ``` -------------------------------- ### Full manifest example Source: https://extensions.stripchat.com/docs/getting-started/backend-actions A complete manifest demonstrating external API integration, URL/header templating, and delayed event scheduling. ```json { "actions": [ { "name": "authenticate", "type": "externalCall", "config": { "action": "https://api.example.com/auth/token", "method": "GET", "headers": { "X-Api-Key": "your-api-key" } } }, { "name": "stopDevice", "type": "externalCall", "config": { "action": "https://api.example.com/devices/{{deviceId}}/stop", "method": "PUT", "headers": { "Authorization": "Bearer {{token}}" } }, "params": { "deviceId": "string", "token": "string" } }, { "name": "createSession", "type": "externalCall", "config": { "action": "https://api.example.com/sessions", "method": "POST", "headers": { "X-Api-Key": "your-api-key" } } }, { "name": "closeSession", "type": "externalCall", "config": { "action": "https://api.example.com/sessions/{{sessionId}}/close", "method": "PUT", "headers": { "Authorization": "Bearer {{token}}" } }, "params": { "sessionId": "string", "token": "string" } }, { "name": "delayedCloseSession", "type": "delayedEvent", "config": { "action": "closeSession", "delay_ms": 30000 }, "params": { "sessionId": "string", "token": "string" } }, { "name": "delayedStopDevice", "type": "delayedEvent", "config": { "action": "stopDevice", "delay_ms": 30000 }, "params": { "deviceId": "string", "token": "string" } } ] } ``` -------------------------------- ### Full Manifest Configuration Source: https://extensions.stripchat.com/docs/getting-started/manifest A comprehensive manifest example including multiple slots, settings, and moveable overlay dimensions. ```json { "version": "v2.0", "views": { "settings": "settings.html", "slots": ["mainSexToy", "moveableOverlay", "background"], "pages": { "menu": "menu.html", "overlay": "overlay.html", "background": "background.html" }, "resolveSlotPageScript": "resolveSlotPage.js" }, "moveableSlot": { "width": 400, "height": 600 }, "actions": [] } ``` -------------------------------- ### Minimal Manifest Configuration Source: https://extensions.stripchat.com/docs/getting-started/manifest A basic manifest setup defining a single slot and page mapping. ```json { "version": "v2.0", "views": { "slots": ["mainGameFun"], "pages": { "menu": "menu.html" }, "resolveSlotPageScript": "resolveSlotPage.js" } } ``` -------------------------------- ### Configure manifest for slot resolution Source: https://extensions.stripchat.com/docs/getting-started/resolve-slot-page Example manifest configuration defining slots, pages, and the resolver script. ```json { "version": "v2.0", "views": { "slots": ["mainGameFun", "rightOverlay", "background"], "pages": { "menu": "menu.html", "overlay": "overlay.html", "background": "background.html" }, "resolveSlotPageScript": "resolveSlotPage.js" } } ``` ```json { "version": "v2.0", "views": { "slots": ["mainGameFun", "rightOverlay", "background"], "pages": { "model-menu": "model-menu.html", "viewer-menu": "viewer-menu.html", "model-overlay": "model-overlay.html", "viewer-overlay": "viewer-overlay.html", "background": "background.html" }, "resolveSlotPageScript": "resolveSlotPage.js" } } ``` -------------------------------- ### GET v1.model.ext.settings.get Source: https://extensions.stripchat.com/docs/api/requests Retrieves the current extension settings. ```APIDOC ## GET v1.model.ext.settings.get ### Description Retrieves the current settings for the extension. ### Method GET ### Endpoint v1.model.ext.settings.get ### Request Example ```ts const res = await ext.makeRequest('v1.model.ext.settings.get', null); ``` ### Response #### Success Response (200) - **settings** (unknown) - The current settings object. ``` -------------------------------- ### Make a Request to the Platform Source: https://extensions.stripchat.com/docs/api/requests Use `makeRequest` to send RPC calls to the platform. Each request has typed parameters and results. This example shows a basic request. ```typescript const result = await ext.makeRequest('v1.ext.context.get', null); ``` -------------------------------- ### Example: Background Slot as Coordinator Source: https://extensions.stripchat.com/docs/getting-started/slots-communication Demonstrates a common pattern where the background slot acts as a central coordinator, maintaining state and relaying messages between visual slots. ```APIDOC ## Example: Background Slot as Coordinator ### Background Slot (Coordinator) js ```javascript // background slot const ext = createExtHelper(); let gameState = { round: 0, scores: {} }; ext.subscribe('v1.ext.whispered', (data) => { if (data.type === 'PLAYER_ACTION') { gameState = updateGameState(gameState, data); // Assume updateGameState is defined elsewhere // relay updated state to local UI slots ext.makeRequest('v1.ext.whisper.local', { data: { type: 'STATE_UPDATE', state: gameState } }); } }); ``` ### Right Overlay Slot (UI) js ```javascript // rightOverlay slot const ext = createExtHelper(); ext.subscribe('v1.ext.whispered', (data) => { if (data.type === 'STATE_UPDATE') { updateUI(data.state); // Assume updateUI is defined elsewhere } }); ``` ``` -------------------------------- ### Make an Activity Request Source: https://extensions.stripchat.com/docs/overview/how-extensions-work Use `makeRequest` to send typed RPC calls to the platform. This example shows how to request activity information with a specified duration. ```typescript const res = await ext.makeRequest('v1.ext.activity.request', { durationMs: 60000, }); ``` -------------------------------- ### Subscribe to Token Spend Events Source: https://extensions.stripchat.com/docs/overview/how-extensions-work Use `subscribe` to receive real-time notifications from the platform. This example listens for successful token spend events. ```typescript ext.subscribe('v1.payment.tokens.spend.succeeded', (data) => { }); ``` -------------------------------- ### Get Current Extension Context Source: https://extensions.stripchat.com/docs/api/requests Retrieve the current room context, including broadcaster and viewer information. Call this once on startup and use `v1.ext.context.updated` to maintain up-to-date context. ```typescript const ctx = await ext.makeRequest('v1.ext.context.get', null); if (ctx.user) { console.log(ctx.user.username); } ``` -------------------------------- ### SDK Initialization Source: https://extensions.stripchat.com/docs/api/methods Initializes the ExtHelper instance, establishing communication with the host platform and setting the theme. ```APIDOC ## `createExtHelper` Creates and initializes an `ExtHelper` instance. Call this **once** at the entry point of each HTML page. ts ```typescript import { createExtHelper } from '@stripchatdev/ext-helper'; const ext = createExtHelper(); ``` The function automatically: * Establishes a PostMessage transport to communicate with the host platform. * Reads the current theme (`dark` or `light`) and sets `data-theme` on the `` element. Returns an `ExtHelper` instance with `makeRequest`, `subscribe`, and `unsubscribe` methods. ``` -------------------------------- ### Build and Package Extension Source: https://extensions.stripchat.com/docs/getting-started/quick-start Commands to build the project and create a ZIP archive for upload. ```bash npm run build cd dist zip -r ../my-extension.zip . ``` -------------------------------- ### Initialize SDK Source: https://extensions.stripchat.com/docs/getting-started/quick-start Initialize the SDK at the entry point of each page before executing main script logic. ```typescript import {createExtHelper} from '@stripchatdev/ext-helper'; const ext = createExtHelper(); ``` -------------------------------- ### Initialize ExtHelper Instance Source: https://extensions.stripchat.com/docs/api/methods Call `createExtHelper` once at the entry point of each HTML page to initialize the SDK. It automatically establishes communication and sets the theme. ```typescript import { createExtHelper } from '@stripchatdev/ext-helper'; const ext = createExtHelper(); ``` -------------------------------- ### v1.ext.signup.open Source: https://extensions.stripchat.com/docs/api/requests Opens the Stripchat sign-up dialog for anonymous users. ```APIDOC ## POST v1.ext.signup.open ### Description Opens Stripchat sign-up dialog for anonymous users. Use this when your extension requires a registered account to function. ### Request Body - **type** ('user') - Required - Sign-up type. ### Request Example { "type": "user" } ``` -------------------------------- ### Send Broadcast Whisper Message Source: https://extensions.stripchat.com/docs/overview/how-extensions-work Send a message to all clients (viewers and model) using broadcast whisper. This example sends a game event through the server. ```typescript await ext.makeRequest('v1.ext.whisper', { data: { type: 'GAME_EVENT', round: 3 }, }); ``` -------------------------------- ### Receive Local Whisper Message Source: https://extensions.stripchat.com/docs/overview/how-extensions-work Subscribe to local whisper messages to receive data exchanged between iframes of the same extension. This example listens for whispered data. ```typescript ext.subscribe('v1.ext.whispered', (data) => { }); ``` -------------------------------- ### Send Local Whisper Message Source: https://extensions.stripchat.com/docs/overview/how-extensions-work Exchange messages between iframes of the same extension using local whisper. This example sends a state update from the background slot. ```typescript await ext.makeRequest('v1.ext.whisper.local', { data: { type: 'STATE_UPDATE', score: 42 }, }); ``` -------------------------------- ### v1.ext.context.get Source: https://extensions.stripchat.com/docs/api/requests Retrieves the current context for the room, including broadcaster and viewer information. ```APIDOC ## RPC v1.ext.context.get ### Description Returns the current context for the room, including broadcaster info and viewer info. ### Parameters - **params** (null) - Required - Must be null. ### Response #### Success Response - **model** (TV1ExtModel | undefined) - Broadcaster for the current room. - **user** (TV1ExtUser | undefined) - Current user running the extension. ### Request Example ```ts const ctx = await ext.makeRequest('v1.ext.context.get', null); ``` ``` -------------------------------- ### v1.model.ext.settings.get Source: https://extensions.stripchat.com/docs/api/requests Loads the current extension settings inside the settings page context. ```APIDOC ## GET v1.model.ext.settings.get ### Description Loads the current extension settings inside the settings page context. ### Response #### Success Response (200) - **settings** (unknown) - Previously saved settings object, or a default value. ``` -------------------------------- ### Load extension settings Source: https://extensions.stripchat.com/docs/getting-started/settings Retrieve current settings on component mount to populate the configuration form. ```typescript import { createExtHelper } from '@stripchatdev/ext-helper'; const ext = createExtHelper(); const res = await ext.makeRequest('v1.model.ext.settings.get', null); const settings = res.settings; // populate your form with `settings` ``` -------------------------------- ### v1.ext.settings.get Source: https://extensions.stripchat.com/docs/api/requests Returns the current extension settings saved by the model. ```APIDOC ## RPC v1.ext.settings.get ### Description Returns the current extension settings saved by the model. Available in any slot. ### Parameters - **params** (null) - Required - Must be null. ### Response #### Success Response - **settings** (unknown) - The settings object. Shape is defined by the extension. ### Request Example ```ts const res = await ext.makeRequest('v1.ext.settings.get', null); ``` ``` -------------------------------- ### Manifest Fields Reference Source: https://extensions.stripchat.com/docs/getting-started/manifest Detailed reference for all fields within the manifest.json file. ```APIDOC ## Manifest Fields Reference ### Top-level Fields | Field | Type | Required | Description | |------------------|---------|------------|--------------------------------------------------| | `version` | `string`| Yes | Manifest format version. Must be `"v2.0"`. | | `views` | `object`| Yes | Defines the rendering contract — slots, pages, resolver, and settings. | | `moveableSlot` | `object`| Conditional| Required when `moveableOverlay` is listed in `views.slots`. | | `actions` | `array` | No | Backend action definitions. See Backend Actions. | ### `views` Object | Field | Type | Required | Description | |----------------------------|------------|------------|-----------------------------------------------------------------------------| | `views.slots` | `string[]` | Yes | Array of slot names your extension occupies. | | `views.pages` | `object` | Yes | Map of page names to HTML file paths. Each key is an arbitrary name; each value is a path to an HTML file in the archive. | | `views.resolveSlotPageScript`| `string` | Yes | A script that maps each slot to a page key from `views.pages` at runtime. See Resolve Slot Page. | | `views.settings` | `string` | No | Settings HTML entry point. See Extension Settings. | ### `moveableSlot` Object Defines the dimensions of the moveable overlay container. Required only when `views.slots` includes `"moveableOverlay"`. | Field | Type | Required | Description | |--------------------|--------|------------|-------------------------------------------------------| | `moveableSlot.width` | `number`| Yes | Width of the moveable overlay in pixels. Must be a positive integer, max `450px`. | | `moveableSlot.height`| `number`| Yes | Height of the moveable overlay in pixels. Must be a positive integer, max `740px`. | ``` -------------------------------- ### Define settings view in manifest Source: https://extensions.stripchat.com/docs/getting-started/settings Register the settings HTML file within the extension manifest under the views object. ```json { "version": "v2.0", "views": { "settings": "settings.html", "slots": ["mainGameFun", "rightOverlay", "background"], "pages": { "menu": "menu.html", "overlay": "overlay.html", "background": "background.html" }, "resolveSlotPageScript": "resolveSlotPage.js" } } ``` -------------------------------- ### v1.ext.activity.request Source: https://extensions.stripchat.com/docs/api/requests Requests the platform to keep the extension active for a specified duration. ```APIDOC ## RPC v1.ext.activity.request ### Description Requests the platform to keep the extension active for a specified duration to prevent suspension. ### Parameters - **durationMs** (number) - Required - Requested activity duration in milliseconds. ### Response #### Success Response - **isGranted** (boolean) - Whether the platform granted the activity request. ### Request Example ```ts const res = await ext.makeRequest('v1.ext.activity.request', { durationMs: 60000 }); ``` ``` -------------------------------- ### v1.ext.actions.call Source: https://extensions.stripchat.com/docs/getting-started/backend-actions Triggers a pre-defined backend action from the extension SDK. ```APIDOC ## POST v1.ext.actions.call ### Description Executes a server-side action defined in the extension's manifest.json. The platform performs the HTTP request on behalf of the extension. ### Method POST ### Endpoint v1.ext.actions.call ### Request Body - **actionName** (string) - Required - The unique name of the action defined in manifest.json - **params** (object) - Optional - Key-value pairs to populate placeholders in the action configuration ### Request Example { "actionName": "stopDevice", "params": { "deviceId": "dev_456", "token": "tok_abc" } } ``` -------------------------------- ### Make a Request to the Platform Source: https://extensions.stripchat.com/docs/api/methods Use `makeRequest` to send a typed request to the platform and receive a promise with the result. The `request` parameter is the request name, and `params` are specific to each request. ```typescript const ctx = await ext.makeRequest('v1.ext.context.get', null); ``` -------------------------------- ### v1.model.ext.settings.set.requested Source: https://extensions.stripchat.com/docs/api/events Fired in the settings iframe when the model clicks Save. ```APIDOC ## v1.model.ext.settings.set.requested ### Description Fired in the settings iframe when the model clicks Save in the settings modal. Your handler should validate the form and call v1.model.ext.settings.set to persist the settings. ### Payload - **null** ### Request Example ```ts ext.subscribe('v1.model.ext.settings.set.requested', async () => { const settings = { theme: 'neon', rounds: 5 }; const isError = false; await ext.makeRequest('v1.model.ext.settings.set', { settings, isError, }); }); ``` ``` -------------------------------- ### Making Requests Source: https://extensions.stripchat.com/docs/api/methods Sends a typed request to the platform and returns a promise with the result. ```APIDOC ## `makeRequest` Sends a typed request to the platform and returns a promise with the result. ts ```typescript ext.makeRequest(request, params): Promise ``` Argument| Type| Description ---|---|--- `request`| `string`| Request name. See Requests. `params`| varies| Parameters specific to each request. Described per request in Requests. **Returns:** `Promise` resolving to a result specific to the request. See Requests for return types. ### Example ts ```typescript const ctx = await ext.makeRequest('v1.ext.context.get', null); ``` ``` -------------------------------- ### Open sign-up dialog Source: https://extensions.stripchat.com/docs/api/requests Triggers the sign-up dialog for anonymous users. ```typescript await ext.makeRequest('v1.ext.signup.open', { type: 'user' }); ``` -------------------------------- ### Manifest File Structure Source: https://extensions.stripchat.com/docs/getting-started/manifest The manifest.json file is required at the root of every extension archive. It describes which UI slots the extension occupies and how pages map to these slots. ```APIDOC ## Manifest File Structure Every extension archive must include a `manifest.json` file at the root level. The manifest describes which slots your extension occupies, how pages map to those slots, and optionally defines backend actions. ### Minimal Example ```json { "version": "v2.0", "views": { "slots": ["mainGameFun"], "pages": { "menu": "menu.html" }, "resolveSlotPageScript": "resolveSlotPage.js" } } ``` ### Full Example ```json { "version": "v2.0", "views": { "settings": "settings.html", "slots": ["mainSexToy", "moveableOverlay", "background"], "pages": { "menu": "menu.html", "overlay": "overlay.html", "background": "background.html" }, "resolveSlotPageScript": "resolveSlotPage.js" }, "moveableSlot": { "width": 400, "height": 600 }, "actions": [] } ``` ``` -------------------------------- ### Implement context-aware slot resolver Source: https://extensions.stripchat.com/docs/getting-started/resolve-slot-page An implementation of resolveSlotPage.js that uses the context argument to return different pages based on the user's role. ```javascript // resolveSlotPage.js export default function resolveSlotPage(slotType, context) { const isCurrentUserModel = context.user?.id === context.model?.id; if (slotType === 'EXTENSION_SLOT_MAIN_GAME_FUN') { return isCurrentUserModel ? 'model-menu' : 'viewer-menu'; } if (slotType === 'EXTENSION_SLOT_RIGHT_OVERLAY') { return isCurrentUserModel ? 'model-overlay' : 'viewer-overlay'; } if (slotType === 'EXTENSION_SLOT_BACKGROUND') { return 'background'; } return null; } ``` -------------------------------- ### v1.ext.whisper (Broadcast) Source: https://extensions.stripchat.com/docs/getting-started/slots-communication Sends a message through the server to all clients in the room that have this extension loaded. Use this to synchronize state across all users. ```APIDOC ## POST v1.ext.whisper (Broadcast) ### Description Sends a message through the server to all clients in the room that have this extension loaded. Every slot iframe of every user receives the `v1.ext.whispered` event. Use this when you need to synchronize state across all users. ### Method POST ### Endpoint v1.ext.whisper ### Request Body - **data** (object) - Required - The message payload. - **type** (string) - Required - A string to identify the message type. - **...** (any) - Optional - Any other JSON-serializable data. ### Request Example ```json { "data": { "type": "GAME_STARTED", "round": 1 } } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message. #### Response Example ```json { "message": "Message sent successfully" } ``` ### Receiving Event js ```javascript ext.subscribe('v1.ext.whispered', (data) => { if (data.type === 'GAME_STARTED') { // Handle game started event console.log('Game started, round:', data.round); } }); ``` ``` -------------------------------- ### v1.ext.actions.call Source: https://extensions.stripchat.com/docs/api/requests Triggers a backend action defined in the manifest.json. ```APIDOC ## RPC v1.ext.actions.call ### Description Triggers a backend action defined in your manifest.json. Stripchat executes the action server-side and returns the response. ### Parameters - **actionName** (string) - Required - Name of the action as declared in the manifest actions array. - **params** (Record) - Required - Key-value parameters passed to the action. ### Response #### Success Response - **code** (number) - HTTP status code returned by the external server. - **body** (unknown) - Parsed response body. ### Request Example ```ts const result = await ext.makeRequest('v1.ext.actions.call', { actionName: 'stopDevice', params: { deviceId: 'dev_456', token: 'tok_abc' }, }); ``` ``` -------------------------------- ### Trigger a backend action via SDK Source: https://extensions.stripchat.com/docs/getting-started/backend-actions Execute a defined action at runtime using the v1.ext.actions.call method. ```typescript const result = await ext.makeRequest('v1.ext.actions.call', { actionName: 'stopDevice', params: { deviceId: 'dev_456', token: 'tok_abc', }, }); ``` -------------------------------- ### TV1TipSource Enum Source: https://extensions.stripchat.com/docs/api/entities Possible sources for a tip. ```APIDOC ## TV1TipSource Enum ### Description Possible sources for a tip. ### Values - **console**: Tip sent using `/` command. - **tipMenu**: Tip sent using tip menu. - **goal**: Tip sent via goal button. - **epicGoal**: Tip sent to epic goal. - **fullscreen**: Tip sent from the fullscreen view. - **interactiveToy**: Tip sent from the interactive toy. - **publicChat**: Tip sent using public chat, either in public or group show. - **privateChat**: Tip sent from the private chat, in any type of show. - **extension**: Tip sent from one of the extensions. - **sendTipButton**: Tip sent using send tip button. - **feed**: Tip sent from the feed. ``` -------------------------------- ### Define Resolver Script Source: https://extensions.stripchat.com/docs/getting-started/quick-start Create a standalone JavaScript file to map slot types to specific HTML pages. ```javascript // resolveSlotPage.js export default function resolveSlotPage(slotType) { switch (slotType) { case 'EXTENSION_SLOT_MAIN_GAME_FUN': return 'menu'; case 'EXTENSION_SLOT_RIGHT_OVERLAY': return 'overlay'; case 'EXTENSION_SLOT_BACKGROUND': return 'background'; default: return null; } } ``` -------------------------------- ### POST v1.model.ext.settings.set Source: https://extensions.stripchat.com/docs/api/requests Saves extension settings from the settings page, typically called in response to the v1.model.ext.settings.set.requested event. ```APIDOC ## POST v1.model.ext.settings.set ### Description Saves extension settings. Call this in response to the v1.model.ext.settings.set.requested event. ### Method POST ### Endpoint v1.model.ext.settings.set ### Parameters #### Request Body - **settings** (unknown) - Required - The settings object to save. - **isError** (boolean) - Required - Set to true if validation failed to keep the modal open. ### Request Example ```ts ext.subscribe('v1.model.ext.settings.set.requested', async () => { const settings = { theme: 'neon', rounds: 5 }; const isError = false; await ext.makeRequest('v1.model.ext.settings.set', { settings, isError, }); }); ``` ### Response #### Success Response (200) - **result** (null) ``` -------------------------------- ### Handle token tips Source: https://extensions.stripchat.com/docs/api/events Monitor tips occurring in the chat, excluding private tips during public shows. ```typescript ext.subscribe('v1.tokens.spent', ({ tipData }) => { console.log(`Received ${tipData.amount} tokens from ${tipData.source}`); if (tipData.isFromTheCurrentUser) { console.log('This tip was sent by the current user'); } if (tipData.user) { console.log('Tipped by:', tipData.user.username); } }); ``` -------------------------------- ### Retrieve extension settings Source: https://extensions.stripchat.com/docs/api/requests Fetches current extension settings using the v1.model.ext.settings.get endpoint. ```typescript const res = await ext.makeRequest('v1.model.ext.settings.get', null); const settings = res.settings; // populate form fields with settings ``` -------------------------------- ### POST /sessions Source: https://extensions.stripchat.com/docs/getting-started/backend-actions Creates a new session by sending parameters as a JSON body to the external API. ```APIDOC ## POST /sessions ### Description Creates a new session via an external API call. ### Method POST ### Endpoint https://api.example.com/sessions ### Request Body - **name** (string) - Required - The name of the session - **mode** (string) - Required - The mode of the session (e.g., interactive) ### Request Example { "name": "my-session", "mode": "interactive" } ### Response #### Success Response (200) - **code** (number) - HTTP status code from the external server - **body** (unknown) - Parsed response body ``` -------------------------------- ### Define action parameters Source: https://extensions.stripchat.com/docs/getting-started/backend-actions Specify input parameters for actions using shorthand type strings or object definitions. These parameters can be used as placeholders in URLs and headers. ```json { "params": { "deviceId": "string", "userId": "number" } } ``` -------------------------------- ### v1.payment.tokens.spend Source: https://extensions.stripchat.com/docs/api/requests Initiates a token spend for the current user. ```APIDOC ## POST v1.payment.tokens.spend ### Description Initiates a token spend for the current user. Stripchat shows a confirmation dialog to the user before deducting tokens. ### Request Body - **tokensAmount** (number) - Required - Number of tokens to spend. - **tokensSpendData** (Record) - Required - Arbitrary metadata attached to the transaction. ### Request Example { "tokensAmount": 10, "tokensSpendData": { "action": "spin_wheel", "round": 3 } } ``` -------------------------------- ### Slots Source: https://extensions.stripchat.com/docs/getting-started/manifest Information about how extensions occupy UI slots. ```APIDOC ## Slots The `views.slots` array determines which UI slots your extension will render into. Available slot keys depend on the extension category selected in the Extension Platform. Each slot listed in `views.slots` must have a corresponding HTML page mapped through `views.pages` and the resolver script. For a detailed explanation of what each slot does and where it appears in the UI, see Extension Slots. ``` -------------------------------- ### v1.tokens.spent Source: https://extensions.stripchat.com/docs/api/events Fired on every tip in chat for both model and user. ```APIDOC ## v1.tokens.spent ### Description Fired on every tip in chat for both model and user. Does not fire on private tips during public shows. ### Payload - **tipData** (TV1TipData) - Tip details including amount, source, and user info. ### Request Example ```ts ext.subscribe('v1.tokens.spent', ({ tipData }) => { console.log(`Received ${tipData.amount} tokens from ${tipData.source}`); if (tipData.isFromTheCurrentUser) { console.log('This tip was sent by the current user'); } if (tipData.user) { console.log('Tipped by:', tipData.user.username); } }); ``` ``` -------------------------------- ### JavaScript Slot Resolver Logic Source: https://extensions.stripchat.com/docs/getting-started/resolve-slot-page Implement the `resolveSlotPage` function to dynamically determine which page to load for a given slot type. Use `extSettings` to conditionally return a page or `null`. ```javascript // resolveSlotPage.js export default function resolveSlotPage(slotType, context, extSettings) { if (slotType === 'EXTENSION_SLOT_MAIN_SEX_TOY') { return 'main'; } if (slotType === 'EXTENSION_SLOT_MOVEABLE_OVERLAY') { return extSettings?.enableOverlay ? 'overlay' : null; } if (slotType === 'EXTENSION_SLOT_BACKGROUND') { return 'background'; } return null; } ``` -------------------------------- ### v1.monitoring.report.log Source: https://extensions.stripchat.com/docs/api/requests Reports an extension-side diagnostic log to the platform monitoring pipeline. ```APIDOC ## POST v1.monitoring.report.log ### Description Reports an extension-side diagnostic log to the platform monitoring pipeline. Use this for important lifecycle events or fallback decisions. ### Request Body - **message** (string) - Required - Short stable log message that identifies the event. - **data** (unknown) - Required - Additional structured context for debugging. ### Request Example { "message": "fallback mode enabled", "data": { "stage": "bootstrap", "feature": "realtime-sync" } } ``` -------------------------------- ### v1.ext.context.updated Source: https://extensions.stripchat.com/docs/api/events Fired whenever the room context changes, such as user joins, show status changes, or model online/offline status. ```APIDOC ## v1.ext.context.updated ### Description Fired whenever the room context changes — for example, when a user joins, the show status changes, or the model goes online/offline. ### Payload - **context** (TV1ExtContext) - Updated context object containing model and user. ### Request Example ```ts ext.subscribe('v1.ext.context.updated', ({ context }) => { if (context.model) { console.log('Model status:', context.model.status); } if (context.user) { console.log('User:', context.user.username); } }); ``` ``` -------------------------------- ### Spend tokens Source: https://extensions.stripchat.com/docs/api/requests Initiates a token spend transaction and listens for the success event. ```typescript await ext.makeRequest('v1.payment.tokens.spend', { tokensAmount: 10, tokensSpendData: { action: 'spin_wheel', round: 3, }, }); ext.subscribe('v1.payment.tokens.spend.succeeded', (data) => { console.log(`Spent ${data.tokensAmount} tokens`); console.log(data.tokensSpendData); // { action: 'spin_wheel', round: 3 } }); ``` -------------------------------- ### Interact with SDK Source: https://extensions.stripchat.com/docs/getting-started/quick-start Perform common SDK operations including reading context, subscribing to events, and sending whisper messages. ```typescript // Read context const ctx = await ext.makeRequest('v1.ext.context.get', null); // Subscribe to events ext.subscribe('v1.ext.context.updated', ({context}) => { // handle context update }); // Send a whisper to other slots await ext.makeRequest('v1.ext.whisper.local', { data: {type: 'READY'}, }); ``` -------------------------------- ### Configure Themed Background Colors Source: https://extensions.stripchat.com/docs/getting-started/slots-layout Use CSS variables on the html element to support light and dark themes while ensuring the background covers the full slot area. ```css :root { --frame-bg: #1c1c1c; } html[data-theme='light'] { --frame-bg: #f7f7f7; } html { height: 100%; background-color: var(--frame-bg); } ``` -------------------------------- ### Define the extension ZIP archive structure Source: https://extensions.stripchat.com/docs/getting-started/archive-structure The root of the ZIP archive must contain the manifest, resolution script, icon, and HTML files for each slot. ```text extension.zip ├── manifest.json # required ├── resolveSlotPage.js # required ├── settings.html # optional ├── icon.svg # required ├── any-name-1.html # required for each slot defined in manifest.json ├── ... └── any-name-N.html # required for each slot defined in manifest.json ``` -------------------------------- ### Receive v1.ext.whispered Event Source: https://extensions.stripchat.com/docs/getting-started/slots-communication Subscribes to broadcasted messages from the server. ```js ext.subscribe('v1.ext.whispered', (data) => { if (data.type === 'GAME_STARTED') { foo(data.round); } }); ``` -------------------------------- ### Defining Actions in manifest.json Source: https://extensions.stripchat.com/docs/getting-started/backend-actions Schema for defining externalCall actions in the extension manifest. ```APIDOC ## Configuration: externalCall ### Description Defines an HTTP request action that the platform will execute server-side. ### Parameters - **name** (string) - Required - Unique identifier for the action - **type** (string) - Required - Must be "externalCall" - **config** (object) - Required - Contains action, method, headers, and body - **params** (object) - Optional - Definitions of input parameters for placeholder substitution - **available_for_guests** (boolean) - Optional - Whether guests can trigger this action ### Request Example { "name": "stopDevice", "type": "externalCall", "config": { "action": "https://api.example.com/devices/{{deviceId}}/stop", "method": "PUT", "headers": { "Authorization": "Bearer {{token}}" } }, "params": { "deviceId": "string", "token": "string" } } ``` -------------------------------- ### v1.ext.whisper Source: https://extensions.stripchat.com/docs/api/requests Broadcasts a message to all clients in the room. ```APIDOC ## POST v1.ext.whisper ### Description Broadcasts a message through the server to all clients in the room that have this extension loaded. ### Request Body - **data** (Record) - Required - Any JSON-serializable object. ### Request Example { "data": { "type": "GAME_STARTED", "round": 1 } } ``` -------------------------------- ### Read settings from slots Source: https://extensions.stripchat.com/docs/getting-started/settings Access current extension settings from any slot at runtime. ```typescript const res = await ext.makeRequest('v1.ext.settings.get', null); const settings = res.settings; ``` -------------------------------- ### v1.ext.movableOverlay.update Source: https://extensions.stripchat.com/docs/api/requests Updates the status and optional message of the moveableOverlay slot. ```APIDOC ## POST v1.ext.movableOverlay.update ### Description Updates the status and optional message of the moveableOverlay slot, a small floating indicator visible to the user. ### Request Body - **status** ('active' | 'inactive' | 'connecting' | 'error') - Optional - Visual state of the overlay pill. - **message** (string) - Optional - Short text displayed inside the pill. ### Request Example { "status": "active", "message": "Connected" } ``` -------------------------------- ### Handle successful token spend Source: https://extensions.stripchat.com/docs/api/events React to confirmed token spend transactions initiated by the extension. ```typescript ext.subscribe('v1.payment.tokens.spend.succeeded', (data) => { console.log(`Spent ${data.tokensAmount} tokens`); console.log('Metadata:', data.tokensSpendData); console.log('Anonymous:', data.isAnonymous); }); ``` -------------------------------- ### v1.payment.tokens.spend.succeeded Source: https://extensions.stripchat.com/docs/api/events Fired when a token spend initiated by the extension is successfully confirmed and processed. ```APIDOC ## v1.payment.tokens.spend.succeeded ### Description Fired when a token spend initiated by v1.payment.tokens.spend is successfully confirmed by the user and processed. ### Payload - **tokensAmount** (number) - Number of tokens spent. - **tokensSpendData** (Record) - The metadata object passed in the original request. - **isAnonymous** (boolean) - Whether the spend was made anonymously. ### Request Example ```ts ext.subscribe('v1.payment.tokens.spend.succeeded', (data) => { console.log(`Spent ${data.tokensAmount} tokens`); console.log('Metadata:', data.tokensSpendData); console.log('Anonymous:', data.isAnonymous); }); ``` ``` -------------------------------- ### v1.monitoring.report.error Source: https://extensions.stripchat.com/docs/api/requests Reports an extension-side error to the platform monitoring pipeline. ```APIDOC ## RPC v1.monitoring.report.error ### Description Reports an extension-side error to the platform monitoring pipeline. ### Parameters - **message** (string) - Required - Short stable error message that identifies the failure type. - **data** (unknown) - Optional - Additional structured context for debugging. ### Response #### Success Response - **result** (null) ### Request Example ```ts await ext.makeRequest('v1.monitoring.report.error', { message: 'extension bootstrap failed', data: { stage: 'bootstrap' }, }); ``` ``` -------------------------------- ### TV1TipData Entity Source: https://extensions.stripchat.com/docs/api/entities Information about a tip sent within the extension. ```APIDOC ## TV1TipData Entity ### Description Information about a tip sent within the extension. ### Fields - **amount** (number) - Amount of tokens spent. - **isAnonymous** (boolean) - Whether the tip was anonymous. - **isFromTheCurrentUser** (boolean) - Whether the tip was sent by the current user. - **isOriginalSource** (boolean) - Whether the tip was sent from the current extension. - **message** (string | undefined) - Message sent with the tip. Empty string if no message was sent. - **source** (TV1TipSource) - Source of the tip. - **type** ('private' | 'public') - Whether the tip was sent in public or private chat. - **user** (TV1ExtUser | null | undefined) - User who sent the tip. Can be `null` for anonymous tips. ``` -------------------------------- ### Configure a delayed event Source: https://extensions.stripchat.com/docs/getting-started/backend-actions Define a polling-based action that executes a target action after a specified delay in milliseconds. ```json { "name": "delayedCloseSession", "type": "delayedEvent", "config": { "action": "closeSession", "delay_ms": 30000 }, "params": { "sessionId": "string", "token": "string" } } ``` -------------------------------- ### Call a Backend Action Source: https://extensions.stripchat.com/docs/api/requests Trigger a backend action defined in `manifest.json`. Stripchat executes the action server-side and returns the response. Ensure actions are not called unconditionally from the background slot to avoid overwhelming your backend. ```typescript const result = await ext.makeRequest('v1.ext.actions.call', { actionName: 'stopDevice', params: { deviceId: 'dev_456', token: 'tok_abc', }, }); console.log(result.code); // 200 console.log(result.body); // response from the external server ``` -------------------------------- ### Subscribe to a Platform Event Source: https://extensions.stripchat.com/docs/api/methods Use `subscribe` to listen for platform events. The provided handler function will be invoked with the event payload each time the event is emitted. ```typescript ext.subscribe('v1.ext.context.updated', ({ context }) => { console.log(context); }); ``` -------------------------------- ### TV1ExtModel Entity Source: https://extensions.stripchat.com/docs/api/entities Details about the model (broadcaster) in the current room. ```APIDOC ## TV1ExtModel Entity ### Description Details about the model (broadcaster) in the current room. ### Fields - **id** (number) - Model user ID. - **username** (string) - Model username. - **name** (string) - Model display name. Empty string for models with no display name. - **avatarUrlThumb** (string) - URL of model avatar thumbnail. - **gender** (TV1Genders) - Performer composition in the room. - **status** (TV1ModelStatus) - Current show status. - **isPrivateEnabled** (boolean) - Whether Private show is enabled. - **isSpyEnabled** (boolean) - Whether spy feature is enabled for the Private show. When enabled, users can spy on an already started Private show at a lower cost. - **isExclusivePrivateEnabled** (boolean) - Whether Exclusive Private show is enabled. - **isNonNude** (boolean) - Whether the model account is configured as non-nude (also known as Flirting Mode). ``` -------------------------------- ### Subscribe to context updates Source: https://extensions.stripchat.com/docs/api/events Listen for changes in room context such as user joins or model status updates. ```typescript ext.subscribe('v1.ext.context.updated', ({ context }) => { console.log(context); }); ``` ```typescript ext.subscribe('v1.ext.context.updated', ({ context }) => { if (context.model) { console.log('Model status:', context.model.status); } if (context.user) { console.log('User:', context.user.username); } }); ``` -------------------------------- ### TV1ExtUser Entity Source: https://extensions.stripchat.com/docs/api/entities Information about the current user interacting with the extension. ```APIDOC ## TV1ExtUser Entity ### Description Information about the current user interacting with the extension. ### Fields - **id** (number) - User ID. - **username** (string) - User username. - **status** (TV1UserStatus) - Current show/session state for this user (`public`, `private`, etc.). - **hasTokens** (boolean) - Whether the user has tokens. - **hasPaidBefore** (boolean) - Whether the user previously purchased tokens. - **hasUltimateSubscription** (boolean) - Whether the user has Ultimate membership. - **isModel** (boolean) - Whether the current user is the model (useful for branching UI). - **userRanking** (TV1UserRanking | undefined) - User activity ranking data when available. ``` -------------------------------- ### Subscribing to Events Source: https://extensions.stripchat.com/docs/api/methods Subscribes to a platform event. The handler is called each time the event is emitted. ```APIDOC ## `subscribe` Subscribes to a platform event. The handler is called each time the event is emitted. ts ```typescript ext.subscribe(eventName, handler): void ``` Argument| Type| Description ---|---|--- `eventName`| `string`| Event name to subscribe to. See Events for the full list. `handler`| `(data) => void`| Callback invoked with the event payload. ### Example ts ```typescript ext.subscribe('v1.ext.context.updated', ({ context }) => { console.log(context); }); ``` ``` -------------------------------- ### HTML Theme Attribute Source: https://extensions.stripchat.com/docs/getting-started/theming The platform sets the 'data-theme' attribute on the element to 'dark' or 'light' based on the current interface theme. ```html ``` -------------------------------- ### Request private show Source: https://extensions.stripchat.com/docs/api/requests Triggers the private show request flow. ```typescript await ext.makeRequest('v1.private.request', null); ``` -------------------------------- ### Background Slot Coordinator Pattern Source: https://extensions.stripchat.com/docs/getting-started/slots-communication Uses the background slot to maintain state and relay messages to visual slots. ```js // background slot const ext = createExtHelper(); let gameState = { round: 0, scores: {} }; ext.subscribe('v1.ext.whispered', (data) => { if (data.type === 'PLAYER_ACTION') { gameState = bar(gameState, data); // relay updated state to local UI slots ext.makeRequest('v1.ext.whisper.local', { data: { type: 'STATE_UPDATE', state: gameState }, }); } }); ``` ```js // rightOverlay slot const ext = createExtHelper(); ext.subscribe('v1.ext.whispered', (data) => { if (data.type === 'STATE_UPDATE') { foo(data.state); } }); ``` -------------------------------- ### TV1ExtContext Entity Source: https://extensions.stripchat.com/docs/api/entities Represents the context of the extension within a room, providing information about the broadcaster and the current user. ```APIDOC ## TV1ExtContext Entity ### Description Represents the context of the extension within a room, providing information about the broadcaster and the current user. ### Fields - **model** (TV1ExtModel | undefined) - Broadcaster for the current room. - **user** (TV1ExtUser | undefined) - Current user running the extension (viewer, model, or studio context). ``` -------------------------------- ### Send v1.ext.whisper Broadcast Source: https://extensions.stripchat.com/docs/getting-started/slots-communication Broadcasts a message to all clients in the room via the server. ```js await ext.makeRequest('v1.ext.whisper', { data: { type: 'GAME_STARTED', round: 1, }, }); ``` -------------------------------- ### Handle settings save request Source: https://extensions.stripchat.com/docs/getting-started/settings Subscribe to the save request event to validate form state and persist settings. ```typescript ext.subscribe('v1.model.ext.settings.set.requested', async () => { // gather your form state and validate it using your own logic const settings = { /* your settings object */ }; const isError = false; // set to true if validation failed await ext.makeRequest('v1.model.ext.settings.set', { settings, isError, }); }); ``` -------------------------------- ### Handle settings save request Source: https://extensions.stripchat.com/docs/api/events Triggered when a model saves settings in the modal; use this to validate and persist configuration. ```typescript ext.subscribe('v1.model.ext.settings.set.requested', async () => { const settings = { theme: 'neon', rounds: 5 }; const isError = false; await ext.makeRequest('v1.model.ext.settings.set', { settings, isError, }); }); ```