# Alert Groups Source: https://developers.chameleon.io/apis/alert-groups Alert Groups are used for Tours and Microsurveys to notify any relevant Team members when an Experience is in violation of the alert conditions. In the HTTP Response for [Listing](/apis/alert-groups#alert-groups-index) and [Showing](/apis/alert-groups#alert-groups-show) Alert Groups, the full list of matching [Experiences](/concepts/experiences) are returned as the `experiences` key. *** ## Schema | Property | Type | Description | | ------------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `kind` | string | The kind of matched Experiences for this Alert Group. [More info ↓](/apis/alert-groups#alert-group-kinds): One of `all`, `tour`, `survey`, `tags`, or `campaigns` | | `interval` | number | # of days that the alerting condition should wait before triggering a violation | | `published_at` | timestamp | The time this was most recently published | | `style` | string | The style of alert condition to evaluate. [More info ↓](/apis/alert-groups#alert-group-styles): One of `unseen` or `uncompleted` | | `last_notified_at` | timestamp | Last time this alert was triggered for any Experience | | `tag_ids` | array | When `kind=tags`, the IDs of the [Tags](/apis/tags) that Experiences must be tagged with to be included in this Alert Group | | `campaign_ids` | array | When `kind=campaigns`, the IDs of the [Experiences](/concepts/experiences) to be included in this Alert Group | | `slack_uid` | string | The Slack channel ID to notify on, only when `opt_in_slack_at` has a value | | `opt_in_slack_at` | timestamp | Whether or not to send triggered alerts to Slack on the `slack_uid` channel | | `emails` | array | The email address(es) to message, only when `opt_in_email_at` has a value | | `opt_in_email_at` | timestamp | Whether or not to send triggered alerts to the given list of `emails` | ##### Kinds of Alert Groups (`kind` property) An Alert Group creates a **dynamic** or **static** group of Experiences. Each experience is checked for violation of the alert conditions. | Kind | - | Description | | ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `all` | dynamic | All currently published [Tours](/apis/tours) + [Microsurveys](/apis/surveys) | | `tour` | dynamic | All published [Tours](/apis/tours) | | `survey` | dynamic | All published [Microsurveys](/apis/surveys) | | `tags` | dynamic | All published [Tours](/apis/tours) + [Microsurveys](/apis/surveys) with ***any*** of the specified [Tags](/apis/tags) in the `tag_ids` list | | `campaigns` | static | All published [Tours](/apis/tours) + [Microsurveys](/apis/surveys) ***explicitly*** in the `campaign_ids` list | ##### Alerting conditions (`style` property) | Kind | - | Description | | ------------- | - | ------------------------------------------------------------------------------------------------------------------ | | `unseen` | - | An Experience that is not Seen (i.e. displayed to any User) during the `interval` # of days will trigger an alert. | | `uncompleted` | - | An Experience that is not Completed (i.e. no User finished) during the `interval` # of days will trigger an alert. | ## Listing Alert Groups Retrieve a list of **all** Alert Groups and **all** currently matching [Experiences](/concepts/experiences). An account typically has 1-5 Alert Groups so this response should be relatively small. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/alert_groups ``` #### HTTP Response ```json theme={null} { "alert_groups": [ { "id": "5f3c4232c712de665632a6e2", "name": "Research opportunities flow (at least 1 per 2 weeks)", "interval": 14, "style": "uncompleted", "kind": "campaigns", "campaign_ids": [ "5f3c4232c712de665632a6d5", "5f3c4232c712de665632a2a3" ], ... "experiences": [ { "id": "5f3c4232c712de665632a6d5", "name": "Research: Planed New Feature X", ... }, { "id": "5f3c4232c712de665632a2a3", "name": "Research: New Feature Z", ... } ] }, { "id": "5f3c4232c712de665632a6e1", "name": "Any Tour/Microsurvey that goes 1 week without a completion", "interval": 7, "style": "uncompleted", "kind": "all", ... "experiences": [ ... ] }, { "id": "5f3c4232c712de665632a6d8", "name": "Broken Feature announcements (1 day not Seen)", "interval": 1, "style": "unseen", "kind": "tags", "tag_ids": [ "5f3c4232c712de665632a5d7", "5f3c4232c712de665632aa3b" ], ... "experiences": [ ... ] }, ... ] } ``` *** ## Showing an Alert Group Retrieve a single Alert Group and **all** currently matching [Experiences](/concepts/experiences). #### HTTP Request | param | - | description | | ----- | -------- | --------------------------- | | `id` | required | An Alert Group ID to lookup | ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/alert_groups/:id ``` #### HTTP Response ```json theme={null} { "alert_group": { "id": "5f3c4232c712de665632a6e2", "name": "Research opportunities flow (at least 1 per 2 weeks)", "interval": 14, "style": "uncompleted", "kind": "campaigns", "campaign_ids": [ "5f3c4232c712de665632a6d5", "5f3c4232c712de665632a2a3" ], "experiences": [ { "id": "5f3c4232c712de665632a6d5", "name": "Research: Planed New Feature X", ... }, { "id": "5f3c4232c712de665632a2a3", "name": "Research: New Feature Z", ... } ], ... } } ``` # Buttons Source: https://developers.chameleon.io/apis/buttons Buttons are the configuration for a specific call to action on a Step. They contain information about styling, positioning, and any actions that should be taken when clicked. Buttons define the interactive call-to-action elements within [Steps](/apis/steps). Each Step can have one or more Buttons that control what happens when a user clicks them — navigating the Tour, opening a URL, running JavaScript, triggering another Experience, and more. *** ## Schema | Property | Type | Description | | -------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `text` | string | The call to action text for this button | | `position` | string | The placement of this button: One of `bottom_left`, `bottom_center`, `bottom_right`, `center_right`, or `center_left` | | `tour_action` | string | What does this [Tour](/apis/tours) do when clicked: One of `next`, `previous`, or `exit` | | `additional_actions` | array\ | What else does this Button do when clicked: One of `cta`, `cta_url`, `any_click`, `code`, `element_click`, `hero_button`, `tour`, `survey`, `exit`, `tag_user`, `property`, `helpbar`, `automation`, `demo` | | `action_url` | string | When `additional_actions` includes `cta_url` this is the URL to load (`action_new_window=true` opens this URL in a new tab) | | `action_new_window` | boolean | Should the `action_url` open in a new tab | | `action_script` | string | When `additional_actions` includes `code` this is the JavaScript code snippet to evaluate | | `action_element` | object | When `additional_actions` includes `element_click` this is the [Element](/apis/elements) targeted for clicking | | `action_campaign_id` | ID | When `additional_actions` includes `tour` or `survey`, the ID of the Tour or Microsurvey to link to | ### Button action types | Action | Description | | --------------- | -------------------------------------------------------------------------------- | | `cta_url` | Navigate the user to a URL. Set `action_url` and optionally `action_new_window`. | | `code` | Execute a JavaScript snippet defined in `action_script`. | | `element_click` | Programmatically click an element on the page defined by `action_element`. | | `tour` | Start another Tour specified by `action_campaign_id`. | | `survey` | Start a Microsurvey specified by `action_campaign_id`. | | `exit` | Dismiss/close the current Experience. | | `tag_user` | Apply a Tag to the current user. | | `property` | Set a property on the current user's profile. | | `helpbar` | Open the HelpBar. | | `automation` | Start a Chameleon Automation. | | `demo` | Start a Chameleon Demo. | | `hero_button` | A primary hero-style button with emphasis styling. | | `any_click` | Trigger on any click within the step (not just the button). | #### Example button JSON ```json theme={null} { "id": "5f3c4232c712de665632a9b1", "created_at": "2029-04-07T12:18:00Z", "updated_at": "2029-04-07T12:18:00Z", "text": "Learn more", "position": "bottom_right", "tour_action": "next", "additional_actions": ["cta_url"], "action_url": "https://help.chameleon.io/getting-started", "action_new_window": true } ``` #### Example button with JavaScript action ```json theme={null} { "id": "5f3c4232c712de665632a9b2", "text": "Open settings", "position": "bottom_right", "tour_action": "exit", "additional_actions": ["code"], "action_script": "window.location.hash = '#/settings';" } ``` *** ## Buttons in context Buttons appear as an array within [Step](/apis/steps) objects. They are not listed or retrieved independently. ```json theme={null} { "step": { "id": "5f3c4232c712de665632a8f1", "title": "Welcome!", "body": "Let's get you started with a quick tour.", "buttons": [ { "id": "5f3c4232c712de665632a9b1", "text": "Show me", "position": "bottom_right", "tour_action": "next", "additional_actions": [] }, { "id": "5f3c4232c712de665632a9b2", "text": "Not now", "position": "bottom_left", "tour_action": "exit", "additional_actions": [] } ] } } ``` See also: * [Steps](/apis/steps) — where buttons are defined * [Tours](/apis/tours) — which contain steps with buttons * [Webhook: tour.button.clicked](/webhooks/outgoing#example-tour-button-clicked) — receive events when buttons are clicked # Changes Source: https://developers.chameleon.io/apis/changes Changes are a record of every update made to your key models (Experiences). * [Tours](/apis/tours) * [Surveys](/apis/surveys) * [Embeds](/apis/embeddables) * [Launchers](/apis/launchers) * [Tooltips](/apis/tooltips) * [Steps](/apis/steps) *** Use the feed of changes to: * Export a paper trail to know which changes made the biggest impact. * Ensure that your most important Experiences stay static. Do this by listing all changes for a specific Experience and make sure the set of changes is empty * Audit an issue with the delivery of an Experience. ## Schema | Property | Type | Description | | --------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `experience_id` | ID | The ID of the parent model that this change represents. (a [Tour](/apis/tours) when model is a [Step](/apis/steps) | | `model_id` | ID | The ID of the model that this change represents | | `model_type` | string | The type of the model that this change represents | | `kind` | string | The type of change this represents: One of: `create`, `update`, `destroy`, `raw`, `partial`, `related`, `revert`, or `apply` | | `path` | string | They keypath this change represents | | `object` | object | The underlying value of this change. It can be an object with scalar values (for a `kind=create` or `kind=destroy`) or values as a 2-item array of the \[`before`, `after`] [diff](/apis/changes#schema-diff-item) | | `options` | object | A hash of other information about this change. Values are a [diff](/apis/changes#schema-diff-item). | | `user` | object | The Chameleon admin who made this change. Contains `id`, `name`, and `email` | ### Change "Diff item" Schema Each value is a 2-item array `[BEFORE, AFTER]`. If the value changed from `"silver"` to `"gold"` then: ``` ["silver", "gold"] ``` In the context of a Change `object`: ```json theme={null} { "plan": ["silver", "gold"], "monthly_spend": [99, 249] } ``` ## List Changes List all Changes. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/changes ``` or ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/:model_kind/:model_id/changes ``` | param | - | description | | ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------- | | `limit` | optional | Defaults to `50` with a maximum of `500` | | `before` | optional | Used when paginating, use directly from the `cursor` object from the previous response | | `before` | optional | Read as "created `before`" and can be given as a timestamp to get only `limit` items that were created before this time | | `after` | optional | Read as "created `after`" and can be given as a timestamp or ID to get only `limit` items that were created after this time | | `filters` | optional | An array of properties to filter `Changes` with; use this to fetch "all changes for a specific set of properties" | | `model_kind` | optional | A `kind` of model to fetch changes for. One of `tour`, `survey`, `embed`, `launcher`, or `tooltip`. | | `model_id` | optional | The ID of the model to fetch changes for | ##### Examples Only changes for the `6f3c4232c712de665632a6d5` Tour ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/tours/6f3c4232c712de665632a6d5/changes ``` Only changes to the `published_at` property of any Experience ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/changes?filter=published_at ``` #### HTTP Response ```json theme={null} { "changes": [ { "id": "6f3c4232c712de665632a6d5", "created_at": "2029-04-07T12:38:00Z", "experience_id": "6f3c1931c712d632a6d5e665", "model_id": "6f3c1931c712d632a6d5e665", "model_type": "Campaign", "kind": "update", "path": "model", "object": { "published_at": [ "2029-04-07T10:00:00Z", "2029-04-07T12:38:00Z" ], "published_at_count": [1, 2] }, "options": {}, "user": { "id": "5e3c4232c712de665632a6a1", "name": "Jane Smith", "email": "jane@example.com" } }, { "id": "6f3c4232c712de665632a6d6", "created_at": "2029-04-07T12:30:00Z", "experience_id": "6f3c1931c712d632a6d5e665", "model_id": "6e3c193a6d5e51c712d63266", "model_type": "Step", "kind": "update", "path": "model", "object": { "body": [ "### We've updated all of the data things!", "### We've upgraded the data things!" ] }, "options": { "capture_id": ["6d3c4232c665632a712de2f1", "6d3c423665632a2c712de2f7"] }, "user": { "id": "5e3c4232c712de665632a6a1", "name": "Jane Smith", "email": "jane@example.com" } }, ... ], "cursor": { "limit": 50, "before": "6f3c4232c712de665632a6d6" } } ``` ## Summary of Changes ## Summary Schema | Property | Type | Description | | ------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `model_id` | ID | The ID of the model that this change represents | | `path` | string | They keypath this change represents | | `kind` | string | The type of change this represents: One of: `create`, `update`, `destroy` | | `change_id` | array | A 2-item array of the \[`before`, `after`] [diff](/apis/changes#schema-diff-item) of Screen Capture ID of this change. Note some changes are no represented visually and will have null value for the `after` value | | `capture_id` | array | A 2-item array of the \[`before`, `after`] [diff](/apis/changes#schema-diff-item) of Screen Capture ID of this change. Note some changes are no represented visually and will have null value for the `after` value | | `object` | object\ | A [ChangeUpdate](/apis/changes#schema-summary-change-update-item) of properties that have changed for this model | | `changes` | array\ | An Array of [ChangeUpdate](/apis/changes#schema-summary-change-update-item) items representing changes to child associated models ([Steps](/apis/steps), [Buttons](/apis/buttons) etc. | ### Change update object Schema | Property | Type | Description | | ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `name` | string | The name of the underlying property that changed | | `description` | string | A longer description of the underlying property | | `value` | object | The underlying value of this change. It can be an object with scalar values (for a `kind=create` or `kind=destroy`) or values as a 2-item array of the \[`before`, `after`] [diff](/apis/changes#schema-diff-item) | ##### Examples ```json theme={null} { "name": "Step created", "description": null, "value": { "id": "6f3c4232c712de665632a6d6", ... } } ``` ```json theme={null} { "name": "Body", "description": "The content of the Step", "value": ["New features are here!", "New features have arrived!"] } ``` ## Change Summary List all Change Summaries #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/:model_kind/:model_id/changes/summary ``` | param | - | description | | ------------ | -------- | --------------------------------------------------------------------------------------------------- | | `model_kind` | required | A `kind` of model to fetch changes for. One of `tour`, `survey`, `embed`, `launcher`, or `tooltip`. | | `model_id` | required | The ID of the model to fetch changes for | #### HTTP Response ```json theme={null} { "model_id": "6f3c1931c712d632a6d5e665", "kind": "create", "change_id": [ "5e3c4232c712de665632a6d9", "5f3c42665632a6d932c712de" ], "path": "model", "object": { "id": "6f3c1931c712d632a6d5e665", "name": "New data importing options", ... }, "changes": [ { "model_id": "6e3c193a6d5e51c712d63266", "kind": "create", "capture_id": [ ... ], "object": { "id": "6e3c193a6d5e51c712d63266", "body": "Welcome!", ... }, ... }, { "model_id": "6e3c193a6d5e51c712d63266", "kind": "update", "capture_id": [ ... ], "object": { "body": ["Welcome!", "Hello and Welcome"], ... } ... } ], ... } ``` # Companies Source: https://developers.chameleon.io/apis/companies Companies represent your *accounts*: real customers who were identified to Chameleon. They can store complex (semi-arbitrary) properties. > For a full list of your User / Company Properties see the [Properties API](/apis/properties) *** ## Schema #### Fully-expanded [Company](/apis/companies) when listed directly or embedded with `expand` param specified properly | Property | Type | Description | | -------------- | --------- | -------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `uid` | string | The external ID that came from your backend system | | `*any options` | mixed | Any other options you have sent as Custom Properties will show up here too | #### Non-expanded [Company](/apis/companies) when embedded in another (i.e. Microsurvey response) | Property | Type | Description | | ------------ | --------- | --------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `uid` | string | The external ID that came from your backend system | ## Create or Update a Company See the [Companies Webhook](/webhooks/companies) for sending User data to Chameleon ## Retrieve a Company Retrieve a single Company. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/analyze/companies/:id ``` or ```http title="GET" theme={null} https://api.chameleon.io/v3/analyze/company?uid=:uid ``` | param | - | description | | ----- | -------- | -------------------------------------------------------------------- | | `id` | optional | The Chameleon ID of the Company | | `uid` | optional | The Company identifier (typically the Database ID from your backend) | ```json theme={null} { "company": { "id": "5f3c4232c712de665632a2a1", "created_at": "2029-04-07T12:38:00Z", "uid": "1868", "domain": "example.com", "plan": "custom-92", "clv": 231902.42, ... } } ``` ## List Companies List all Companies. #### HTTP Request ``` GET|POST https://api.chameleon.io/v3/analyze/companies ``` | param | - | description | | ---------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | | `limit` | optional | Defaults to `50` with a maximum of `500` | | `before` | optional | Used when paginating, use directly from the `cursor` object from the previous response | | `before` | optional | Read as "created `before`" and can be given as a timestamp to get only `limit` items that were created before this time | | `after` | optional | Read as "created `after`" and can be given as a timestamp or ID to get only `limit` items that were created after this time | | `expand` | optional | Object that specifies relationships to include/exclude. Supported keys are `company` | | `expand.company` | optional | use values of `all`, `min` to control the properties present in the `company`. Defaults to `all` | #### Using the `expand` parameter ``` # As a URL parameter expand[profile]=min&expand[company]=skip # In the Request body {"expand":{"profile":"min","company":"skip"}} ``` #### HTTP Response ```json theme={null} { "companies": [ { "id": "5f3c4232c712de665632a6d5", "created_at": "2029-04-07T12:38:00Z", "uid": "1868", "domain": "example.com", "plan": "custom-92", "clv": 231902.42, ... }, { "id": "5f3c4232c712de665632a2a1", "created_at": "2029-04-07T12:38:00Z", "uid": "2015", "domain": "chameleon.io", "plan": "custom-12", "clv": 39102.17, ... }, ... ], "cursor": { "limit": 50, "before": "5f3c4232c712de665632a2a1" } } ``` ### Search Companies Searching Companies through the Chameleon API allows you to: * Search for a company by `id`, `uid`, or any custom company property you have sent to us. * Filter companies using [Segmentation Filter Expressions](/concepts/filters) with the `property` and `group` kinds. * Sort the matching companies by any company property. * Get the [Count of Companies](#companies-count) matching a set of filters. > *Note: [Rate Limiting](/concepts/rate-limiting) applies according to the table below.* | endpoint | Maximum concurrent requests | | ------------ | --------------------------- | | `/companies` | 2 | #### HTTP Request ``` GET|POST https://api.chameleon.io/v3/analyze/companies ``` | param | - | description | | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `filters` | optional | The array of [Segmentation filter expressions](/concepts/filters) used to match companies. Only the `property` and `group` kinds are supported (see the note below) | | `filters_op` | optional | The operator to apply between each filter. Use either `or` or `and` (default) | | `sort_by` | optional | A company property name to sort by — one of `id`, `uid`, `created_at`, `last_seen_at`, `profile_count`, or any custom company property you have sent to us | | `sort_dir` | optional | The sort direction. Use either `asc` (default) or `desc` | | `limit` | optional | Defaults to `50` with a maximum of `500` | | `offset` | optional | The number of matching companies to skip before returning results — used to page through filtered or sorted results (see the note below). Defaults to `0` | > *Note: Company filters support only the `property` and `group` filter kinds. The `event`, `tour`, and `survey` kinds available for [profile search](/apis/profiles-search) are not supported for companies.* > *Note: When `filters` or `sort_by` is provided, results are paginated with an offset-based `cursor`. Pass the returned `offset` back on the next request to fetch the following page:* ```json theme={null} { "cursor": { "limit": 50, "offset": 50 } } ``` Without `filters` or `sort_by`, companies use the standard `before` / `after` [cursor pagination](/concepts/pagination) shown under [List Companies](#companies-index). #### Examples All of these examples are based directly on the full schema of [Segmentation Filter Expressions](/concepts/filters). Each example below is showing the value for the `filters` key in the JSON request body: ```json theme={null} { "filters": [ ... ] } ``` ##### Companies that have a specific uid Find the company with the `uid` of `123`: ```json theme={null} { "filters": [ { "kind": "property", "prop": "uid", "op": "eq", "value": "123" } ] } ``` ```bash theme={null} curl -H "X-Account-Secret: ACCOUNT_SECRET" \ -H "Content-Type: application/json" \ -X POST \ -d '{"filters":[{"kind":"property","prop":"uid","op":"eq","value":"123"}]}' \ https://api.chameleon.io/v3/analyze/companies ``` The following examples show the full JSON request body. ##### Companies matching multiple properties Find companies on the `enterprise` plan **or** with a lifetime value (`clv`) greater than `100000`, combining two property filters with `filters_op`: ```json theme={null} { "filters_op": "or", "filters": [ { "kind": "property", "prop": "plan", "op": "eq", "value": "enterprise" }, { "kind": "property", "prop": "clv", "op": "gt", "value": 100000 } ] } ``` ```bash theme={null} curl -H "X-Account-Secret: ACCOUNT_SECRET" \ -H "Content-Type: application/json" \ -X POST \ -d '{"filters_op":"or","filters":[{"kind":"property","prop":"plan","op":"eq","value":"enterprise"},{"kind":"property","prop":"clv","op":"gt","value":100000}]}' \ https://api.chameleon.io/v3/analyze/companies ``` ##### Companies sorted by profile count Return companies ordered by `profile_count`, highest first: ```json theme={null} { "sort_by": "profile_count", "sort_dir": "desc" } ``` ```bash theme={null} curl -H "X-Account-Secret: ACCOUNT_SECRET" \ -H "Content-Type: application/json" \ -X POST \ -d '{"sort_by":"profile_count","sort_dir":"desc"}' \ https://api.chameleon.io/v3/analyze/companies ``` ### Counting Companies Return the number of companies matching a set of filters, without fetching the companies themselves. #### HTTP Request ``` GET|POST https://api.chameleon.io/v3/analyze/companies/count ``` | param | - | description | | ------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `filters` | optional | The array of [Segmentation filter expressions](/concepts/filters) used to match companies. Only the `property` and `group` kinds are supported | | `filters_op` | optional | The operator to apply between each filter. Use either `or` or `and` (default) | Counting uses the same `filters` / `filters_op` as [Search Companies](#companies-search); `sort_by`, `sort_dir`, `limit`, and `offset` do not apply. #### HTTP Response ```json theme={null} { "count": 128 } ``` ## Delete a Company When deleting a company, the company record itself is deleted and company is removed from all profiles associated with it. The associated profiles can also be removed by passing `cascade=profiles` with the request. | param. | - | description | | ------ | -------- | -------------------------------------------------------------------- | | `id` | optional | The Chameleon ID of the [Company](/apis/companies) | | `uid` | optional | The Company identifier (typically the Database ID from your backend) | #### HTTP Request Either `id` or `uid` is required. ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/companies/:id ``` or ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/company?uid=:uid ``` #### HTTP Response The endpoint returns `id` of the Deletion record. The Deletion is an internal Chameleon record that can be referenced as proof of initiating this request. ```json theme={null} { "deletion": { "id": "5f3c4232c712de665632a6d5" } } ``` ### Deleting a company and all profiles associated with it Deleting a company and all profiles associated with it can be done by passing `cascade=profiles`: ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/companies/:id?cascade=profiles ``` or ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/company?uid=:uid&cascade=profiles ``` #### HTTP Response When cascade deletion is requested, the endpoint also returns deletion ids of all the profiles associated with the company under `deletions` key. ```json theme={null} { "deletion": { "id": "5f3c4232c712de665632a6d5" }, "deletions": [ { "id": "5f3c4232c712de665632a6d6" }, { "id": "5f3c4232c712de665632a6d7" }, { "id": "5f3c4232c712de665632a6d8" } ] } ``` # Deliveries Source: https://developers.chameleon.io/apis/deliveries Deliveries are used to directly trigger an Experience to one specific User. * In a simple case, the linked Experience will be triggered with the given options. * A time window (`from` / `until`) can be applied to only deliver after/before/in the specified time window. * Filters such as `once` and `use_segmentation` can fine-tune the triggering. > An Experience that is delivered to the User will show immediately and with higher priority than any other Automatic Experiences > but an Experience *may not* show due to the conditions added to the Delivery itself. > For example, when a Delivery uses segmentation (`use_segmentation`) and the segmentation does not match the > User at the time of the delivery, the Experience will not show and the Delivery is not attempted again. ## Schema | Property | Type | Description | | ------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `model_id` | ID | The Chameleon ID of Experience this Delivery will trigger. | | `model_kind` | string | The kind of Experience: One of `tour` or `survey` (Microsurvey) | | `profile_id` | ID | The Chameleon ID of the [User Profile](/apis/profiles#schema) | | `idempotency_key` | string | A key that is used to enforce server-side "at most once delivery" for the given `profile_id`. [Learn more ↓](/apis/deliveries#idempotency) | | `options` | mixed | Any content to be used in the Experience, accessible via merge tag. | | `from` | timestamp | The timestamp before which this Delivery will not run. | | `until` | timestamp | The timestamp after which this Delivery is no longer valid. | | `use_segmentation` | boolean | Whether or not to first apply the Segment to determine if the Experience will show to the user. (default `false`) | | `once` | boolean | Whether or not to check if the user has seen this Experience before. (default `false`) | | `skip_triggers` | boolean | Whether or not to bypass the triggers, elements and delays on the first step to "force" it to show right away. (default `true`) | | `skip_url_match` | boolean | Whether or not to bypass the first Step URL match to "force" it to show right away. (default `true`) | | `at` | timestamp | The timestamp of when this Delivery was triggered for the User. | | `at_href` | string | The page URL of where this Delivery was triggered for the User. | | `interaction_id` | ID | The Chameleon ID of [Interaction](/apis/tour-interactions) this Delivery triggered. | | `group_kind` | string | The triggering system/api: One of `link`, `api_js`, `launcher`, `experiment`, `campaign`, or `delivery` | ### Errors * When the Experience is not live (not currently published) (`409`) * When User Profile has too many pending Deliveries (`409`) * When the user has not been seen by Chameleon (`422`) * When the supplied dates (`from` and `until`) are out of order (`422`) * When the supplied dates (`from` and `until`) are not in compatible formats (`422`) | Code | description | | ----- | ------------------------------------------------------------------------------------------------------- | | `404` | A related model cannot be found (Tour, Microsurvey or Profile) | | `409` | The Experience is not live, please publish and retry | | `409` | The Experience has already been triggered (it can no longer be subsequently changed) | | `409` | Too many outstanding deliveries for this User Profile, use `delivery_ids_at_limit` with value of `drop` | | `422` | The dates cannot be used in their given values (use `iso8601` or similar format) | | `422` | The `delivery_ids_limit` is too small or too large | | `429` | Only one Delivery at a time can be created per User Profile | ### Limitations > **Once a Delivery is marked as triggered (when `at` has a timestamp value) the delivery can no-longer be updated.** **Pending Deliveries** (yet untriggered; with a `null` value for the `at` property) are limited to 3 total per User Profile. This limit can be changed: * Globally to enable certain Use cases (if you're on our Growth plan, [Contact us](https://app.chameleon.io/help)). * Per request, to limit to any number smaller than your global limit (defaults to `3`). A User Profile that already has 2 pending Deliveries requires a special parameter `delivery_ids_position` to instruct us where in the list to add this new Delivery. Use values of `first`, `last` or an integer array of indexes. If an error occurs for a "limit reached", either specify `delivery_ids_at_limit` with value of `drop` or first [list the Deliveries by User Profile](/apis/deliveries#deliveries-index) to determine which ones to remove. **Time based limits**: When using `from` and `until` the deliveries will be added to the list of pending deliveries and made available to the client-side JavaScript but will remain undelivered until the `from` time is reached or after the `until` time is been passed. **Managing Delivery lifecycle**: When delivering for multiple use cases or when using different versions of `from` and `until` you may need to implicitly manage the "current set of deliveries for a user". This can be done ***directly*** with the API for [Removing a Delivery ↓](/apis/deliveries#deliveries-destroy) OR ***indirectly*** with `delivery_ids_limit`, `delivery_ids_at_limit` and `delivery_ids_position`. Use `delivery_ids_limit=1` and `delivery_ids_at_limit=drop` to only keep **this Delivery** in the list. ### Idempotency An idempotency key is used to generate a **single delivery** when the delivering criteria might otherwise be met **multiple times**. This is different than the `once` parameter because the `idempotency_key` operates at the moment when the Delivery is being created, where the `once` is used when attempting the Delivery on the client-side. * `idempotency_key` only creates a delivery if the idempotency key has **never been used** before. * `once` only shows the Experience if it has **not been seen before**. In terms of use cases: * Create a Delivery when an Event is triggered (but only deliver the Experience once). * Create a Delivery when an account needs to be upgraded to a new plan (but only deliver the Experience once). * Create a Delivery when an account crosses a specific billing threshold (but only deliver the Experience once). * Create a Delivery when you want feedback on a very specific action they took (but only deliver this type of feedback once). ###### Picking a good `idempotency_key`: In many the use cases above simply repeat the `model_id` as the `idempotency_key`. In other cases you may want to deliver one of many in-product Microsurveys, but if you want the "first one" to be shown to your end-user you must pick a "campaign specific" idempotency key such as `"data-import-feedback-2029"` to only ask for one Microsurvey response for the campaign you're running to get feedback on your hypothetical "data import flow". *** ## List all Deliveries #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/deliveries ``` | param | - | type | description | | ------------ | -------- | --------- | --------------------------------------------------------------------------------------------------------------------------- | | `model_id` | optional | ID | The Chameleon ID of Experience to filter to | | `profile_id` | optional | ID | The Chameleon ID of User Profile to filter to | | `limit` | optional | integer | Defaults to `50` with a maximum of `500` | | `before` | optional | ID | Used when paginating, use directly from the `cursor` object from the previous response | | `before` | optional | timestamp | Read as "created `before`" and can be given as a timestamp to get only `limit` items that were created before this time | | `after` | optional | timestamp | Read as "created `after`" and can be given as a timestamp or ID to get only `limit` items that were created after this time | ```json theme={null} { "deliveries": [ { "model_kind": "survey", "model_id": "5f3c4232c712de665632a6d4", "profile_id": "5f3c4232c712de665632a6d6", "until": "2029-04-07T12:18:00Z", ... }, { "model_kind": "tour", "model_id": "5f3c4232c712de665632a6d5", "profile_id": "5f3c4232c712de665632a6d7", "from": "2029-02-03T12:18:00Z", "until": "2029-04-07T12:18:00Z", ... }, ... ] } ``` ## Create a Delivery #### HTTP Request ```http title="POST" theme={null} https://api.chameleon.io/v3/edit/deliveries ``` Mirrors to the options for [Showing an Experience via JavaScript](/js/show-tour#options) | param | - | type | description | | ----------------------- | ---------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `model_kind` | required | string | The kind of Experience this Delivery will trigger either `tour` or `survey` (Microsurvey) | | `model_id` | required | ID | The Chameleon ID of Experience this Delivery will trigger | | `profile_id` | optional\* | ID | The Chameleon ID of User Profile to target | | `uid` | optional\* | string | The User Profile Identifier (typically the Database ID from your backend -- same value passed to `chmln.identify`) | | `email` | optional\* | string | The email address of User Profile to target | | `idempotency_key` | optional | string | The key used to enforce server-side "at most once delivery" for the given user profile. | | `options` | optional | object | Any keys/values to be used in personalizing the Experience content (i.e. body text, button CTA url) | | `from` | optional | timestamp | The timestamp before which this Delivery will not run - don't trigger this Experience before this time. | | `until` | optional | timestamp | The timestamp after which this Delivery is no longer valid - don't trigger this Experience after this time. Default +infinity | | `until` | optional | string | The [time interval](/concepts/normalization#timestamps) after which this Delivery is no longer valid (i.e. `"+30d"` => 30 days from now, `"+62d"` => 62 days from now) | | `use_segmentation` | optional | boolean | Whether or not to first apply the Segment to determine if the Experience show to the user. (default `false`) | | `once` | optional | boolean | Whether or not to check if the user has seen this Experience before. (default `false`) | | `skip_triggers` | optional | boolean | Whether or not to bypass the triggers, elements and delays on the first step to "force" it to show right away. (default `true`) | | `skip_url_match` | optional | boolean | Whether or not to bypass the first Step URL match to "force" it to show right away. (default `true`) | | `delivery_ids_limit` | optional | integer | Used to control the number of items that end up in the array of delivery\_ids. Defaults to `3`. | | `delivery_ids_position` | optional | one of 'first', 'last', integer | Defaults to `first`. The value of `last` or a specific integer array index to insert at, are accepted. | | `delivery_ids_at_limit` | optional | one of 'error', 'drop' | Defaults to `error`. The value of `drop` is used to "pop" a delivery id off the end of the `delivery_ids` array after adding the current one. Note: when at the limit of pending deliveries, using `delivery_ids_position=last` + `delivery_ids_at_limit=drop` will cause an error. | > Required: One of `profile_id`, `uid` or `email` ```json theme={null} { "model_kind": "tour", "model_id": "5f3c4232c712de665632a6d5", "uid": "542213", "from": "2029-02-03", "until": "+45d", ... } ``` #### HTTP Response | Status code | - | description | | ----------- | - | ------------------------------------ | | `201` | - | Delivery was created | | `200` | - | idempotent Delivery already occurred | ```json theme={null} { "delivery": { "model_kind": "tour", "model_id": "5f3c4232c712de665632a6d5", "profile_id": "5f3c4232c712de665632a6d7", "from": "2029-02-03T00:00:00Z", "until": "2029-04-20T00:00:00Z", ... } } ``` ###### Request with data (in `options`) intended for **merge tags** in the Experience ```json theme={null} { "model_kind": "tour", "model_id": "5f3c4232c712de665632a6d5", "profile_id": "5f3c4232c712de665632a6d7", "options": { "title": "Upcoming changes to billing", "body": "Book a demo with your Account manager, Jessica to see our upcoming changes in action", "button1": { "text": "Book Demo", "url": "https://calendly.com/your-product/15min" }, ... } } ``` ## Update a Delivery > **Once a Delivery is marked as triggered (when `at` has a timestamp value) the delivery can no-longer be updated.** #### HTTP Request ```http title="PATCH" theme={null} https://api.chameleon.io/v3/edit/deliveries/:id ``` | param | - | description | | -------- | -------- | ----------------------------------------------------------------------------- | | `id` | required | The Chameleon ID of the Delivery | | \*others | optional | Any other params from [Create a Delivery](/apis/deliveries#deliveries-create) | ## Remove a Delivery Cancel a Delivery that has yet to happen > **Once a Delivery is marked as triggered (when `at` has a timestamp value) the delivery can no-longer be deleted.** #### HTTP Request ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/deliveries/:id ``` | param | - | description | | ----- | -------- | -------------------------------- | | `id` | required | The Chameleon ID of the Delivery | *** ## Troubleshooting Deliveries are used to directly trigger an Experience to one or to many users. On the next page-load, the linked Experience will be triggered with the given options. While this is generally true there are a few different conditions that must be met for the trigger to occur: * The user never loads any page * The `from` time has not be reached * The `until` time has passed * The Experience is not live * `use_segmentation=true` and the Audience does not currently match * `once=false` and the user has seen the Experience before * `skip_triggers=false` and the user never clicks/hovers on the configured Step triggers * `skip_url_match=false` and the user never loads the matching URL # Product Demos Source: https://developers.chameleon.io/apis/demos A Product Demo is recorded with the Chameleon Chrome extension to show product features to prospects, introduce new features, explain complex workflows, and drive adoption. > [Demo Webhooks](/webhooks/outgoing#topics) are also available for key moments in the life of a Demo ## Using Demos with your CRM Chameleon can create new (and update existing) **Contact** and **Company** records in response to interactions with Demos. Completions of, and Tags of Demos will be stored as properties; the data schema is [below](#schema-crm). ### Contacts These are the moments when Chameleon will sync **Contact** data to your CRM: 1. When an anonymous user submits a form with their email address 2. When an [identified user](/js/demos#mode-profile) with an email address starts a Demo What will happen in the above situations? 1. A **Contact** is created or updated 2. `Chameleon Demos last seen time` is updated 3. The current Demo is added to `Chameleon Demos Seen` and the Tags (if any) are added to `Chameleon Demos Tags` 4. Any previous demos attached to the same `anonymous_id` will be added to the respective properties from \[3] ### Companies These are the moments when Chameleon will sync **Company** data to your CRM: 1. When [Clearbit reveal](https://app.chameleon.io/integrations/clearbit) is enabled, the Demo user has `consent_mode=granted` and a match is found What will happen in the above situation? 1. A **Company** is created or updated ## Integrations ### Hubspot integration 1. Visit the [Hubspot integration](https://app.chameleon.io/integrations/hubspot) page in the Chameleon dashboard 2. If you have not yet configured Hubspot, click "Connect" to initiate OAuth 3. Toggle on the "Create and Update objects in the CRM" option 4. Add an Email capture form or include a Product Demo in your product via another Chameleon experience ## CRM Schema ### Contacts | Name | Property | Type | Description | | ------------------------------------------ | ------------------------------------------ | --------------- | -------------------------------------------------------------------------------------------------------- | | `Chameleon Demos - All Demos Seen` | `chameleon_demos_seen__profile_v1` | Multiple select | A multi-checkbox of the Chameleon Demos that this Contact has seen | | `Chameleon Demos - Last updated at` | `chameleon_demos_last_updated__profile_v1` | Timestamp | The last time any Demo/Tag was added to this Contact | | `Chameleon Demos - Tags of All Demos Seen` | `chameleon_demos_tags__profile_v1` | Multiple select | A multi-checkbox of the Chameleon Tags that were attached to all of the Demos that this Contact has seen | ### Companies | Name | Property | Type | Description | | ------------------------------------------ | ------------------------------------------ | --------------- | ----------------------------------------------------------------------------------------------------------------------------- | | `Chameleon Demos - All Demos Seen` | `chameleon_demos_seen__company_v1` | Multiple select | A multi-checkbox of the Chameleon Demos that all of the Contacts have collectively seen | | `Chameleon Demos - Last updated at` | `chameleon_demos_last_updated__company_v1` | Timestamp | The last time any Demo/Tag was added to this Company | | `Chameleon Demos - Tags of All Demos Seen` | `chameleon_demos_tags__company_v1` | Multiple select | A multi-checkbox of the Chameleon Tags that were attached to all of the Demos that all of the Contacts have collectively seen | *** ## `Demo` Schema | Property | Type | Description | | ------------- | ---------- | ------------------------------------------------------------------ | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `description` | string | The display description | | `position` | string | The order that these appear in lists (starting from 0) | | `page_title` | string | The title of the page this Demo was recorded on | | `tag_ids` | array\ | The Chameleon IDs of the [Tags](/apis/tags) attached to this model | ## `DemoRun` Schema | Property | Type | Description | | --------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `consent_mode` | string | One of `pending`, `denied`, or `granted` | | `referrer` | string | The referrer of the page this Demo is embedded into | | `created_what` | string | The Browser name, version number and OS e.g. `Chrome 191.0 (Mac)` | | `created_where` | string | The city, region, country, country flag of the likely location of the user; *Only present for `consent_mode=granted`*. e.g. `Oakland CA, US 🇺🇸` | | `actions` | array\ | An array of the individual demo actions that occurred for this demo run | | `submissions` | array\<[DemoSubmission](/apis/demos#schema-demo-submission)> | An array of the form submissions that took place during this demo run | Additional `DemoRun` Schema when [Clearbit Reveal](https://clearbit.com/) 1. Add your API Key in [your dashboard](https://app.chameleon.io/integrations/clearbit) 2. Ensure `consent_mode` of the Demo is set to `granted` (e.g. `data-consent-mode="granted"` on the iframe element for the embed) 3. Chameleon will try to find a match based on the IP address of anonymous traffic | Property | Type | Description | | --------------- | ------ | ------------------------------------------------------- | | `clearbit_uid` | string | The ID of the matched company from Clearbit | | `reveal_domain` | string | The Company domain of the matched company from Clearbit | | `reveal_name` | string | The Company name of the matched company from Clearbit | ## `DemoSubmission` Schema | Property | Type | Description | | ------------ | ---------------------------------------------------------- | -------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `step_id` | string | The id of the DemoItem this submission came from | | `action_id` | string | The id of the item as found in [DemoRun](#schema-demo-run) `actions` | | `data` | array\<[DemoSubmissionData](#schema-demo-submission-data)> | | ## `DemoSubmissionData` Schema | Property | Type | Description | | ------------ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `field` | object\<[DemoFormField](#schema-demo-form-field)> | | | `value` | string/array/number/timestamp | The inputted value from the user as the real data type. Array for field `type=select`, timestamp for `datetime-local` etc. | ## `DemoFormField` Schema | Property | Type | Description | | ------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `type` | string | The input/field type of this field. One of `text`, `email`, `select`, `checkbox`, `radio`, `datetime-local`, `number`, `tel`, `url`, or `button` | | `name` | string | The display label of the field | | `description` | string | The display description of the field | # Elements Source: https://developers.chameleon.io/apis/elements Elements define which HTML element an experience will be anchored to, positioned next to, triggered from, or dismissed when clicked. Elements are the bridge between Chameleon Experiences and your product's UI. They describe **how to find a specific HTML element** on the page using a combination of CSS selectors, attributes, and DOM path information. Elements are used by: * **[Steps](/apis/steps)** — to position tooltips relative to an element, trigger on element visibility, or listen for clicks/hovers. * **[Tours](/apis/tours)** — each step in a Tour can target one or more elements. * **[Tooltips](/apis/tooltips)** — always anchored to a specific element. * **[Buttons](/apis/buttons)** — can trigger a click on a target element. > Elements are managed automatically by the Chameleon Builder when you visually select elements in your product. The API provides read access to inspect element configurations. *** ## Schema | Property | Type | Description | | ---------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `selector` | string | The full CSS / JavaScript selector to this element | | `description` | string | A human-readable description of the selected element | | `use` | array\ | A list of the attributes of the element that are used to build `selector`. Any of: `selector`, `path`, `tag`, `text`, `attr_id`, `attr_class`, `attr_href`, `attr_title`, `attr_type`, `attr_name`, `arity`, `shadow_selector`, `path_index`, `attr_data`, `attr_aria_labelledby`, or `attr_aria_label`. If `selector` is included then the element will be selected ONLY by the `selector` | | `path` | string | A complete CSS Path from the body down to the element | | `tag` | string | The HTML tag name of the element (e.g., `div`, `a`, `button`). | | `text` | string | The visible text content of the element. | | `attr_id` | string | The value of the element's `id` attribute, if present. | | `attr_class` | string | The value(s) of the element's `class` attribute, typically space-separated. | | `attr_href` | string | The value of the `href` attribute (used in links, anchors, etc.). | | `attr_title` | string | The value of the `title` attribute, often used for tooltips. | | `attr_type` | string | The value of the `type` attribute (e.g., `text`, `password`, `button`). | | `attr_name` | string | The value of the `name` attribute, often used in form controls. | | `arity` | string | Represents the number of child nodes or arguments for the element. | | `shadow_selector` | string | A selector path inside a shadow DOM, if the element resides in one. | | `path_index` | string | Index-based representation of the element's location in the DOM hierarchy. | | `attr_data` | string | Custom `data-*` attribute value(s) associated with the element. | | `attr_aria_labelledby` | string | Value of the `aria-labelledby` attribute (points to element IDs). | | `attr_aria_label` | string | Value of the `aria-label` attribute, providing accessibility text. | #### Example element JSON ```json theme={null} { "id": "5f3c4232c712de665632a7e1", "created_at": "2029-04-07T12:18:00Z", "updated_at": "2029-04-07T12:18:00Z", "selector": "#onboarding-btn", "description": "Onboarding start button", "use": ["attr_id"], "path": "body > div.app > header > button#onboarding-btn", "tag": "button", "text": "Get Started", "attr_id": "onboarding-btn", "attr_class": "btn btn-primary", "attr_type": "button" } ``` ### How element selection works Chameleon uses the `use` array to determine which attributes to combine when building the runtime selector. This enables resilient element targeting even when your UI changes: * **`selector` only** — When `use` includes `selector`, the raw CSS/JS selector is used directly. Best for stable, unique selectors like `#my-button`. * **Combined attributes** — When `use` includes multiple attributes (e.g., `["tag", "text", "attr_class"]`), Chameleon combines them to build a more resilient selector that can tolerate minor DOM changes. * **Shadow DOM** — When your element is inside a Web Component's shadow DOM, the `shadow_selector` provides the path within the shadow root. *** ## Elements in context Elements appear as embedded objects within other resources. They are not listed or retrieved independently — instead, they are included when you retrieve a [Step](/apis/steps) or [Tour](/apis/tours) with the appropriate `expand` parameter. For example, a Step's `trigger_element` and `position_element` fields are Element objects: ```json theme={null} { "step": { "id": "5f3c4232c712de665632a8f1", "step_trigger": "element_match", "position_type": "snap_to_element", "trigger_element": { "id": "5f3c4232c712de665632a7e1", "selector": "#onboarding-btn", "tag": "button", "text": "Get Started", "use": ["attr_id"] }, "position_element": { "id": "5f3c4232c712de665632a7e2", "selector": ".dashboard-sidebar .nav-item:first-child", "tag": "li", "use": ["selector"] } } } ``` See [Steps](/apis/steps) for all element-related fields on a Step. # Embeddables Source: https://developers.chameleon.io/apis/embeddables Embeddables are persistent, in-app widgets that can be embedded directly into your product's UI. Unlike Tours that appear as overlays, Embeddables are rendered inline within your application. *** An Embeddable is displayed when: * **URL matching** - the page must match the configured URL conditions. * **Segmentation matches** - User is the right person (required but can be set to match All Users). * **Element targeting** - Embeddables are rendered relative to a specific element on the page. *To know more about Embeddables, visit our [product documentation](https://help.chameleon.io/en/collections/7829085-embeddables).* *** With the Chameleon API for Embeddables, you can: * List all the Embeddables that follow a specified set of parameters. * Retrieve a single Embeddable based on the `id`. * Update an Embeddable to change Environments or publish/unpublish it. ## Schema | Property | Type | Description | | ------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `archived_at` | timestamp | The time when this was archived | | `name` | string | The name given by an administrator of Chameleon | | `description` | string | The internal description for this Embeddable | | `style` | string | The display style of this Embeddable: One of `banner` or `card` | | `position` | number | The order that these appear in lists (starting from 0) | | `segment_ids` | array\ | The Chameleon IDs of the configured [Segments](/apis/segments#schema) | | `published_at` | timestamp | The time this was most recently published | | `tag_ids` | array\ | The Chameleon IDs of the [Tags](/apis/tags) attached to this model | | `rate_unlimit_at` | timestamp | This item is excluded from [Rate limiting](https://help.chameleon.io/en/articles/3513345-rate-limiting-experiences) | | `dashboard_url` | string | Direct link to this Embeddable in the Chameleon Dashboard | | `stats` | object | Aggregated statistics for this model (all-time) | | `stats.started_count` | number | Number of your end-users who saw this | | `stats.last_started_at` | timestamp | Most recent time any user saw this | | `stats.completed_count` | number | Number of your end-users who completed/finished this | | `stats.last_completed_at` | timestamp | Most recent time any user completed/finished this | | `stats.exited_count` | number | Number of your end-users who dismissed/exited this | | `stats.last_exited_at` | timestamp | Most recent time any user dismissed/exited this | ## List Embeddables List all the Embeddables that follow a specified set of parameters. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/embeds ``` | param | - | description | | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | | `limit` | optional | Defaults to `50` with a maximum of `500` | | `before` | optional | Used when paginating, use directly from the `cursor` object from the previous response | | `before` | optional | Read as "created `before`" and can be given as a timestamp to get only `limit` items that were created before this time | | `after` | optional | Read as "created `after`" and can be given as a timestamp or ID to get only `limit` items that were created after this time | #### HTTP Response ```json theme={null} { "embeds": [ { "id": "5f3c4232c712de665632a6d5", "name": "Feature Announcement Banner", "style": "banner", "position": 1, "published_at": "2029-04-07T12:18:00Z", ... }, { "id": "5f3c4232c712de665632a2a1", "name": "Upgrade Prompt Card", "style": "card", "position": 0, "published_at": "2029-04-07T12:38:00Z", ... }, ... ], "cursor": { "limit": 50, "before": "5f3c4232c712de665632a2a1" } } ``` ## Retrieve an Embeddable Retrieve a single Embeddable. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/embeds/:id ``` | param | - | description | | ----- | -------- | -------------------------- | | `id` | required | An Embeddable ID to lookup | ```json theme={null} { "embed": { "id": "5f3c4232c712de665632a2a1", "name": "Feature Announcement Banner", "style": "banner", "position": 0, "published_at": "2029-04-07T12:38:00Z", ... } } ``` ## Update an Embeddable Update a single Embeddable to change its properties or to Publish it. #### HTTP Request ```http title="PATCH" theme={null} https://api.chameleon.io/v3/edit/embeds/:id ``` | param | - | description | | -------------- | -------- | ------------------------------------------------------------------------------------------ | | `id` | required | An Embeddable ID to update | | `url_group_id` | optional | An [Environments](/apis/urls) ID prefixed with `+` to add or `-` to remove the Environment | | `tag_id` | optional | A [Tag](/apis/tags) ID prefixed with `+` to add or `-` to remove the Tag | | `published_at` | optional | The published time of this Embeddable (set to now to trigger a publish) | To **Publish** the Embeddable send the current timestamp in `iso8601` format ```json theme={null} { "published_at": "2029-04-07T12:18:00Z" } ``` To **Unpublish** the Embeddable set the `published_at` to `null` ```json theme={null} { "published_at": null } ``` To **add** the `5e3c4232c712de666d55632a` Environment use a `+` prefix ```json theme={null} { "url_group_id": "+5e3c4232c712de666d55632a" } ``` To **remove** the `5e3c4232c712de666d55632a` Environment use a `-` prefix ```json theme={null} { "url_group_id": "-5e3c4232c712de666d55632a" } ``` ## Filtering by Segment See [Listing Related models](/apis/segments#segment-experiences-index) # Event Names Source: https://developers.chameleon.io/apis/event-names Event Names represent the tracked and custom events in your Chameleon account. Use the Event Names API to list and retrieve your configured events. Event Names represent the events that Chameleon tracks for your account. These include events sent via the [JavaScript API](/js/events) (e.g. `chmln.track('Signed up')`) and events forwarded from integrations like Segment. Events can be used in [Segmentation Filters](/concepts/filters) to target users who have (or haven't) performed specific actions. *** With the Chameleon API for Event Names, you can: * Retrieve a list of all Event Names in your account. * Retrieve a single Event Name by its `id`. * See which events are published (actively tracked) vs. unpublished. ## Schema | Property | Type | Description | | ----------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The display name given by an administrator of Chameleon | | `description` | string | A description of the event | | `uid` | string | The normalized identifier for the event (e.g. `chmln.track('Signed up')` becomes `signed_up`). See [Normalization](/concepts/normalization#events) | | `kind` | enum | The kind of event. One of `tracked` or `custom` | | `source` | enum | The source of the event. One of `api_js`, `api_v3`, `segment`, `freshpaint`, `heap`, `mixpanel`, `rudderstack`, or `amplitude` | | `published_at` | timestamp | When this event was set to be a Tracked event. `null` if not actively tracked | | `last_seen_at` | timestamp | When this event was last triggered by any user | | `filters` | array | Custom event property filters configured for this event | | `content_summary` | string | A summary of the event | | `dashboard_url` | string | A link to the Event Name in the Chameleon Dashboard | *** ## Listing Event Names Retrieve a list of Event Names for your account. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/event_names ``` | param | - | description | | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | | `limit` | optional | Defaults to `50` with a maximum of `500` | | `before` | optional | Used when paginating, use directly from the `cursor` object from the previous response | | `before` | optional | Read as "created `before`" and can be given as a timestamp to get only `limit` items that were created before this time | | `after` | optional | Read as "created `after`" and can be given as a timestamp or ID to get only `limit` items that were created after this time | #### HTTP Response ```json theme={null} { "event_names": [ { "id": "5f3c4232c712de665632a6d5", "created_at": "2029-01-15T10:30:00Z", "updated_at": "2029-06-20T14:22:00Z", "name": "Signed up", "description": "User completed the signup flow", "uid": "signed_up", "kind": "tracked", "source": "api_js", "published_at": "2029-01-15T10:35:00Z", "last_seen_at": "2029-08-10T09:15:00Z", "filters": [], "content_summary": null, "dashboard_url": "https://app.chameleon.io/data/events/profile/5f3c4232c712de665632a6d5" }, { "id": "5f3c4232c712de665632a6d6", "created_at": "2029-02-01T08:00:00Z", "updated_at": null, "name": "Imported data", "description": null, "uid": "imported_data", "kind": "tracked", "source": "segment", "published_at": null, "last_seen_at": "2029-08-05T14:30:00Z", "filters": [], "content_summary": null, "dashboard_url": "https://app.chameleon.io/data/events/profile/5f3c4232c712de665632a6d6" }, ... ], "cursor": { "limit": 50, "before": "5f3c4232c712de665632a6d5" } } ``` *** ## Showing an Event Name Retrieve a single Event Name. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/event_names/:id ``` | param | - | description | | ----- | -------- | -------------------------- | | `id` | required | An Event Name ID to lookup | #### HTTP Response ```json theme={null} { "event_name": { "id": "5f3c4232c712de665632a6d5", "created_at": "2029-01-15T10:30:00Z", "updated_at": "2029-06-20T14:22:00Z", "name": "Signed up", "description": "User completed the signup flow", "uid": "signed_up", "kind": "tracked", "source": "api_js", "published_at": "2029-01-15T10:35:00Z", "last_seen_at": "2029-08-10T09:15:00Z", "filters": [], "content_summary": null, "dashboard_url": "https://app.chameleon.io/data/events/profile/5f3c4232c712de665632a6d5" } } ``` # Data Imports Source: https://developers.chameleon.io/apis/imports Imports are used to add data to Chameleon via CSV. Each row should correspond with one record in the Chameleon database. You may import data into User Profiles or Companies with the model_kind property. You may Import data into a [User Profiles](/apis/profiles) or a [Company](/apis/companies) with the `model_kind` property. When using a CSV to create new records that are not yet in Chameleon, you must provide a mapping to the `uid` property, this is the same value you pass to `chmln.identify` via the [JS API](/js/profiles). Using a tagging `kind` (`tag_csv` or `tag_filters`) will either create a new User Tag or a new Company Tag and add all of the matching models to the new Tag. ## Schema | Property | Type | Description | | --------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `kind` | string | The kind of Import to be processed: One of `tag_csv`, `tag_filters`, `update_csv`, `delete_csv` or `delete_filters` | | `model_kind` | string | The target data collection to update: One of `profile` or `company`. Note that deleting companies is not currently supported. | | `tag_import_id` | ID | To add members to a previous Import, specify this as the ID of a previous Import | | `on_model_missing` | string | The strategy to use when data present in the Import is missing in Chameleon (i.e. [User Profile](/apis/profiles) or [Company](/apis/companies) has **not yet** been identified to Chameleon): One of `create` or `ignore` | | `head_columns` | array\ | A list representing the parsed version of the first 5 lines. Each object has a header column `name` and `values` are an ordered array of the next 4 rows for that column | | `import_at` | timestamp | The "trigger" to start the importing process (for convenience, use the string `$now`). At this point, the CSV upload is completed, all `properties` are confirmed, and the Import starts | | `properties` | array\ | The list of definitions of how to map CSV column headers to [Properties](/apis/properties) on the model. [example ↓](/apis/imports#examples-profiles-tag-all) | | `properties.$.name` | string | The column header of this property in the CSV file | | `properties.$.prop` | string | The `prop` value of the [Property](/apis/properties) to store on the model. New properties are created dynamically for missing `prop` values. | | `filters` | array\ | For filter-based imports, an array of items that each define a [Segmentation Filter expression](/concepts/filters) | | `segment_ids` | array\ | For `tag_filters` imports only, instead of `filters` you can also pass a combination of `segment_ids`, `segments_op`, `excluded_segment_ids`. These params will be used to build the filters behind the scenes. The `segment_ids` refers to *included* segments combined via `segments_op` | | `segment_op` | string | The operator to combine segments from `segment_ids`. One of `and` or `or` | | `excluded_segment_ids` | array\ | IDs of excluded segments | | `stats` | object | The details of the data itself and of the last run of this Import | | `stats.data_size` | number | The number of bytes contained in the uploaded file | | `stats.rows_count` | number | The number of rows in the file | | `stats.last_row` | number | The row number of the most recent processed row (used for mid-import progress bar) | | `stats.last_import_state` | string | The current state of the import: One of `started`, `completed`, `retrying`, or `error` | | `stats.last_import_error` | string | A representation of the error the last import encountered | | `stats.last_import_at` | timestamp | The last time this import was run | | `stats.last_import_elapsed` | number | The total time (in seconds) that the import took. | | `stats.created_count` | number | The number of records created by this Import | | `stats.updated_count` | number | The number of records updated by this Import | *** ## Limitations * Imports must be less than 50MB (200MB on the Growth plan) \[1] * Imports must be less 20 columns (100 on the Growth plan) \[1] * Only 20 Imports total can be created (50 on the Growth plan) \[1] * Imports "Tags" can be reused with `tag_import_id`, reused imports do not count against this limit. * Once an Import is marked as triggered (when `import_at` has a timestamp value) the Import can no longer be updated. * Only one Import will be run concurrently (though many can be triggered at the same time) > \[1] Import limits can be increased on an Growth / Enterprise plan. [Contact us](https://app.chameleon.io/help) to talk about your use case. *** ## List all Imports #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/imports ``` ```json theme={null} { "imports": [ { "id": "5f3c4232c712de665632a6d9", "kind": "tag_csv", "name": "Feedback Request: Post-BETA1", "model_kind": "profile", "properties": [ { "name": "User ID", "prop": "uid" } ], "head_columns": [ { "name": "User ID", "values": ["5a1fe53", "621f8e7"] } ], "stats": { "rows_count": 142934, "last_row": 112000, "last_import_state": "started", "last_import_at": null }, ... }, ... ] } ``` ## Create an Import * Check out the [cURL Examples](/apis/imports#examples-all-curl) below to see this in action. #### HTTP Request ```http title="POST" theme={null} https://api.chameleon.io/v3/edit/imports ``` | param | - | type | description | | ------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `name` | optional | string | The name given to this Import, defaults to `'s Import - ` | | `kind` | optional | string | The kind of Import to be processed: One of `tag_csv`, `tag_filters`, `update_csv`, `delete_csv` or `delete_filters`. Defaults to `tag_csv` | | `model_kind` | optional | string | The target data collection to update: One of `profile` or `company`. Defaults to `profile` | | `tag_import_id` | optional | ID | To add members to a previous Import, specify this as the ID of a previous Import | | `on_model_missing` | optional | string | The strategy to use when data present in the Import is missing in Chameleon (i.e. a User Profile or Company has **not yet** been identified to Chameleon): One of `create` or `ignore`. Defaults to `create` | | `properties` | required | array\ | The list of definitions of how to map CSV column headers to [Properties](/apis/properties) on the model. | | `properties.$.name` | required | string | The column header of this property in the CSV file | | `properties.$.prop` | required | string | The `prop` value of the [Property](/apis/properties) to store on the model | | `file` | required | File | The CSV file to be imported | | `filters` | array\ | For filter-based imports, an array of items that each define a [Segmentation Filter expression](/concepts/filters) | | | `import_at` | optional | timestamp | The "trigger" to start the importing process. At this point, the CSV upload is completed, all `properties` are confirmed, and the import starts | > For CSV-based import `kind`, both valid `properties` and `file` are required before `import_at` can be set. ##### Errors (for both `create` and `update`) * When the Import has already been started (when `import_at` has a value). * When the `on_model_missing` is `create` and the `uid` property is not mapped in properties. * When any of the supplied `properties` are not found as Headers in the uploaded file. * When the `tag_import_id` refers to an import that has not been finished | Code | description | | ----- | ---------------------------------------------------------------------------------------------------------------------- | | `409` | Once an Import has been started it cannot be updated | | `409` | The number of Imports limit has been reached, see [limits ↑](/apis/imports#limits) for details | | `422` | The `kind`, `model_kind`, or `on_model_missing` have unrecognized values | | `422` | The `properties` contains a `name` that was not found as a header in the CSV | | `422` | The `on_model_missing` is `create` and the `uid` property is not mapped in properties. | | `422` | The `import_at` was sent before both `properties` and `file` was set | | `422` | The file is larger than the current limits [limits ↑](/apis/imports#limits) allow | | `422` | The file has more columns than the current limits [limits ↑](/apis/imports#limits) allow | | `422` | The `kind=tag_csv` + `model_kind=profile` and `properties` does not map to a `uid` or `email` | | `422` | The `kind=tag_csv` + `model_kind=company` and `properties` does not map to a `uid` | | `422` | The `tag_import_id` refers to an import that has not been finished (when `stats.last_import_state` is not `completed`) | ##### Errors during Import * When an error occurs during the Import, the `stats.last_import_state` will change to `retrying` or `error` and `stats.last_import_error` will have a value. ##### Using `kind=tag_csv` to tag User Profiles via a User ID > This will be the same User ID you send to Chameleon when calling `chmln.identify` => [Identifying Users](/js/profiles). With a CSV `file` like this, specify the header of `User ID` as mapping to the Chameleon User Profile field of `uid`. ```text theme={null} User ID 5a1fe53 621f8e7 ``` Request: ```json theme={null} { "kind": "tag_csv", "name": "Feedback Request: Post-BETA1", "model_kind": "profile", "properties": [ { "name": "User ID", "prop": "uid" } ], ... } ``` Response: ```json theme={null} { "import": { ... "head_columns":[ { "name": "User ID", "values": ["5a1fe53", "621f8e7"] } ] } } ``` ##### Using `kind=tag_csv` to tag User Profiles with Email With a CSV `file` like this, specify the header of `Email address` as mapping to the Chameleon User Profile field of `email`. > You must set `on_model_missing` to `ignore` because no field maps to the `uid` Property. ```text theme={null} Email address jill@sample.com aaron@example.com ``` Request: ```json theme={null} { "kind": "tag_csv", "name": "Feedback Request: Post-BETA2", "on_model_missing": "ignore", "properties": [ { "name": "Email address", "prop": "email" } ], ... } ``` Response: ```json theme={null} { "import": { ... "head_columns": [ { "name":"Email address", "values": ["jill@sample.com", "aaron@example.com"] } ] } } ``` ##### Using `kind=tag_csv` to tag Companies via a Company ID > This will be the same Company ID you send to Chameleon when calling `chmln.identify` => [Identifying Company](/js/profiles#company). With a CSV `file` like this, specify the header of `Company ID` as mapping to the Chameleon Company field of `uid`. ```text theme={null} Company ID 721f8e8 6a1fe54 ``` Request: ```json theme={null} { "kind": "tag_csv", "name": "Company Feedback Request: Post-BETA1", "model_kind": "company", "properties": [ { "name": "Company ID", "prop": "uid" } ], ... } ``` Response: ```json theme={null} { "import": { ... "head_columns": [ { "name": "Company ID", "values": ["721f8e8", "6a1fe54"] } ] } } ``` ##### Using `kind=update_csv` to update User Profile data With a CSV `file` like this, use `properties` to specify the headers as mapped to the `prop` field of Chameleon [Property](/apis/properties). ```text theme={null} User ID,User Role,Role ICP Fit 5a1fe53,Customer Success Engineer,63 621f8e7,Customer Success Manager,88 ``` Request: ```json theme={null} { "kind": "tag_csv", "name": "Feedback Request: Post-BETA1", "model_kind": "profile", "properties": [ { "name": "User ID", "prop": "uid" }, { "name": "User Role", "prop": "role" }, { "name": "Role ICP Fit", "prop": "role_fit" } ], ... } ``` Response: ```json theme={null} { "import": { ... "head_columns": [ { "name": "User ID", "values": ["5a1fe53", "621f8e7"] }, { "name": "User Role", "values": ["Customer Success Engineer", "Customer Success Manager"] }, { "name": "Role ICP Fit", "values": [63, 68] } ] } } ``` ##### Using `kind=delete_csv` to delete User Profiles via a User ID > This will be the same User ID you send to Chameleon when calling `chmln.identify` => [Identifying Users](/js/profiles). With a CSV `file` like this, specify the header of `User ID` as mapping to the Chameleon User Profile field of `uid`. ```text theme={null} User ID 5a1fe53 621f8e7 ``` Request: ```json theme={null} { "kind": "delete_csv", "name": "Data deletion request 54Dw", "model_kind": "profile", "properties": [ { "name": "User ID", "prop": "uid" } ], ... } ``` Response: ```json theme={null} { "import": { ... "head_columns":[ { "name": "User ID", "values": ["5a1fe53", "621f8e7"] } ] } } ``` ##### Using `kind=delete_csv` to delete User Profiles with Email With a CSV `file` like this, specify the header of `Email address` as mapping to the Chameleon User Profile field of `email`. ```text theme={null} Email address jill@sample.com aaron@example.com ``` Request: ```json theme={null} { "kind": "delete_csv", "name": "Data deletion request 65fx", "on_model_missing": "ignore", "properties": [ { "name": "Email address", "prop": "email" } ], ... } ``` Response: ```json theme={null} { "import": { ... "head_columns": [ { "name":"Email address", "values": ["jill@sample.com", "aaron@example.com"] } ] } } ``` #### HTTP Response ```json theme={null} { "import": { "id": "5f3c4232c712de665632a6d9", "kind": "tag_csv", "name": "Feedback Request: Post-BETA1", "model_kind": "profile", "properties": [ { "name": "User ID", "prop": "uid" } ], ... } } ``` ## Show an Import Get information about the this Import which is typically used to track the Import's progress and to know when it finishes. Use `stats.rows_count` and `stats.last_row` to give a percentage complete. The Import is finished when `stats.last_import_state` is `completed`, at that point all other `stats` keys will have a relevant values. (i.e. `stats.last_import_at` and `stats.last_import_elapsed`). #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/imports/:id ``` | param | - | description | | ----- | -------- | ------------------------------ | | `id` | required | The Chameleon ID of the Import | #### HTTP Response ```json theme={null} { "import": { "id": "5f3c4232c712de665632a6d9", "kind": "tag_csv", "name": "Feedback Request: Post-BETA1", "model_kind": "profile", "properties": [...], "stats": { "rows_count": 142934, "last_row": 112000, "last_import_state": "started", "last_import_at": null, "created_count": 921, "updated_count": 111079 }, ... } } ``` ## Update an Import > The main reason to update an import is to "capture a workflow" or to separately upload the CSV file for convenience via `cURL`. > A workflow is typical of an Import UI but not typical of an API #### HTTP Request ```http title="PATCH" theme={null} https://api.chameleon.io/v3/edit/imports/:id ``` **See options for [Creating an Import](/apis/imports#imports-create)** *** ## Download the uploaded data Same endpoint as [show](/apis/imports#imports-show), but adds a `.csv` on the end. The response body is the CSV data. the `Content-Disposition` will be in this format => `attachment; filename="your original upload.csv"` #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/imports/:id.csv ``` | param | - | description | | ----- | -------- | ------------------------------ | | `id` | required | The Chameleon ID of the Import | ## cURL Examples To [Authenticate](/concepts/authentication), replace `ACCOUNT_SECRET` below with your secret token. This can be generated on your [dashboard](https://app.chameleon.io/integrations/tokens).
Tagging User Profiles by UID * `kind=tag_csv` + `model_kind=profile` means Tag Users Profiles by CSV. * Using `on_model_missing=create` means that any User Profile that is not found by UID will be added to Chameleon and Tagged with the Import `name`. With a CSV like this (`feedback-request-post-BETA1.csv`): ```text theme={null} User ID c4235f3 2de2c71 632665 ``` First, Create the import, naming it and mapping the `User ID` CSV header to the `uid` Chameleon property: ```bash theme={null} curl -X POST -H 'X-Account-Secret: ACCOUNT_SECRET' \ -H 'Content-Type: application/json' \ -d '{"name": "Feedback Request: Post-BETA1", "model_kind": "profile", "kind": "tag_csv", "on_model_missing": "create", "properties": [{"name":"User ID","prop":"uid"}] }' \ 'https://api.chameleon.io/v3/edit/imports' ``` Then Upload the CSV called `feedback-request-post-BETA1.csv` and trigger the import with `import_at=now` * Use the `import.id` from the last request in place of IMPORT\_ID: ```bash theme={null} curl -X PATCH -H 'X-Account-Secret: ACCOUNT_SECRET' \ -F file=@feedback-request-post-BETA1.csv \ 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID?import_at=now' ``` Optional: Check on the Import status: ```bash theme={null} curl -H 'X-Account-Secret: ACCOUNT_SECRET' 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID' ```
Tagging User Profiles by Email * `kind=tag_csv` + `model_kind=profile` means Tag Users Profiles by CSV. * Using `on_model_missing=create` means that any User Profile that is not found by UID will be added to Chameleon and Tagged with the Import `name`. With a CSV like this (`feedback-request-post-BETA1.csv`): ```text theme={null} Email address jill@example.co jess@product.io jamie@example.com ``` First, Create the import, naming it and mapping the `Email address` CSV header to the `email` Chameleon property: ```bash theme={null} curl -X POST -H 'X-Account-Secret: ACCOUNT_SECRET' \ -H 'Content-Type: application/json' \ -d '{"name": "Feedback Request: Post-BETA1", "model_kind": "profile", "kind": "tag_csv", "on_model_missing": "create", "properties": [{"name":"Email address","prop":"email"}] }' \ 'https://api.chameleon.io/v3/edit/imports' ``` Then Upload the CSV called `feedback-request-post-BETA1.csv` and trigger the import with `import_at=now` * Use the `import.id` from the last request in place of IMPORT\_ID: ```bash theme={null} curl -X PATCH -H 'X-Account-Secret: ACCOUNT_SECRET' \ -F file=@feedback-request-post-BETA1.csv \ 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID?import_at=now' ``` Optional: Check on the Import status: ```bash theme={null} curl -H 'X-Account-Secret: ACCOUNT_SECRET' 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID' ```
Tagging Companies by UID * `kind=tag_csv` + `model_kind=company` means Tag Companies by CSV. * Using `on_model_missing=create` means that any Companies that are not found by UID will be added to Chameleon and Tagged with the Import `name`. With a CSV like this (`feedback-request-accounts-post-BETA1.csv`): ```text theme={null} Company ID 5f3c423 2c712de 665632 ``` First, Create the import, naming it and mapping the `Company ID` CSV header to the `uid` Chameleon property: ```bash theme={null} curl -X POST -H 'X-Account-Secret: ACCOUNT_SECRET' \ -H 'Content-Type: application/json' \ -d '{"name": "Feedback Request Accounts: Post-BETA1", "model_kind": "company", "kind": "tag_csv", "on_model_missing": "create", "properties": [{"name":"Company ID","prop":"uid"}] }' \ 'https://api.chameleon.io/v3/edit/imports' ``` Then Upload the CSV called `feedback-request-accounts-post-BETA1.csv` and trigger the import with `import_at=now` * Use the `import.id` from the last request in place of IMPORT\_ID: ```bash theme={null} curl -X PATCH -H 'X-Account-Secret: ACCOUNT_SECRET' \ -F file=@feedback-request-accounts-post-BETA1.csv \ 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID?import_at=now' ``` Optional: Check on the Import status: ```bash theme={null} curl -H 'X-Account-Secret: ACCOUNT_SECRET' 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID' ```
Tagging User Profiles using Filters * `kind=tag_filters` + `model_kind=profile` means Tag Users Profiles matching the given Filters. ```bash theme={null} curl -X POST -H 'X-Account-Secret: ACCOUNT_SECRET' \ -H 'Content-Type: application/json' \ -d '{"name": "Gmail users", "model_kind": "profile", "kind": "tag_filters", "filters": [{"kind": "property", "prop": "email", "op": "in", "value": "gmail.com"}], "import_at": "$now"}' \ 'https://api.chameleon.io/v3/edit/imports' ``` Optional: Check on the Import status: ```bash theme={null} curl -H 'X-Account-Secret: ACCOUNT_SECRET' 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID' ```
Deleting User Profiles by UID * `kind=delete_csv` + `model_kind=profile` means Delete Users Profiles by CSV. With a CSV like this (`data-deletion-request-54Dw.csv`): ```text theme={null} User ID c4235f3 2de2c71 632665 ``` First, Create the import, naming it and mapping the `User ID` CSV header to the `uid` Chameleon property: ```bash theme={null} curl -X POST -H 'X-Account-Secret: ACCOUNT_SECRET' \ -H 'Content-Type: application/json' \ -d '{"name": "Data deletion request 54Dw", "model_kind": "profile", "kind": "delete_csv", "properties": [{"name":"User ID","prop":"uid"}] }' \ 'https://api.chameleon.io/v3/edit/imports' ``` Then Upload the CSV called `data-deletion-request-54Dw.csv` and trigger the import with `import_at=now` * Use the `import.id` from the last request in place of IMPORT\_ID: ```bash theme={null} curl -X PATCH -H 'X-Account-Secret: ACCOUNT_SECRET' \ -F file=@data-deletion-request-54Dw.csv \ 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID?import_at=now' ``` Optional: Check on the Import status: ```bash theme={null} curl -H 'X-Account-Secret: ACCOUNT_SECRET' 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID' ```
Deleting User Profiles by Email * `kind=delete_csv` + `model_kind=profile` means Delete Users Profiles by CSV. With a CSV like this (`data-deletion-request-54Dw.csv`): ```text theme={null} Email address jill@example.co jess@product.io jamie@example.com ``` First, Create the import, naming it and mapping the `Email address` CSV header to the `email` Chameleon property: ```bash theme={null} curl -X POST -H 'X-Account-Secret: ACCOUNT_SECRET' \ -H 'Content-Type: application/json' \ -d '{"name": "Data deletion request 54Dw", "model_kind": "profile", "kind": "delete_csv", "properties": [{"name":"Email address","prop":"email"}] }' \ 'https://api.chameleon.io/v3/edit/imports' ``` Then Upload the CSV called `data-deletion-request-54Dw.csv` and trigger the import with `import_at=now` * Use the `import.id` from the last request in place of IMPORT\_ID: ```bash theme={null} curl -X PATCH -H 'X-Account-Secret: ACCOUNT_SECRET' \ -F file=@data-deletion-request-54Dw.csv \ 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID?import_at=now' ``` Optional: Check on the Import status: ```bash theme={null} curl -H 'X-Account-Secret: ACCOUNT_SECRET' 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID' ```
Deleting User Profiles using Filters * `kind=delete_filters` + `model_kind=profile` means Delete Users Profiles matching the given Filters. ```bash theme={null} curl -X POST -H 'X-Account-Secret: ACCOUNT_SECRET' \ -H 'Content-Type: application/json' \ -d '{"name": "Remove users not seen in a year", "model_kind": "profile", "kind": "delete_filters", "filters": [{"kind": "property","prop":"last_seen_at","op":"lt-d","value":"365"}], "import_at": "$now"}' \ 'https://api.chameleon.io/v3/edit/imports' ``` Optional: Check on the Import status: ```bash theme={null} curl -H 'X-Account-Secret: ACCOUNT_SECRET' 'https://api.chameleon.io/v3/edit/imports/IMPORT_ID' ```
*** # Launchers Source: https://developers.chameleon.io/apis/launchers A Launcher is a collection of items shown in a menu to your end-users when they meet all of the predefined matching criteria * **The current page URL matches.** * **Segmentation matches (User is the right person) - required but can be to match All Users.** * **Launcher menu Icon or Custom Icon must be clicked.** *To know more about Launchers, feel free to visit our [product documentation](https://help.chameleon.io/en/articles/2730104-understanding-launchers).* *** With the Chameleon API for Launchers, you can: * List all Launchers based on the specified set of parameters. * Retrieve a specific Launcher based on its `id`. ## Schema | Property | Type | Description | | ---------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `title` | string | The display title | | `description` | string | The display description | | `preset` | string | The preconfigured type: One of `icon`, `element`, `icon_checklist`, `updates`, or `faqs` | | `segment_ids` | array\ | The Chameleon IDs of the configured [Segments](/apis/segments#schema) | | `published_at` | timestamp | The time this was most recently published | | `tag_ids` | array\ | The Chameleon IDs of the [Tags](/apis/tags) attached to this model | | `list_type` | string | If this is a checklist or a normal list: One of `default` or `checklist` | | `search_placeholder` | string | Search placeholder | | `quantifier_url` | string | This must match the current page URL *\[deprecated]* | | `quantifier_urls` | array | List of URL matching conditions that must match the current page URL | | `quantifier_urls.url` | none | The specific URL used in this matching condition | | `quantifier_urls.match_type` | none | The type of matching used. One of: `simple`, `exact`, `regex`, `inverse_simple`, or `inverse_exact` | | `trigger_text` | string | Trigger text | | `blocked_domains` | string | Domains that, if matched, will make this now show | | `empty_state_content` | string | Markdown content to show when all items in the Launcher are completed/hidden | | `icon_size` | string | Icon size | | `screen_position` | string | Screen position: One of `bottom_left` or `bottom_right` | | `position_type` | string | Position type: One of `relative_to_screen` or `snap_to_element` | | `trigger` | string | Trigger: One of `click` or `hover` | | `trigger_type` | string | Trigger type: One of `custom_icon`, `element`, `icon_lightbulb`, `icon_question`, `icon_checklist`, `icon_signpost`, `icon_bell`, or `text` | | `items` | array\ | An array of items that define the Launcher menu contents (see full schema below) | | `stats` | object | Aggregated statistics for this model (all-time) | | `stats.displayed_count` | number | Number of times the Launcher widget (icon) was shown to end-users | | `stats.last_displayed_at` | timestamp | Most recent time the Launcher widget (icon) was shown to end-users | | `stats.started_count` | number | Number of times the Launcher menu was opened by an end-user | | `stats.last_started_at` | timestamp | Most recent time the Launcher menu was opened by an end-user | ## Launcher Item Schema | Property | Type | Description | | ------------- | --------- | ------------------------------------------------------------------------------------------------------------------------ | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `kind` | string | The type of item this is: One of `url`, `tour`, `survey` (Microsurvey), `script`, or `divider` | | `title` | string | The display title in the Launcher menu | | `description` | string | The display description in the Launcher menu | | `segment_id` | ID | The Chameleon ID of the configured [Segment](/apis/segments#schema) | | `url` | string | The URL to link to when \`kind=url | | `campaign_id` | ID | The Chameleon ID of the [Tour](/apis/tours) or [Microsurvey](/apis/surveys) referenced when `kind=tour` or `kind=survey` | | `script` | string | The JavaScript code snippet to execute when this item is clicked by your end-user | | `hide` | boolean | Whether or not to remove this item from the list after clicked/completed | ## List Launchers List all Launchers based on the specified set of parameters. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/launchers ``` | param | - | description | | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | | `limit` | optional | Defaults to `50` with a maximum of `500` | | `before` | optional | Used when paginating, use directly from the `cursor` object from the previous response | | `before` | optional | Read as "created `before`" and can be given as a timestamp to get only `limit` items that were created before this time | | `after` | optional | Read as "created `after`" and can be given as a timestamp or ID to get only `limit` items that were created after this time | #### HTTP Response ```json theme={null} { "launchers": [ { "id": "5f3c4232c712de665632a6d5", "name": "Admin Onboarding checklist", "position": 1, "published_at": "2029-04-07T12:18:00Z", ... }, { "id": "5f3c4232c712de665632a2a1", "name": "Admin Self-serve menu", "position": 0, "published_at": "2029-04-07T12:38:00Z", ... }, ... ], "cursor": { "limit": 50, "before": "5f3c4232c712de665632a2a1" } } ``` ## Update a Launcher Update a single Launcher to change its properties or to Publish it. #### HTTP Request ```http title="PATCH" theme={null} https://api.chameleon.io/v3/edit/launchers/:id ``` | param | - | description | | -------------- | -------- | --------------------------------------------------------------------------------------------- | | `id` | required | A Launcher ID to update | | `url_group_id` | optional | An [Environments](/apis/urls) ID prefixed with `+` to add or or `-` to remove the Environment | | `tag_id` | optional | A [Tag](/apis/tags) ID prefixed with `+` to add or or `-` to remove the Tag | | `published_at` | optional | The published time of this Launcher (set to now to trigger a publish) | To **Publish** the Launcher send the current timestamp in `iso8601` format ```json theme={null} { "published_at": "2029-04-07T12:18:00Z" } ``` To **Unpublish** the Launcher set the `published_at` to `null` ```json theme={null} { "published_at": null } ``` To **add** the `5e3c4232c712de666d55632a` Environment use a `+` prefix ```json theme={null} { "url_group_id": "+5e3c4232c712de666d55632a" } ``` To **remove** the `5e3c4232c712de666d55632a` Environment use a `-` prefix ```json theme={null} { "url_group_id": "-5e3c4232c712de666d55632a" } ``` ## Filtering by Segment See [Listing Related models](/apis/segments#segment-experiences-index) ## Retrieve a Launcher Retrieve a single Launcher. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/launchers/:id ``` | param | - | description | | ----- | -------- | ----------------------- | | `id` | required | A Launcher ID to lookup | ```json theme={null} { "launcher": { "id": "5f3c4232c712de665632a2a1", "name": "Admin Self-serve menu", "position": 0, "published_at": "2029-04-07T12:38:00Z", ... } } ``` # Rate Limit Groups Source: https://developers.chameleon.io/apis/limit-groups Rate Limit Groups are used for Microsurveys and Tours to make sure no more than X Experiences per Y time period are shown to a user. An example of this are your "How do you find this Feature?" Microsurveys. You may want only want to show one per week to limit fatigue. Your Limit Group would have `rate_limit_size=1` and `rate_limit_kind=7d` then include all of the Microsurveys. > Rate Limit Groups can purposefully overlap and work together to form a cohesive Rate Limiting strategy, to learn more or to run your strategy by the Team, feel free to [Contact us](https://app.chameleon.io/help). *** At certain moments an experience can be exempt from a Rate Limit Group policy. These cases are all considered to be manually delivered: * Explicitly [toggling them off](https://app.chameleon.io/rate-limiting) to rate-unlimit it. * When [manually delivered](https://help.chameleon.io/en/articles/3406346-choosing-a-delivery-method) via Short Link * via [JavaScript API](/js/show-tour) * via [Deliveries API](/apis/deliveries) * When shown in a [Launcher](/apis/launchers) *** With the Chameleon API for Rate Limit Groups, you can: * Retrieve a list of Rate Limit Groups. * List all the related data that are connected to this Limit Group; Tours, Microsurveys and/or Tags ## Schema | Property | Type | Description | | ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `description` | string | The display description | | `kind` | string | The type of Rate Limit Group this represents: One of `all`, `tour`, `survey`, `tags`, or `campaigns` | | `rate_limit_size` | number | The total number of Experiences for the period of time specified by `rate_limit_kind` | | `rate_limit_kind` | string | The period of time to apply to this Rate Limit Group: One of `1h`, `2h`, `4h`, `1d`, `7d`, `30d`, `91d`, `182d` or `365d` | | `tag_ids` | array | The [Tags](/apis/tags) associated with this Rate Limit Group (only present when `kind=tags`) | | `campaign_ids` | array | The [Tours](/apis/tours) + [Microsurveys](/apis/surveys) associated with this Rate Limit Group (only present when `kind=campaigns`) | ##### Kinds of Rate Limit Groups (`kind` property) A Rate Limit Group creates a **dynamic** or **static** group of Experiences over which to apply the `rate_limit_size` number of Experiences in `rate_limit_kind` interval of time. | Kind | - | Description | | ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `all` | dynamic | All currently published [Tours](/apis/tours) + [Microsurveys](/apis/surveys) | | `tour` | dynamic | All published [Tours](/apis/tours) | | `survey` | dynamic | All published [Microsurveys](/apis/surveys) | | `tags` | dynamic | All published [Tours](/apis/tours) + [Microsurveys](/apis/surveys) with ***any*** of the specified [Tags](/apis/tags) in the `tag_ids` list | | `campaigns` | static | All published [Tours](/apis/tours) + [Microsurveys](/apis/surveys) ***explicitly*** in the `campaign_ids` list | ## Listing Limit Groups Retrieve a list of **all** Limit Groups. An account typically has 1-5 Limit Groups so this response should be relatively small. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/limit_groups ``` #### HTTP Response ```json theme={null} { "limit_groups": [ { "id": "5f3c4232c712de665632a6e2", "name": "1 Tour or Microsurvey every 2 hours (1 per session)", "kind": "all", "rate_limit_size": 1, "rate_limit_kind": "2h", ... }, { "id": "5f3c4232c712de665632a6d9", "name": "How is X Feature? (1 per week)", "kind": "tags", "tag_ids": [ "5f3c4232c712de665632a5d6", "5f3c4232c712de665632aa3a" ], "rate_limit_size": 1, "rate_limit_kind": "7d", ... }, { "id": "5f3c4232c712de665632a6e2", "name": "Product upsell opportunities (2 per month)", "kind": "campaigns", "campaign_ids": [ "5f3c4232c712de665632a6d5", "5f3c4232c712de665632a2a3" ], "rate_limit_size": 2, "rate_limit_kind": "30d", ... }, ... ] } ``` *** ## Showing a Limit Group Retrieve a single Limit Group. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/limit_groups/:id ``` | param | - | description | | ----- | -------- | -------------------------- | | `id` | required | A Limit Group ID to lookup | #### HTTP Response ```json theme={null} { "limit_group": { "id": "5f3c4232c712de665632a6e2", "name": "1 Tour or Microsurvey every 2 hours (1 per session)", "kind": "all", "rate_limit_size": 1, "rate_limit_kind": "2h", ... } } ``` *** ## Listing Related Experiences A Limit Group is attached to many Chameleon Experiences (Tours/Microsurveys). This endpoint allows you to get a complete picture of all Experiences currently attached to the Limit Group. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/limit_groups/:id/experiences ``` | param | - | description | | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------- | | `id` | required | A Limit Group ID to lookup | | `filter` | optional | Use `all` or `published_at` to include or exclude Experiences that are currently not published. Defaults to `published_at` | #### HTTP Response (Example with `kind=campaigns`) Note: this example Limit Group is based on `kind=campaigns` which means the Chameleon administrator ***explicitly picked these Experiences*** from a dropdown menu in the application. Keys returned: `limit_group`, `tours` and `surveys` ```json theme={null} { "limit_group": { "id": "5f3c4232c712de665632a6d9", "name": "How is X Feature? (1 per week)", "kind": "campaigns", "campaign_ids": [ "5f3c4232c712de665632a6d5", "5f3c4232c712de665632a2a3", "5f3c4232c712de665632a2a9" ], ... }, "tours": [ { "id": "5f3c4232c712de665632a2a9", "name": "Data was just imported v2", "position": 2, "published_at": null, ... } ], "surveys": [ { "id": "5f3c4232c712de665632a6d5", "name": "Task #2 completion CES", "position": 1, "published_at": "2029-04-07T12:18:00Z", ... }, { "id": "5f3c4232c712de665632a2a3", "name": "Admin account setup #1 completion question", "position": 0, "published_at": "2029-04-07T12:38:00Z", ... } ] } ``` #### HTTP Response (Example kind=tags) Note: this example Limit Group is based on `kind=tags` which means the Chameleon administrator ***explicitly picked a [set of Tags](/apis/tags)*** from a dropdown menu in the application. Keys returned: `limit_group`, `tags`, `tours` and `surveys` ```json theme={null} { "limit_group": { "id": "5f3c4232c712de665632a6d9", "name": "How is X Feature? (1 per week)", "kind": "tags", "tag_ids": [ "5f3c4232c712de665632a5f1", "5f3c4232c712de665632a5f2" ], ... }, "tags": [ { "id": "5f3c4232c712de665632a5f1", "uid": "new_feature", "name": "New Feature", "description": "Any feature announcement", "models_count": 9, "last_seen_at": "2029-04-07T12:18:00Z" }, { "id": "5f3c4232c712de665632a5f2", "uid": "ui_change", "name": "Interface Change", "description": "Any significant interface change to highlight", "models_count": 5, "last_seen_at": "2029-04-07T12:19:00Z" } ], "tours": [ { "id": "5f3c4232c712de665632a6d5", "name": "How hard was it to complete this task?", "position": 19, "published_at": "2029-04-07T12:18:00Z", "tag_ids": [ "5f3c4232c712de665632a5f2" ], ... }, ... ], "surveys": [ { "id": "5f3c4232c712de665632a2a3", "name": "Admin account setup #1 completion question", "position": 12, "published_at": "2029-04-07T12:38:00Z", "tag_ids": [ "5f3c4232c712de665632a190", "5f3c4232c712de665632a5f1" ] ... } ] } ``` # Overview Source: https://developers.chameleon.io/apis/overview Chameleon's REST API allows you to interact with information in Chameleon to integrate it with your own systems. It's meant to be flexible and adapt to your own use cases. Requests look like this: `curl -H "X-Account-Secret: ACCOUNT_SECRET" https://api.chameleon.io/...` -- see the pages below for more info * [Authentication](/concepts/authentication) * [Pagination](/concepts/pagination) * [Errors](/concepts/errors) * [Rate limiting](/concepts/rate-limiting) *** > Use `https://api.chameleon.io` for all requests to the Chameleon API. Currently, our REST API supports the following endpoints: | Model + details | List URL | Show URL | | ----------------------------------------------- | ------------------------------ | ---------------------------------- | | [User Profiles](/apis/profiles) | `GET /v3/analyze/profiles` | `GET v3/analyze/profiles/:id` | | [Companies](/apis/companies) | `GET /v3/analyze/companies` | `GET v3/analyze/companies/:id` | | [Segments](/apis/segments) | `GET /v3/edit/segments` | `GET /v3/edit/segments/:id` | | [Tours](/apis/tours) | `GET /v3/edit/tours` | `GET /v3/edit/tours/:id` | | [Tour Interactions](/apis/tour-interactions) | `GET /v3/analyze/interactions` | `GET /v3/analyze/interactions/:id` | | [Microsurveys](/apis/surveys) | `GET /v3/edit/surveys` | `GET /v3/edit/surveys/:id` | | [Microsurvey Responses](/apis/survey-responses) | `GET /v3/analyze/responses` | - | | [Experience Deliveries](/apis/deliveries) | `GET /v3/edit/deliveries` | `GET /v3/edit/delivery/:id` | | [Rate Limit Groups](/apis/limit-groups) | `GET /v3/edit/limit_groups` | `GET v3/edit/limit_groups/:id` | | [Alert Groups](/apis/alert-groups) | `GET /v3/edit/alert_groups` | `GET v3/edit/alert_groups/:id` | | [Launchers](/apis/launchers) | `GET /v3/edit/launchers` | `GET /v3/edit/launchers/:id` | | [Tooltips](/apis/tooltips) | `GET /v3/edit/tooltips` | `GET /v3/edit/tooltips/:id` | | [Webhooks](/apis/webhooks) | `GET /v3/edit/webhooks` | `GET v3/edit/webhooks/:id` | | [Domains](/apis/urls) | `GET /v3/edit/urls` | `GET /v3/edit/urls/:id` | | [Tags](/apis/tags) | `GET /v3/edit/tags` | `GET v3/edit/tags/:id` | | [Data Properties](/apis/properties) | `GET /v3/edit/properties` | `GET /v3/edit/properties/:id` | | [Data Imports](/apis/imports) | `GET /v3/edit/imports` | `GET /v3/edit/imports/:id` | ## Ideas for how you can use this API Chameleon's REST API is made to be adaptable to your own custom use cases. Nevertheless, there are some cases where you might want to use it: * **[Import data](/apis/imports)** (via CSV) on a one-time or recurring basis. * Register a **[Webhook](/apis/webhooks)** to receive realtime notifications of **[Microsurvey Responses](/apis/survey-responses)**. * Use the **[Microsurveys Endpoint](/apis/surveys)** to download **[Microsurvey Response](/apis/survey-responses)** data periodically. * Get a list of all the User data being sent to Chameleon and manipulate it (delete, update, etc.) through the **[User Profiles Endpoint](/apis/profiles)**. * Use an **[Alert Group](/apis/alert-groups)** to alert when Experiences aren't completed in a specific amount of time. * Monitor the Experiences assigned to your **[Rate Limit Groups](/apis/limit-groups)**. * Trigger an Experience via REST API that will run on next page load via **[Experience Deliveries](/apis/deliveries)**. > If there is any use case where you'd like to use our API but you're not sure how, feel free to [Contact us](https://app.chameleon.io/help). # User Profiles Source: https://developers.chameleon.io/apis/profiles User Profiles represent your product's end-users: real individuals who were identified to Chameleon. They can store complex (semi-arbitrary) properties about who they are. > For a full list of your User / Company Properties see the [Properties API](/apis/properties) *** The Chameleon User Profiles API allows you to: * Create / Update custom User properties * Retrieve a user by `id`, `uid` and `email`. * Search for users or get the count of users using any of the properties you have sent to us. * Clear or reset a specific user's data. * Delete a user permanently ## Schema #### Fully-expanded profile when listed directly or embedded with `expand` param specified properly | Property | Type | Description | | ------------------------- | ---------- | --------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `uid` | string | The external ID that came from your backend system | | `company_id` | ID | The Chameleon ID of the [Company](/apis/companies#schema) (only if associated) | | `browser_x` | number | Browser width in pixels | | `browser_tz` | number | Browser timezone in integer offset (+/-) from UTC | | `browser_l` | string | Language code as reported by the Accept-Language header | | `browser_n` | string | Browser name: One of `chrome`, `firefox`, `safari`, `opera`, `ie10`, `ie11`, or `edge` | | `browser_k` | string | Browser kind: One of `desktop` or `mobile` | | `percent` | number | Randomly assigned but stable, used for A/B testing | | `last_seen_at` | timestamp | When the user was las active on a page where Chameleon is installed | | `last_seen_session_count` | number | Number of sessions specified as a period of inactivity of `last_seen_at` of greater than 90 minutes | | `delivery_ids` | array\ | Ordered list of [Delivery](/apis/deliveries#schema) model IDs | | `company` | object | The expandable [Company](/apis/companies#schema) (only if associated) | | `*any options` | mixed | Any other options you have sent as Custom Properties will show up here too | #### Non-expanded profile when embedded in another (i.e. Microsurvey response) | Property | Type | Description | | ------------ | --------- | --------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `uid` | string | The external ID that came from your backend system | ## Create or Update a User See the [User Profiles Webhook](/webhooks/profiles) for sending User data to Chameleon ## Retrieve a specific User #### HTTP Request ``` GET|POST https://api.chameleon.io/v3/analyze/profiles/:id GET|POST https://api.chameleon.io/v3/analyze/profile # singular with parameters ``` | param | - | description | | ------- | -------- | -------------------------------------------------------------------------------- | | `id` | optional | The Chameleon ID of the User Profile | | `uid` | optional | The User Profile identifier (typically the Database ID from your backend) | | `email` | optional | If you have sent an email address, this will be available for single-user lookup | Only one of these parameters is required. Users matched are uniquely identified based on these keys (no two users have the same `uid` or `email`) When using a **GET** request with parameters: ``` ?id=5f3c4232c712de665632a6d5 ?uid=18821 ?email=leon@chmln.co ``` When using a **POST** request send one of these properties: ```json theme={null} { "id": "5f3c4232c712de665632a6d5", "uid": 18821, "email": "leon@chmln.co" } ``` #### HTTP Response ```json theme={null} { "profile": { "id": "5f3c4232c712de665632a6d5", "uid": 18821, "email": "leon@chmln.co", "first_name": "Leon", "role": "admin", "last_import_at": "2029-04-07T12:18:00Z", "invited_users_count": 4, ... } } ``` ## Clear or Reset a User Profile Clearing a profile consists of: * Resetting the properties such as browser width, last seen time, sessions count, etc.. * Removing Microsurvey responses. * Reverts summary data from any actions this user took (i.e. Tour Started counts decremented appropriately). * Removes and resets any Events that were tracked for this user. * A new `percent` is assigned and `last_cleared_at` is updated to `"$now"`. * A few other internal cleanup items. It is also possible to clear a user profile through the [Chameleon Dashboard](https://app.chameleon.io/testing) but is limited to profiles associated with the currently logged-in Chameleon Admin. To clear any profile on your account use this API. #### HTTP Request ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/profiles/:id ``` or ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/profiles?uid=:uid ``` | param | - | description | | ----- | -------- | ------------------------------------------------------------------------- | | `id` | optional | A Chameleon User Profile ID to lookup | | `uid` | optional | The User Profile Identifier (typically the Database ID from your backend) | #### HTTP Response ```json theme={null} { "profile": { "id": "5f3c4232c712de665632a6d5", "uid": 18821, "last_cleared_at": "2029-04-07T12:18:00Z", "browser_x": null, "last_seen_at": null, "percent": 12.231, ... } } ``` ## Delete a User Profile permanently The ability to delete a User Permanently is part of our effort to allow your users to opt-out of continued data storage by Chameleon and its partners. The key actions taken directly after deleting a User, is to remove Associated data before then removing the User profile data. Associated data includes records of Chameleon Experiences, Events logged and any other internal metrics associated with actions the user has taken. At the end of the process no record of this user exists in our database. Additionally, any data stored in backups relating to user profile data in our database has a retention of 3 months. #### HTTP Request ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/profiles/:id/forget ``` or ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/profiles/forget?uid=:uid ``` | param | - | description | | ------- | -------- | -------------------------------------------------------------------------------- | | id | optional | A Chameleon User Profile ID to remove | | uid | optional | The User Profile Identifier (typically the Database ID from your backend) | | `email` | optional | If you have sent an email address, this will be available for single-user lookup | #### HTTP Response The Deletion is an internal Chameleon record that can be referenced as proof of initiating this request. ```json theme={null} { "profile": { "id": "5f3c4232c712de665632a6d5", }, "deletion": { "id": "5f3c4232c712de665632a6d6", } } ``` ## Delete many User Profiles Please use [this gist](https://gist.github.com/bnorton/f8f3cf5ecf7fc72d0586ad1774ca7802) to delete users via a CSV! # Searching and Counting User Profiles Source: https://developers.chameleon.io/apis/profiles-search User Profiles represent your *product's end-users*: real individuals who were identified to Chameleon. *If you want to know more about User Profiles, visit the [User Profiles section](/apis/profiles).* *** Searching User Profiles through the Chameleon API allows you to: * Search for a user by `id`, `uid` and `email`. * Search for users or get the Count of Users by any of the properties you have sent to us. * Search for users by any of the interactions they had with Chameleon (answered a Microsurvey etc.). > *Note: [Rate Limiting](/concepts/rate-limiting) applies according to the table below.* | endpoint | Maximum concurrent requests | | ----------------- | --------------------------- | | `/profiles` | 2 | | `/profiles/count` | 1 | ## Schema See the full [User Profile schema](/apis/profiles#schema). ## Examples All of these examples are based directly on the full schema of [Segmentation Filter Expressions](/concepts/filters). > *Note: A fully-fledged version of these examples is implemented in the Chameleon Builder section for Segments.* Each example below is used as the value for the `filters` key in the JSON request body: ```json theme={null} { "filters": [ ... ] } ``` #### 1. User Profiles that Completed a Tour ```json theme={null} [ { "kind": "tour", "value": Chameleon Tour ID, "range": "completed" } ] ``` #### 2. User Profiles that exited a Tour within last 3 days `cond` - A secondary time-based filter operator. `int` - A secondary time-based filter # of days. ```json theme={null} [ { "kind": "tour", "value": Chameleon Tour ID, "range": "exited", "cond": "gt-d", "int": 3 } ] ``` #### 3. User Profiles that are an NPS promoter `mod` - A secondary matching condition for range. `range` - A secondary matching range (in this case, button index). > *Note: For a 11-button NPS, value `range` are 0,1,2,3,4,5,6,7,8,9,10.* ```json theme={null} [ { "kind": "survey", "value": Chameleon Microsurvey ID, "mod": "gte", "range": 9 } ] ``` #### 4. User Profiles that answered negatively to CES Microsurvey `mod` - A secondary matching condition for range. `range` - A secondary matching range (in this case, button index). > *Note: For a 5-button CES, value `range` are 0,1,2,3,4.* ```json theme={null} [ { "kind": "survey", "value": Chameleon Microsurvey ID, "mod": "lte", "range": 2 } ] ``` #### 5. User Profiles that were most recently active more than 7 days ago ```json theme={null} [ { "kind": "property", "prop": "last_seen_at", "op": "gt-d", "value": 7 } ] ``` #### 6. Admins `AND` are responsible for 3 or more user invites ```json theme={null} [ { "kind": "property", "prop": "role", "op": "eq", "value": "admin" }, { "kind": "property", "prop": "invited_users_count", "op": "gte", "value": 3 } ] ``` #### Full example using `filters_op=or`: Admins `OR` are responsible for 3 or more user invites Query for users where either role is admin OR invited 3 or more users ```json theme={null} { "filters_op": "or", "filters": [ { "kind": "property", "prop": "role", "op": "eq", "value": "admin" }, { "kind": "property", "prop": "invited_users_count", "op": "gte", "value": 3 } ] } ``` #### Full example using `filters_op=or` and filter Groups Query for users where either Admins AND are in a Non-North-American timezone ```json theme={null} { "filters": [ { "kind": "property", "prop": "role", "op": "eq", "value": "admin" }, { "kind": "group", "filters_op": "or", "filters": [ { "kind": "property", "prop": "browser_tz", "op": "gt", "value": -4 }, { "kind": "property", "prop": "browser_tz", "op": "lt", "value": -8 } ] } ] } ``` #### Full example using `filters_op=or` and filter Groups Query for users where either Admins AND are either com the Acme account or have an Acme email address. ```json theme={null} { "filters": [ { "kind": "property", "prop": "role", "op": "eq", "value": "admin" }, { "kind": "group", "filters_op": "or", "filters": [ { "kind": "property", "prop": "company.name", "op": "eq", "value": "Acme Inc." }, { "kind": "property", "prop": "email", "op": "in", "value": "@acme.co" } ] } ] } ``` ## Searching Users #### HTTP Request ``` GET|POST https://api.chameleon.io/v3/analyze/profiles (plural) ``` | param | - | description | | ---------------- | -------- | ---------------------------------------------------------------------------------------------------------- | | `segment_id` | optional | The Chameleon Segment ID from the [List of Segments](/apis/segments) | | `filters` | optional | The array of [Segmentation filter expressions](/concepts/filters) | | `filters_op` | optional | The operator to apply between each filter. Use either `or` or `and` (default) | | `expand` | optional | Object that specifies relationships to include/exclude. Supported keys are `profile` and `company` | | `expand.profile` | optional | use values of `all`, `min` to control the properties present in the `profile`. Defaults to `all` | | `expand.company` | optional | use values of `all`, `min` or `skip` to control the properties present in the `company`. Defaults to `min` | #### Using the `expand` parameter ``` # As a URL parameter expand[profile]=min&expand[company]=skip # In the Request body {"expand":{"profile":"min","company":"skip"}} ``` Notes: * A `profile` key will always be present with an object value. The `company` (embedded within `profile`) will be missing when the User Profile is not attached to a Company, otherwise it will be an object. #### Example: Segment ID ```json theme={null} { "segment_id": "5f3c4232c712de665632a6d7" } ``` #### Example: Segmentation filter expressions [See examples above](/apis/profiles-search#examples) #### HTTP Response ```json theme={null} { "profiles": [ { "id": "5f3c4232c712de665632a6d5", "uid": 18821, "email": "leon@chmln.co", "role": "admin", "invited_users_count": 4, ... }, { "id": "5f3c4232c712de665632a6d6", "uid": 18829, "email": "prehensile@chmln.co", "role": "admin", "invited_users_count": 6, ... } ] } ``` *** ## Counting Users #### HTTP Request ``` GET|POST https://api.chameleon.io/v3/analyze/profiles/count ``` **Use the same params / request body as [Searching Users](/apis/profiles-search#profiles-index)** #### HTTP Response ```json theme={null} { "count": 65121 } ``` # Properties Source: https://developers.chameleon.io/apis/properties Properties track the specific data sent to Chameleon via custom data properties to [User Profiles](/apis/profiles) or [Companies](/apis/companies). ## Schema | Property | Type | Description | | -------------- | --------- | ---------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `description` | string | The display description | | `kind` | string | Type of record this property is associated with: One of `profile`, `event`, or `company` | | `prop` | string | The normalized property key | | `integration` | string | The source integration of this property | | `last_seen_at` | timestamp | The time when this property was last added to / removed from a User Profile. | | `types` | array | The identified type of property values seen (string, integer etc.) | | `values` | array | A sample of the most recent values seen for this property (most recent first). | ## Listing Properties Retrieve a complete (un-paginated) list of properties for the given `kind` + `integration`. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/properties ``` | param | - | description | | ------------- | -------- | ------------------------------------------------------------------------------------------------------ | | `kind` | required | Use a values of either `profile` or `company` | | `integration` | optional | Used to filter properties to only ones created by a specific integration. Omit for "all integrations". | | `order` | optional | One of `created_at` or `last_seen_at`, ordered by most recent. Defaults to `created_at`. | Custom User Profile properties ```json theme={null} { "kind": "profile", "integration": "api", "order": "last_seen_at" } ``` Salesforce Company properties ```json theme={null} { "kind": "company", "integration": "salesforce" } ``` #### HTTP Response ```json theme={null} { "properties": [ { "id": "5f3c4232c712de665632a6d9", "name": "Monthly plan value (dollars USD)", "prop": "plan_cost", "types": ["integer"], "values": [678, 442, 1218, 239, 394], "last_seen_at": "2029-04-07T12:18:00Z" }, { "id": "5f3c4232c712de665632a6e2", "name": "Lifetime value", ... }, ... ] } ``` ## Create a Property #### HTTP Request ```http title="POST" theme={null} https://api.chameleon.io/v3/edit/properties ``` | param | - | type | description | | ------------- | -------- | ------ | ---------------------------------------------------------------------------------------- | | `name` | required | string | The name given by an administrator of Chameleon | | `description` | required | string | The display description | | `kind` | required | string | Type of record this property is associated with: One of `profile`, `event`, or `company` | ```json theme={null} { "name": "Next invoice date", "description": "The next time an Invoice will be generated by QBO", "kind": "company", ... } ``` #### HTTP Response ```json theme={null} { "property": { "id": "5f3c4232c712de665632a6d5", "created_at": "2029-02-03T00:00:00Z", "name": "Next invoice date", "description": "The next time an Invoice will be generated by QBO", "kind": "company", "prop": "next_invoice_date", ... } } ``` ## Update a Property #### HTTP Request ``` PUT|PATCH https://api.chameleon.io/v3/edit/properties/:id ``` | param | type | description | | ------------- | ------ | ----------------------------------------------- | | `id` | string | The ID of the Property | | `name` | string | The name given by an administrator of Chameleon | | `description` | string | The display description | ```json theme={null} { "description": "The next time an Invoice will be generated by Stripe", ... } ``` # HelpBar Source: https://developers.chameleon.io/apis/search Add a HelpBar to your product that allows your Users to search your Help center, Product, and any custom content for straightforward federated search. > **You have content within your product, even if you don't think of it that way. Any database records that your Users would want to find is a piece of content, akin to a Google search result. Send this content to Chameleon and we will surface it to your Users in the Chameleon HelpBar. The content can be scoped to a specific [Company](/apis/companies), be pinned to the top when the HelpBar is opened and can perform any action from clicking an item.**. *** See the specific APIs for more information on how to use Search your product. * [REST API](/apis/search#search-rest-api) * [JavaScript API](/apis/search#search-js-api) * [Limits](/apis/search#limits) #### To get HelpBar up and running, complete these items: 1. Create a [HelpBar](/apis/search#schema), configure it with `placeholder` etc. 2. Add your Help center as a [`SearchGroup`](/apis/search#schema-search-groups). 3. Add the top-level navigation within your product; First download this CSV [template](/apis/search#schema-search-imports) or [example](/apis/search#schema-search-imports) then [Import](/apis/search#schema-search-imports) it. 4. \[Optional] Add specific content from your database by creating a [SearchItem](/apis/search#schema-search-items) per database record you want to be searchable. 5. Publish your HelpBar by setting the `published_at` timestamp on the `Search`. 6. Visit your product where Chameleon is installed and hit `CMD` + `k` (or how you configured `key_meta` and `key_uid`). 7. Test a few search terms! *** ## HelpBar REST API With the Chameleon REST API for Search, you can: * Index custom content (the data from your product) into searchable [SearchItem](/apis/search#schema-search-items)s. * Import your product navigation to allow your Users to jump to a specific thing they are looking for with a [SearchImport](/apis/search#schema-search-imports). * Configure [SearchGroups](/apis/search#schema-search-groups) to pull content from public sources (i.e. your Help center, Blog etc.). * Define a [SearchLabelTheme](/apis/search#schema-search-label-themes) to label your [SearchItem](/apis/search#schema-search-items)s for greater visibility. * Add labels to the title or description of `SearchItem`s as [SearchLabel](/apis/search#schema-search-labels)s. ## `Search` bar Schema > `Search` is associated with `groups`: [SearchGroups](/apis/search#schema-search-groups), and `label_themes`: [SearchLabelThemes](/apis/search#schema-search-groups) | Property | Type | Description | | ----------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `placeholder` | string | The text used as the Search input placeholder | | `key_meta` | boolean | For the keyboard shortcut activation, is the CMD / CTRL key required to activate the HelpBar | | `key_uid` | string | For the keyboard shortcut activation, the letter to be used in combination with `key_meta` to activate the HelpBar bar | | `title_recent` | string | The label given to the group of "Recent items" | | `title_pinned` | string | The label given to the group of "Pinned items" | | `published_at` | timestamp | The time this was most recently published | | `style_color_background` | string | The background color of this HelpBar | | `style_color_text` | string | The font color of this HelpBar | | `style_item_color_highlight` | string | The hover color of the items of HelpBar | | `style_item_border_highlight` | string | The left-hand-side highlight color of the items of this HelpBar | | `url_group_ids` | array | The [`Environment`](/apis/urls#url-groups) that this is enabled to run on | | `published_updated_at` | timestamp | A copy of the Updated time (`updated_at`) when this was most recently published; used to track if an Experience is edited since last publish | | `published_user_id` | ID | The Chameleon ID of User who most recently published this | | `oids` | none | A set of pre-known IDs to directly add [SearchItem](/apis/search#schema-search-items)s to the default [SearchGroup](/apis/search#schema-search-groups)s | | `label_themes` | array | The array of `SearchLabelTheme` models | ## `SearchGroups` Schema | Property | Type | Description | | --------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `url` | string | The URL that this [SearchGroup](/apis/search#schema-search-groups) uses to fetch Search content | | `title` | string | The label given to this group in the HelpBar `Search` box | | `integration` | string | The backend search integration to search with (defaults to `bing`) | | `position` | number | The order that these appear in lists (starting from 0) | | `last_test_at` | timestamp | At the completion of a test of the configured URL, this value is set to the current timestamp. | | `icon` | object | The `SearchIcon` info to display for all results of this [SearchGroup](/apis/search#schema-search-groups) | | `icon.kind` | none | The "kind" of icon being used, one of `uid` or `image` | | `icon.uid` | none | When using `kind="uid"`, a specific Chameleon supplied svg-based icon \[2]. One of: `academic_cap`, `badge_check`, `beaker`, `bell`, `book_open`, `bulb`, `cake`, `calculator`, `calendar`, `chart_bar`, `chart_pie`, `chat_messages`, `chat_dots`, `chip`, `clipboard`, `clock`, `cloud_download`, `cloud`, `code`, `cog`, `color_swatch`, `connection`, `database`, `document_add`, `document_report`, `download`, `film`, `finger_print`, `fire`, `flag`, `folder`, `gift`, `globe`, `home`, `identification`, `key`, `leon`, `library`, `lightning_bolt`, `link`, `location_marker`, `map`, `microsurvey`, `music_note`, `paper_airplane`, `paper_clip`, `photograph`, `pop_out`, `presentation_chart`, `puzzle`, `qr_code`, `question_mark_circle`, `refresh`, `scale`, `search`, `segments`, `server`, `shield_check`, `sparkles`, `speakerphone`, `star`, `sun`, `support`, `table`, `tag`, `target`, `ticket`, `hammer`, `tooltip`, `signpost`, `truck`, `user_circle`, `user`, `users`, `variable`, `boards`, `grid`, `grid_add`, `list`, `warning`, `zoom_in`, `zoom_out`, `thumbs_up`, `thumbs_down`, `cube`, `company`, `click`, `hash`, or `toggle` | | `icon.image_url` | none | When using `kind="image"`, the url to an appropriate icon for this [SearchGroup](/apis/search#schema-search-groups) | | `icon.image_alt` | none | When using `kind="image"`, the alt text for the icon | | `url_options` | object | When configuring this [SearchGroup](/apis/search#schema-search-groups) for an Search integration, Chameleon will fetch some information about the given URL | | `url_options.integration` | none | The detected integration of the URL; (`intercom`, `zendesk`, `readme`, etc.) | | `url_options.title` | none | The title of the page loaded for URL | | `url_options.results_count` | none | The number of public search results for this URL (0-10) | ## `SearchPage` Schema | Property | Type | Description | | ----------------- | --------- | -------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `position` | number | The order that these appear in lists (starting from 0) | | `url_match_all` | boolean | Url match all | | `quantifier_urls` | array | List of URL matching conditions that must match the current page URL | ## `SearchLabelTheme` Schema > To reference a `LabelTheme` when adding `title_labels` or `description_labels` to `SearchItem`s, use the `id` field returned in the `label_themes` wen listing the `Search` with `GET /searches` or Creating with `POST /searches`. | Property | Type | Description | | ------------------------ | --------- | ------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `style` | string | The basic look of the label: One of: `outline` or `filled` | | `style_color_text` | string | The text color as a hex code of a `style=filled` label, the text and outline of a `style=outline` label | | `style_color_background` | string | The background color as a hex code, of a `style=filled` label | ## List all HelpBars There is only one per account. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/searches ``` #### HTTP Response ```json theme={null} { "searches": [ { "id": "6adae460426f060a00000000", "placeholder": "Search for help...", "key_meta": true, "key_uid": "k", ... } ] } ``` ## Create or Update your HelpBar There is only one per account so an update uses the same endpoint as create. Use any of the properties available in the [schema](/apis/search#schema) #### HTTP Request ```http title="POST" theme={null} https://api.chameleon.io/v3/edit/searches ``` ###### Examples With a basic config activating with `CMD` + `k` (or `CTRL` + `k`). ```json theme={null} { "placeholder": "Search for help...", "key_meta": true, "key_uid": "k", "title_recent": "Recently clicked", "title_pinned": "Pinned" } ``` Add two search groups of all help-center content on `help.your-product.com` and of all of your posts to your blog at `blog.your-product.com`. Help center content defaults to the `book_open` `icon` and `film` for the blog content. ```json theme={null} { "search_groups": [ { "title": "Help center", "url": "https://help.your-product.com", "integration": "bing", "icon": { "kind": "uid", "uid": "book_open" } }, { "title": "Best practices", "url": "https://blog.your-product.com", "integration": "bing", "icon": { "kind": "uid", "uid": "film" } } ] } ``` Add a theme for filled-red labels, and one for filled green labels. > To reference a `LabelTheme` when adding `title_labels` or `description_labels` to `SearchItem`s, use the `id` field returned with each theme. ```json theme={null} { "label_themes": [ { "style": "filled", "style_color_text": "FFF", "style_color_background": "FF6666" }, { "style": "filled", "style_color_text": "FFF", "style_color_background": "66FF66" } ] } ``` > After you configure/update your HelpBar must publish it! Publish by setting `published_at` to the current time. This makes your HelpBar available to your Users ```json theme={null} { "published_at": "2029-04-07T12:18:00Z" } ``` #### HTTP Response ```json theme={null} { "search": { "id": "5f3c4232c712de665632a6d9", "placeholder": "Search for help...", "key_meta": true, "key_uid": "k", "title_pinned": "Recommended", "title_recent": "Recent", "published_at": "2029-04-07T12:18:00Z", "label_themes": [ { "id": "6f3c4232c712de632a6d9656", "style": "filled", "style_color_text": "FFF", "style_color_background": "FF6666" }, { "id": "62c73c423f12de632a6d96fa", "style": "filled", "style_color_text": "FFF", "style_color_background": "66FF66" } ] } } ``` *** ## `SearchItem` Schema A search item is a discrete unit of searchable content akin to a Google search result. You have content within your product, even if you don't think of it that way. Any database records that your Users would want to find is a piece of content. Send us this content to surface it to your Users in the Chameleon HelpBar. > `SearchItem`s are associated with `actions`: [SearchActions](/apis/search#schema-search-actions), and `title_labels` / `description_labels`: [SearchLabels](/apis/search#schema-search-labels) | Property | Type | Description | | -------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `uid` | string | The external ID of the search content | | `title` | string | The display title | | `description` | string | The display description | | `pinned_at` | timestamp | Only `SearchItem`s with a timestamp here will show up in the "Pinned" / "Recommended" items search results group. | | `search_group_id` | string | The [SearchGroup](/apis/search#schema-search-groups) that this `SearchItem` will display in. | | `profile_ids` | array | The IDs of the [User Profile](/apis/profiles) that has access to this `SearchItem`. Only members these specific [User Profiles](/apis/profiles) will be displayed this `SearchItem` as a search result | | `company_ids` | array | The IDs of the [Company](/apis/companies) that has access to this `SearchItem`. Only members of this [Company](/apis/companies) will be displayed this `SearchItem` as a search result | | `segment_ids` | array | The IDs of the [Segment](/apis/segments) that has access to this `SearchItem`. Only current members of this [Segment](/apis/segments) will be displayed this `SearchItem` as a search result | | `company_uids` | array | The external ID (from in your database) for which Company has access to this `SearchItem`. Only members of this [Company](/apis/companies) will be displayed this `SearchItem` as a search result | | `profile_uids` | array | The external ID of the [User Profile](/apis/profiles) that has access to this `SearchItem`. Only members these specific [User Profiles](/apis/profiles) will be displayed this `SearchItem` as a search result | | `icon.kind` | string | The "kind" of icon being used, one of `uid` or `image` | | `icon.uid` | string | When using `kind="uid"`, a specific Chameleon supplied svg-based icon \[2]. One of: `academic_cap`, `badge_check`, `beaker`, `bell`, `book_open`, `bulb`, `cake`, `calculator`, `calendar`, `chart_bar`, `chart_pie`, `chat_messages`, `chat_dots`, `chip`, `clipboard`, `clock`, `cloud_download`, `cloud`, `code`, `cog`, `color_swatch`, `connection`, `database`, `document_add`, `document_report`, `download`, `film`, `finger_print`, `fire`, `flag`, `folder`, `gift`, `globe`, `home`, `identification`, `key`, `leon`, `library`, `lightning_bolt`, `link`, `location_marker`, `map`, `microsurvey`, `music_note`, `paper_airplane`, `paper_clip`, `photograph`, `pop_out`, `presentation_chart`, `puzzle`, `qr_code`, `question_mark_circle`, `refresh`, `scale`, `search`, `segments`, `server`, `shield_check`, `sparkles`, `speakerphone`, `star`, `sun`, `support`, `table`, `tag`, `target`, `ticket`, `hammer`, `tooltip`, `signpost`, `truck`, `user_circle`, `user`, `users`, `variable`, `boards`, `grid`, `grid_add`, `list`, `warning`, `zoom_in`, `zoom_out`, `thumbs_up`, `thumbs_down`, `cube`, `company`, `click`, `hash`, or `toggle` | | `icon.image_url` | sting | When using `kind="image"`, the url to an appropriate icon for this [SearchGroup](/apis/search#schema-search-groups) | | `icon.image_alt` | string | When using `kind="image"`, the alt text for the icon | | `actions` | array | An array of the [`SearchAction`](/apis/search#schema-search-actions) that run when this `SearchItem` is clicked/selected in the HelpBar | | `title_labels` | array | An array of the [`SearchLabel`](/apis/search#schema-search-labels) items displayed in the title of this `SearchItem` | | `description_labels` | array | An array of the [`SearchLabel`](/apis/search#schema-search-labels) items displayed under the description of this `SearchItem` | ## `SearchLabel` Schema | Property | Type | Description | | ----------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | string | The display text of the label | | `theme_uid` | string | The theme of this label, either the ID of a `SearchLabelTheme` configured on the `Search`, or a predefined theme: One of: `filled_green`, `filled_blue`, `filled_yellow`, `filled_red`, `outline_green`, `outline_blue`, `outline_yellow`, or `outline_red` | ## List all Search Items `SearchItem`s are for private content, and are added to Chameleon via CSV or directly via this REST API. They can be scoped on a per-company basis and there can be many thousands of custom search items, use the `cursor` to list as many as you need. > Note: this is how you iterate through all searchable content but it's not how your Users search for this content, if you want to query your data like and end-user, feel free to [Contact us](https://app.chameleon.io/help) to learn more. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/search_items ``` | param | - | description | | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | `limit` | optional | Defaults to `50` with a maximum of `500` | | `before` | optional | Used when paginating, use directly from the `cursor` object from the previous response | | `before` | optional | Read as "created `before`" and can be given as a timestamp to get only `limit` items that were created before this time | | `after` | optional | Read as "created `after`" and can be given as a timestamp or ID to get only `limit` items that were created after this time | | `search_import_id` | optional | Fetch only the `SearchItem`s that were created (or updated most recently) by the given [SearchImport](/apis/search#schema-search-imports). | #### HTTP Response ```json theme={null} { "search_items": [ { "id": "5f3c4232c712de665632a5f1", "title": "Data onboarding", "description": "The first step in making the switch is to import your first round of data.", ... }, ... 48 more { "id": "5f3c4232c712de665632a5a2", "title": "Invite your team", "description": "Enable the rest of your team to collaborate, close items in your boards and see your workflows.", ... } ], "cursor": { "limit": 50, "before": "5f3c4232c712de665632a5f2" } } ``` ## Create or Update your SearchItems Use any of the properties available in the [schema](/apis/search#schema-search-items). You must either send a `uid` field (as the unique identifier for a piece of content) OR the Chameleon ID in the url path. Using the POST-based endpoint below and sending the required `uid` acts as a "create or update" (upsert). When content relates to a specific database item, include the database ID of that record in the `uid` #### HTTP Request With the parameter of `uid`; this endpoint will "create or update" (upsert) your content: `POST` | \`\`\`http title="PATCH" [https://api.chameleon.io/v3/edit/search\_items](https://api.chameleon.io/v3/edit/search_items) ```` or ```http title="PATCH" https://api.chameleon.io/v3/edit/search_items/:id ```` ###### Examples Add a specific important action within your product for the Company in your DB with ID=14203, navigate to the onboarding page ```json theme={null} { "uid": "data-onboarding", "title": "Data onboarding", "description": "The first step in making the switch is to import your first round of data.", "company_uids": ["14203"], "actions": [ { "kind": "navigate", "url": "/data/import" } ] } ``` Upsell with a search result, directly book a demo with Calendly ```json theme={null} { "uid": "data-onboarding-book-demo", "title": "Data onboarding - see it in action", "description": "Book a demo with us to see the immediate value we can provide.", "actions": [ { "kind": "calendly", "calendly_url": "https://calendly.com/your-company/sales-team-data-demo" } ] } ``` Target content to a Chameleon [Segment](/apis/segments) of Users ```json theme={null} { "uid": "data-onboarding-admins-book-demo", "title": "Data onboarding - see it in action", "description": "Book a demo with us to see the immediate value we can provide.", "segment_ids": ["5f3c4232c712de665632a6d9"], "actions": [ { "kind": "calendly", "calendly_url": "https://calendly.com/your-company/sales-team-data-demo" } ] } ``` Target content to three Chameleon [Companies](/apis/companies) -- Only members of these companies will be able to search for this item. As parameters you can send either `company_uids` as the ID from **your database** or you can first lookup the Chameleon [Companies](/apis/companies#companies-show) and then send `company_ids` parameter. ```json theme={null} { "uid": "data-example-multi-company-book-demo", "title": "Data onboarding - see it in action", "description": "Book a demo with us to see the immediate value we can provide.", "company_uids": ["44621", "93821", "1265"], "actions": [ { "kind": "calendly", "calendly_url": "https://calendly.com/your-company/sales-team-data-demo" } ] } ``` Target content to a Chameleon [Company](/apis/companies) -- Only members of this Company will be able to search for this item. ```json theme={null} { "uid": "data-onboarding-admins-book-demo", "title": "Data onboarding - see it in action", "description": "Book a demo with us to see the immediate value we can provide.", "company_uids": ["93821"], "actions": [ { "kind": "calendly", "calendly_url": "https://calendly.com/your-company/sales-team-data-demo" } ] } ``` Target content to a Chameleon [User Profile](/apis/profiles) -- Only this specific User will be able to search for this item. ```json theme={null} { "uid": "data-onboarding-59324-book-demo", "title": "Data onboarding for {{first_name fallback='you'}} - see it in action", "description": "Book a demo with us to see the immediate value we can provide.", "profile_uids": ["59324"], "actions": [ { "kind": "calendly", "calendly_url": "https://calendly.com/your-company/sales-team-data-demo" } ] } ``` A hypothetical "car dealership" wants to make a used car searchable, track an event to all [configured Integrations](https://app.chameleon.io/integrations) and open the listing in a new tab. It also includes a title label of `NEW` themed with an [example theme](/apis/search#searches-create-http-response) from above. ```json theme={null} { "uid": "cars:28192", "title": "2029 just off lease!!!", "description": "Come check this one out today, nice inside and out, 105kW battery, 6400 miles.", "actions": [ { "kind": "event", "event_name": "Clicked Search => Car Listing" }, { "kind": "url", "url": "https://my.cars.com/listings/2029-04/car/28192", "url_blank": true } ], "title_labels": [ { "text": "NEW", "theme_uid": "62c73c423f12de632a6d96fa" } ] } ``` ## Batch Update your `SearchItem`s ```http title="POST" theme={null} https://api.chameleon.io/v3/edit/search_items/batch ``` | param | - | description | | --------- | -------- | ------------------------------------------------------------------------------------------------------- | | `ids` | required | An array of `SearchItem` IDs to update | | `*others` | optional | Use any of the properties available in the [single SearchItem update](/apis/search#search-items-create) | To update the icon of many items: ```json theme={null} { "ids": [ "6f3c42a6dd656232c712de63", "6f4c42a6d92f2c712d656e65", "6f5c42a6df232d656e2c7167" ], "icon": { "kind": "uid", "uid": "Puzzle" } } ``` To update the [SearchGroup](/apis/search#schema-search-groups) of many items: ```json theme={null} { "ids": [ "6f3c42a6dd656232c712de63", "6f4c42a6d92f2c712d656e65", "6f5c42a6df232d656e2c7167" ], "search_group_id": "5f3c4232c712de665632a6d9" } ``` ## Delete a `SearchItem`s Send the `uid` of a previously created `SearchItem`. #### HTTP Request ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/search_items ``` ## Bulk Delete a `SearchItem`s Send the `ids` of a previously created `SearchItem`. #### HTTP Request ```http title="DELETE" theme={null} https://api.chameleon.io/v3/edit/search_items/batch ``` ```json theme={null} { "ids": [ "6f3c42a6dd656232c712de63", "6f5c42a6df232d656e2c7167" ] } ``` ## `SearchAction` Schema A search action is one item in a collection of actions attached to a [SearchItem](/apis/search#schema-search-items)s. When the item is clicked the actions will be run in order (configure `kind=navigate` / `kind=url` last). Base schema | Property | Type | Description | | --------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `updated_at` | timestamp | The last time any property was updated | | `kind` | string | The kind of action to take: One of: `url`, `navigate`, `event`, `identify`, `tour`, `survey`, `script`, `function`, `airtable`, `calendly`, `chili_piper`, `figma`, `helpscout`, `hubspot_lists`, `intercom`, `link`, `livestorm`, `loom`, `pitch`, `typeform`, or `zendesk` | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `*others` | optional | Any other integration specific configuration (more info below in the specific schemas) | ### Integration specific schemas ## `SearchAction` with `kind=url` Schema | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "url" (required) | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `url` | `string` | The URL to use/open. Can be a full URL including https, or can be relative to the current page etc.) | | `url_blank` | `string` | If the URL opens in a new tab (defaults to `true`) | ```json theme={null} { "kind": "url", "url": "https://help.your-product.com/posts/339201-learn-more-about-it" } ``` ## `SearchAction` with `kind=navigate` Schema | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "navigate" (required) | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `url` | `string` | The URL to use/open. Can be a full URL including https, or can be relative to the current page etc.) | ```json theme={null} { "kind": "navigate", "url": "/cars/339201/edit" } ``` ## `SearchAction` with `kind=event` Schema Track an event to Chameleon and all of your [configured integrations](https://app.chameleon.io/integrations). | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "event" (required) | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `event_name` | `string` | The name of the Event to track to your configured integrations | ```json theme={null} { "kind": "event", "event_name": "Search action taken (custom)" } ``` ## `SearchAction` with `kind=identify` Schema Send user data to Chameleon and all of your [configured integrations](https://app.chameleon.io/integrations). | Property | Type | Description | | ---------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "identify" (required) | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `identify_key` | `string` | The specific key to set to your configured integrations | | `identify_value` | `string` | The specific value to set to your configured integrations | ```json theme={null} { "kind": "identify", "identify_key": "opted_in_for_product_research", "identify_value": "true" } ``` ## `SearchAction` with `kind=tour` Schema Show a Chameleon Tour immediately (calls `chmln.show` with the configured `tour_id`). Quickly access this ID in the URL on the [Chameleon dashboard](https://app.chameleon.io/tours). [JavaScript API reference](/js/show-tour) | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "tour" (required) | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `tour_id` | `string` | The ID of the published Chameleon Tour to trigger | ```json theme={null} { "kind": "tour", "tour_id": "6f7dfada300116393481bbbb" } ``` ## `SearchAction` with `kind=survey` Schema Show a Chameleon Microsurvey immediately (calls `chmln.show` with the configured `survey_id`). Quickly access this ID in the URL on the [Chameleon dashboard](https://app.chameleon.io/surveys). [JavaScript API reference](/js/show-tour) | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "survey" (required) | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `survey_id` | `string` | The ID of the published Chameleon Microsurvey to trigger | ```json theme={null} { "kind": "survey", "survey_id": "6d7dfad00116393ba481bb3c" } ``` ## `SearchAction` with `kind=script` Schema Run customized JavaScript when this item is clicked in the HelpBar. Check variables, user data, or page state before performing different actions. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "script" (required) | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `script` | `string` | The JavaScript string to evaluate | ```json theme={null} { "kind": "script", "script": "const pageStateDone = /#state=finished/.test(window.location.href);\nif(pageStateDone) { showFinishedModal() } else { showTodoModal() }" } ``` ## `SearchAction` with `kind=function` Schema After you have exposed a function on the `window` object within your application, call it when this item is clicked. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "function" (required) | | `helpbar_state` | string | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `fn` | `string` | The name of a function to call (without arguments (i.e. customChameleonFn\_032) | ```json theme={null} { "kind": "function", "fn": "showCustomModal_chameleonAction_19" } ``` ## `SearchAction` with `kind=airtable` Schema Show an Airtable form directly in your product. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "airtable" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use | ```json theme={null} { "kind": "airtable", "href": "https://airtable.com/1AyOshrwxGUPn" } ``` ## `SearchAction` with `kind=arcade` Schema Launch an Arcade Demo in a full screen modal | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "arcade" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use (Arcade Share URL) | ```json theme={null} { "kind": "arcade", "href": "https://app.arcade.software/share/E4EoapWRfxxeN3nX1rRe" } ``` ## `SearchAction` with `kind=calendly` Schema Show a Calendly scheduling modal directly in your product. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "calendly" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use | ```json theme={null} { "kind": "calendly", "href": "https://calendly.com/chameleon/demo" } ``` [Merge tags](/concepts/personalizing) are available for the `href` field; add the right Calendly link as [User data](/webhooks/profiles) and merge it in the action. (`csm` below refers to a customer success manager) ```json theme={null} { "kind": "calendly", "href": "{{calendly_csm_url}}" } ``` ## `SearchAction` with `kind=chili_piper` Schema Show a ChiliPiper scheduling modal directly in your product. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "chili\_piper" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `selected` | `string` | The type of Experience to enable. One of: `router` or `href` | | `router` | `string` | The ChiliPiper Router name associated with this calendar | | `href` | `string` | The URL to use | For a scheduling link ```json theme={null} { "kind": "chili_piper", "selected": "href", "href": "https://chameleon.na.chilipiper.com/book/queuey-queue" } ``` For a ChiliPiper router ```json theme={null} { "kind": "chili_piper", "selected": "router", "router": "csm-router" } ``` [Merge tags](/concepts/personalizing) are available for the `href` field; add the right Calendly link as [User data](/webhooks/profiles) and merge it in the action. (`csm` below refers to a customer success manager) ```json theme={null} { "kind": "chili_piper", "selected": "href", "href": "https://chameleon.na.chilipiper.com/book/{{chilipiper_csm_queue}}" } ``` ## `SearchAction` with `kind=embed` Schema Launch any embeddable page in a full screen modal. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "embed" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use (this URL needs to be a embeddable) | ```json theme={null} { "kind": "embed", "href": "https://content.acme.co/embeds/custom-widgets/23s2a" } ``` ## `SearchAction` with `kind=figma` Schema Show a Figma file or prototype directly in your product. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "figma" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use | ```json theme={null} { "kind": "figma", "href": "https://www.figma.com/file/QFEMdNRma0Y1WDcMRCw9Fz/Prototyping-in-Figma?node-id=0-1&t=YfflZMSK0tnWnCCu-0" } ``` ## `SearchAction` with `kind=google` Schema Show a Google Doc / Sheet / Form / Slides in a full screen modal. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "google" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use (this Google doc needs to be "Published to Web" to be embeddable) | ```json theme={null} { "kind": "google", "href": "https://docs.google.com/document/d/e/2PACX-1vQ7tXBCx-9gAlzHvROHNGC1_cklni0CmbBPHk/pub" } ``` ## `SearchAction` with `kind=helpscout` Schema | Property | Type | Description | | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "helpscout" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `helpscout_kind` | `string` | The type of HelpScout Experience to enable. One of: `open_chat`, `open_answers`, `search_term`, or `open_help_center` | | `query` | `string` | The search term to use for this action | | `article_url` | `string` | The specific URL / Help article to load | | `article_mode` | `string` | Where to display this article. One of: `null`, `menu`, or `new_tab` (defaults to `null` and opens in a HelpScout modal) | Open the `Beacon` to the default state ```json theme={null} { "kind": "helpscout", "helpscout_kind": "open_chat" } ``` Open HelpScout modal in your product to a specific article. ```json theme={null} { "kind": "helpscout", "helpscout_kind": "open_help_center", "article_url": "https://help.your-product.com/article/596-billing-and-plans-guide" } ``` Open the `Beacon` to a specific article. ```json theme={null} { "kind": "helpscout", "helpscout_kind": "open_help_center", "article_url": "https://help.your-product.com/article/596-billing-and-plans-guide", "article_mode": "menu" } ``` Open the `Beacon` to the answers tab ```json theme={null} { "kind": "helpscout", "helpscout_kind": "open_answers" } ``` Open the `Beacon` to a specific search query. Help users understand what is available in the help center ```json theme={null} { "kind": "helpscout", "helpscout_kind": "search_term", "query": "Import data" } ``` ## `SearchAction` with `kind=hubspot_lists` Schema | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "hubspot\_lists" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use | ```json theme={null} { "kind": "hubspot", "href": "https://meetings.hubspot.com/chameleon-sales/11-chat-30-minutes" } ``` ## `SearchAction` with `kind=intercom` Schema | Property | Type | Description | | --------------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "intercom" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `selected` | `string` | The type of Experience to enable. One of: `open_chat`, `search_term`, or `open_help_center` | | `message` | `string` | A pre-filled message to provide a hint of the proposed message to your team | | `search_term_article` | `string` | The search term to use for this action | | `specific_article` | `string` | The specific URL / Help article to load | | `article_mode` | `string` | Where to display this article | ```json theme={null} { "kind": "intercom", "selected": "open_chat" } ``` ```json theme={null} { "kind": "intercom", "selected": "open_help_center", "specific_article": "https://help.chameleon.io/en/collections/3572193-chameleon-101" } ``` ## `SearchAction` with `kind=livestorm` Schema Directly register a user for a webinar session; combine with a second action for `kind=url` that takes them to your "success" page. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "livestorm" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `session_uid` | `string` | The Livestorm Session ID copied from your Livestorm dashboard | | `utm_campaign` | `string` | The UTM Campaign parameter for this Livestorm Session registration | | `utm_source` | `string` | The UTM Source parameter for this Livestorm Session registration | | `utm_medium` | `string` | The UTM Medium parameter for this Livestorm Session registration | ```json theme={null} { "kind": "livestorm", "session_uid": "b820db33-3f2c-4159-a991-126fe03a7931", "utm_source": "chameleon_helpbar" } ``` ## `SearchAction` with `kind=loom` Schema Show a Loom video directly in your product. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "loom" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use | ```json theme={null} { "kind": "loom", "href": "https://www.loom.com/share/827d72cda9ed4724b30ba663f9ca00d3" } ``` ## `SearchAction` with `kind=navattic` Schema Launch an Navattic Demo in a full screen modal. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "navattic" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use | ```json theme={null} { "kind": "navattic", "href": "https://capture.navattic.com/cl4r18309ml5cngqz3e4fu84k" } ``` ## `SearchAction` with `kind=pitch` Schema Show a Pitch presentation directly in your product. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "pitch" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use | ```json theme={null} { "kind": "pitch", "href": "https://pitch.com/public/23e42e85-8142-4401-814e-509b597f06b0" } ``` ## `SearchAction` with `kind=typeform` Schema Show a Typeform survey directly in your product. | Property | Type | Description | | --------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "typeform" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `href` | `string` | The URL to use | | `mode` | `string` | The Typeform display mode for this survey. One of: `popup`, `drawer_left`, `drawer_right`, or `popover` | ```json theme={null} { "kind": "typeform", "href": "https://trychameleon.typeform.com/to/ahn7QkmE#source=developer_docs", "mode": "popup" } ``` ## `SearchAction` with `kind=zendesk` Schema | Property | Type | Description | | --------------------- | -------- | ------------------------------------------------------------------------------------------------------- | | `kind` | `string` | "zendesk" (required) | | `helpbar_state` | `string` | If the HelpBar stays open or closes when taking this action (optional defaults to null): One of: `open` | | `selected` | `string` | The type of Experience to enable. One of: `open_chat`, `search_term`, or `open_help_center` | | `search_term_article` | `string` | The search term to use for this action | | `specific_article` | `string` | The specific URL / Help article to load | Open the `window.zE` chat window ```json theme={null} { "kind": "zendesk", "selected": "open_chat" } ``` Search your Zendesk help center for the given search term ```json theme={null} { "kind": "zendesk", "selected": "search_term", "search_term_article": "Import data" } ``` *** ## Search JavaScript API At a high level, Chameleon uses the `chmln` object on the page via `chmln.on` to allow you to control the HelpBar experience. **All of these event listeners are optional**. See the [Type definitions below ↓](/apis/search#search-js-types) ##### Recommended ```javascript theme={null} chmln.on('app:navigate', (opts: NavigateOpts) => { /* Nagivate with React router / Vue router / pushState / call window.open / etc. Frameworks: - React info here => https://www.npmjs.com/package/@chamaeleonidae/chmln - Add more frameworks with a PR to this file and receive a $50 gift card opts.to is the `url` from the SearchAction; this SearchAction is configured with `kind=navigate` */ }); ``` ##### Optional ```javascript theme={null} chmln.on('helpbar:search:content', (opts: SearchOpts, ctx: Context) => { /* Optional for User generated content search: - Generally Chameleon will handle search for you - If you need to add custom "Search" logic use this event to pass back the right items, two options: - directly return an array; include and `id`, `title`, and `search_items` keys for each SearchGroup - return a Promise that will resolve with the first argument being an array. - Best used when you already use Algolia or have a custom search endpoint internally Called when: - The User has entered in a query; when a user enters text and pauses return array return Promise that resolves with the first argument as array return null (or don't implement) to use the search results as pulled from Chameleon opts.query is the search term queried for */ }); chmln.on('helpbar:search:external', (opts: SearchOpts, ctx: Context) => { /* Optional for Help center search: - Generally Chameleon will handle search for you - If you need to add custom "Help center search" logic use this event to pass back the right items, two options: - directly return an array; include and `id`, `title`, and `search_items` keys for each SearchGroup - return a Promise that will resolve with the first argument being an array. - Best used when you use a Help center that Chameleon does not integrate with Called when: - The User has entered in a query; when a user enters text and pauses return array return Promise that resolves with the first argument as array return null (or don't implement) to use the search results as pulled from Chameleon opts.query is the search term queried for */ }); chmln.on('helpbar:search:question', (opts: QuestionOpts, ctx: Context) => { /* Optional for AI answering - Generally Chameleon will handle AI answering for you - If you need to provide an answer from your own API or own model opts.query is the question opts.searchGroups the currently displayed groups + results opts.onAnswer a function to call when you have the partial or complete answer This is where you would make our network request and then call onAnswer when ready Example use of onAnswer When the endpoint returns the full answer - opts.onAnswer({ text: 'To start using the data import...' }); When the endpoint returns the full answer + reference material - opts.onAnswer({ text: 'To start using the data import...', links: [{ text: 'Data importing guide', href: 'https://help.acme.io/en/394821' }} }); When the endpoint steams the answer in character, token, word, or sentence call multiple times with each part received the onAnswer callback will concatenate these parts together as they come in - opts.onAnswer({ text: 'To star' }); - opts.onAnswer({ text: 't using the' }); - opts.onAnswer({ text: ' data import feature, first' }); */ }); chmln.on('helpbar:search:answer', (opts: AnswerOpts, ctx: Context) => { /* Optional for tracking AI Answering - Know when an answer is generated including the question and answer opts.query is the question opts.answer is the AI generated answer */ }); chmln.on('helpbar:opened', (opts: BlankOpts, ctx: Context) => { /* Optional: - This is purely informational but can be used for custom tracking etc. Called when: - The HelpBar is triggerd (opened by the User) ctx.source will tell you how it was opened */ }); chmln.on('helpbar:closed', (opts: BlankOpts, ctx: Context) => { /* Optional: - This is purely informational but can be used for custom tracking etc. Called when: - The HelpBar is closed by the User */ }); chmln.on('helpbar:items:recent', (opts: RecentOpts, ctx: Context) => { /* Optional: - Chameleon will handle recent items for you - If you need to add custom "Recent items" logic use this event to pass back the right items Called when: - the HelpBar needs a list of the most recent actions taken return Array or Promise of recent actions taken return null (or don't implement) to use the recent items as tracked by Chameleon opts.items is an array; the 4 most recent actions taken */ }); chmln.on('helpbar:items:pinned', (opts: BlankOpts, ctx: Context) => { /* Optional: - Chameleon will handle pinned items for you - If you need to add custom "Suggestion items" logic use this event to pass back the right items Called when: - the HelpBar needs a list of the pinned items return Array or Promise of pinned items to display return null (or don't implement) to use the pinned items as added to Chameleon backend via SearchItem */ }); chmln.on('helpbar:search:items', (opts: SearchItemsOpts, ctx: Context) => { /* Optional: - This is purely informational but can be used for custom tracking etc. Called when: - The Search query finished with 1 or more search results opts.query is the search term queried for opts.items an array of all search results for this query - opts.items.length will equal 0 when no results were returned */ }); chmln.on('helpbar:item:action', (opts: ActionOpts, ctx: Context) => { /* Optional: - Chameleon performs the configured actions automatically in the order they are defined in. - If you need to know when a specific "SearchItem" is clicked/triggered, use this event to know Called when: - When the SearchItem is clicked/triggered/selected and its actions are about to run opts.item is a SearchItem opts.item.actions is the array that will be run */ }); chmln.on('helpbar:item:action:error', (opts: ActionErrorOpts, ctx: Context) => { /* Optional: - Chameleon may encounter an error when triggering an action. Called when: - When an action encounters an error opts.item is a SearchItem opts.action is a SearchAction that errored */ }); ``` ### JS API type definitions
Type definitions for JS API ```typescript theme={null} // Describes the context of the User when they do a specific action type Context = { source: 'shortcut' | 'element' | 'js_api'; elapsed: number; }; // just a plan object with no properties type BlankOpts = { }; type SearchOpts = { query: string; }; type QuestionOpts = { query: string; groups: Array; onAnswer(opts: { text: string; links?: Array }): void; } type AnswerOpts = { query: string; answer: string; }; type SearchItemsOpts = { query: string; items: Array; }; type RecentOpts = { items: Array; }; // See SearchAction above for schema type ActionOpts = { item: SearchItem; }; type ActionErrorOpts = { item: SearchItem; action: SearchAction; }; type NavigateOpts = { to: string; }; type ReferenceItem = { href: string; text: string; } ```
## Limits > When these limits are exceeded, the endpoints will return a status code `409` with a descriptive error message please [Contact us](https://app.chameleon.io/help) with any questions. 1. Each `SearchItem` can be targeted to one or many `Company`, `Segment`, or `Profile`s. 1. An Free/Startup account is limited to 10 per `SearchItem` and in aggregate across all `SearchItem`s. 2. A Growth/Enterprise account is limited to 30 per `SearchItem` and in aggregate across all `SearchItem`s.. 2. Each `SearchGroup` can be targeted to one or many `Company` or `Segment`. 1. An Free/Startup account is limited to 10 in use across all `SearchGroup`s and in aggregate across all `SearchGroup`s. 2. A Growth/Enterprise account is limited to 30 in use across all `SearchGroup`s and in aggregate across all `SearchGroup`s. 3. Each HelpBar can have many groups (`SearchGroup`) and each can be targeted to one or many `Segment`s. 1. An Free/Startup account is limited to 20 `SearchGroup`s. 2. A Growth/Enterprise account is limited to 100 `SearchGroup`s. *** ## Search Item Importing via CSV (`SearchImport`) | Property | Type | Description | | --------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `file` | File | The file to import, please use the [template](https://chmln.co/helpbar-content-template) to make this easier. | | `filename` | string | The name of the original file uploaded | | `search_group_id` | string | The [SearchGroup](/apis/search#schema-search-groups) that all of the resulting `SearchItem`s will display in. (and/or this can be customized per row with "HelpBar Group ID" column) | | `head_columns` | array | A list representing the parsed version of the first 5 lines. Each object has a header column `name` and `values` are an ordered array of the next 4 rows for that column | | `stats` | object | The details of the data itself and of the last run of this [SearchImport](/apis/search#schema-search-imports). | | `stats.rows_count` | number | The number of rows in the file | | `stats.last_row` | number | The row number of the most recent processed row (used for mid-import progress bar) | | `stats.last_import_state` | string | The current state of the import | | `stats.last_import_error` | string | A representation of the error the last import encountered | | `stats.last_import_at` | timestamp | The last time this import was run | | `stats.last_import_elapsed` | number | The total time (in seconds) that the import took. | | `stats.created_count` | number | The number of records created by this Import | | `stats.updated_count` | number | The number of records updated by this Import | | `stats.deleted_count` | number | The number of records removed by this Import | ## Create a Search Import Use `Content-Type: multipart/form-data` to create an Import in one request, include the `file` parameter with a CSV based on the [template](https://chmln.co/helpbar-content-template). #### HTTP Request ```http title="POST" theme={null} https://api.chameleon.io/v3/edit/search_imports ``` ## Get a Search Import Useful to track the progress of this import. Small imports (\< 100 rows) will finish within approx 1 second. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/search_imports/:id ``` ## Trigger HelpBar This command triggers the display of the HelpBar. You can also use variations of this command with options to prefill a query or specify a custom placeholder, enhancing the user experience and engagement with the HelpBar. ``` chmln.show('helpbar') ``` This variation of the command allows for additional customization by accepting options. The `query` option enables the prefilling of a query within the HelpBar, serving as a starting point for user inquiries. Additionally, you can specify a custom placeholder using the `placeholder` option to provide users with a helpful prompt. ``` chmln.show('helpbar', options) ``` #### Options: * `query` (optional): Specifies a pre-filled query string to assist users in formulating their inquiries. If pre-filled as a question, it will also trigger the AI to generate an answer. * `placeholder` (optional): Sets a custom placeholder text within the HelpBar, guiding users on what they can search for or ask. #### Examples: * Prefill query ``` chmln.show('helpbar', { query: 'annual billing' }) ``` * When pre-filled as a question, this will trigger the AI to provide an asnwer. ``` chmln.show('helpbar', { query: 'What is a tour?' }) ``` * Specify placeholder text: ``` chmln.show('helpbar', { placeholder: 'Search for it...' }) ``` # Segments Source: https://developers.chameleon.io/apis/segments Segments are fundamental to targeting users within Chameleon. They are used for Microsurveys, Tours and Launchers to make sure the right users see the right content at the right moment. *** With the Chameleon API for Segments, you can: * Retrieve a list of segments according to the specified parameters. * Retrieve a single segment based on the `id`. * List all the Chameleon Experiences (Tours, Microsurveys, Launchers) that are connected to a defined segment. ## Schema | Property | Type | Description | | ------------ | --------------------- | ---------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `name` | string | The name given by an administrator of Chameleon | | `items` | array\ | An array of items that each define a [Segmentation Filter expression](/concepts/filters) | | `items_op` | enum | If each filter item is joined with logical `AND` or `OR`. One of `and` or `or` | > For a full list of your User / Company Properties see the [Properties API](/apis/properties) ## Listing Segments Retrieve a list of segments according to the specified parameters. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/segments ``` | param | - | description | | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | | `limit` | optional | Defaults to `50` with a maximum of `500` | | `before` | optional | Used when paginating, use directly from the `cursor` object from the previous response | | `before` | optional | Read as "created `before`" and can be given as a timestamp to get only `limit` items that were created before this time | | `after` | optional | Read as "created `after`" and can be given as a timestamp or ID to get only `limit` items that were created after this time | With a timestamp ```json theme={null} { "limit": 100, "before": "2029-04-07T12:18:00Z" } ``` From the previous response `cursor.before` ```json theme={null} { "limit": 500, "before": "5f3c4232c712de665632a6d7" } ``` #### HTTP Response ```json theme={null} { "segments": [ { "id": "5f3c4232c712de665632a6d9", "name": "Admins who invited > 3", "items": [ { "id": "5f3c4232c712de665632a6d8", "kind": "property", "prop": "role", "op": "eq", "value": "admin" }, { "id": "5f3c4232c712de665632a6d7", "kind": "property", "prop": "invited_users_count", "op": "gte", "value": 3 } ] }, { "id": "5f3c4232c712de665632a6e2", "name": "Grown Plan Upsell", ... }, ... ], "cursor": { "limit": 50, "before": "5f3c4232c712de665632a6d7" } } ``` *** ## Showing a Segment Retrieve a single Segment. #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/segments/:id ``` | param | - | description | | ----- | -------- | ---------------------- | | `id` | required | A Segment ID to lookup | #### HTTP Response ```json theme={null} { "segment": { "id": "5f3c4232c712de665632a6d7", "name": "Admins who invited > 3", "items": [ { "id": "5f3c4232c712de665632a6d8", "kind": "property", "prop": "role", "op": "eq", "value": "admin" }, { "id": "5f3c4232c712de665632a6d9", "kind": "property", "prop": "invited_users_count", "op": "gte", "value": 3 } ] } } ``` *** ## Listing Related Experiences A Segment can be configured to be attached to many Chameleon Experiences, including [Microsurveys](/apis/surveys), [Tours](/apis/tours) and [Launchers](/apis/launchers) and [Rate Limit Groups](/apis/limit-groups). This endpoint allows you to list any of these items that are currently attached to the Segment given with the ID #### HTTP Request ```http title="GET" theme={null} https://api.chameleon.io/v3/edit/segments/:id/:kind ``` | param | - | description | | ------ | -------- | ------------------------------------- | | `id` | required | A Segment ID to lookup | | `kind` | required | One of `tour`, `survey` or `launcher` | #### HTTP Response ```json theme={null} { "segment": { "id": "5f3c4232c712de665632a6d7", "name": "Admins", ... }, "tours": [ { "id": "5f3c4232c712de665632a6d5", "name": "Revamped Dashboard Launch", "style": "auto", "position": 4, "published_at": "2029-04-07T12:18:00Z", ... }, ], "cursor": { "limit": 50, "before": "5f3c4232c712de665632a2a1" } } ``` # Steps Source: https://developers.chameleon.io/apis/steps Steps are the building blocks of Tours, Microsurveys, and Embeddables. Each Step defines the content, positioning, triggers, and interactions for a single screen in an Experience. A Step represents a single screen within a multi-step Experience. Steps define: * **What** to show — title, body text, buttons, and input fields * **Where** to show it — positioned relative to the screen, snapped to an element, or rendered inline * **When** to show it — triggered on page load, element visibility, click, hover, or custom events *** ## Schema | Property | Type | Description | | ---------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `id` | ID | The Chameleon ID | | `created_at` | timestamp | When this happened or when this was added to the Database | | `updated_at` | timestamp | The last time any property was updated | | `title` | string | The configured title text for this Step | | `body` | string | The configured body copy for this Step | | `preset` | string | The template this step follows (see [Step presets](#step-presets) below) | | `dropdown_items` | array\ | For a dropdown Microsurvey Step, the configured options for the dropdown | | `follow_up_delay` | integer | Delay in milliseconds before follow-up actions are triggered | | `cta_has_custom_click` | boolean | Whether the CTA requires custom click handling | | `step_trigger` | string | Primary trigger condition. One of: `page_load`, `element_match`, or `element_not_match` | | `position_type` | string | How the step is positioned on the page. One of: `relative_to_screen`, `snap_to_element`, `snap_to_trigger`, or `inline` | | `step_additional_trigger` | string | Additional trigger condition. One of: `element_match` or `element_not_match` | | `secondary_trigger` | string | Secondary trigger condition. One of: `click`, `hover`, `time_on_page`, `smart_delay`, `input`, or `custom_trigger` | | `trigger_element` | [Element](/apis/elements) | Present if `step_trigger` is `element_match` or `element_not_match`. | | `trigger_additional_element` | [Element](/apis/elements) | Present if a `trigger_additional_element` has been selected in the UI. | | `trigger_secondary_element` | [Element](/apis/elements) | Present if `position_type` is `snap_to_trigger` OR if `secondary_trigger` is one of `click`, `hover`, `input`. | | `position_element` | [Element](/apis/elements) | Present if `position_type` is `snap_to_element` or `inline`. | | `exit_element` | [Element](/apis/elements) | Present if `cta_has_custom_click` is true. | | `buttons` | array\