Skip to main content

Data into Chameleon

These webhooks are a simple way to get data into Chameleon. Currently, our Incoming Webhooks API supports the following two advanced use cases:
  • To send data from your Backend into Chameleon for targeting with Segments.
  • To send data directly from our Integration partners. Some examples are Heap and Customer.io which both have the robust omni-webhook functionality to send Data directly into Chameleon.
Model + detailsURL
User ProfilesPOST /v3/observe/hooks/:account_secret/profiles
CompaniesPOST /v3/observe/hooks/:account_secret/companies
EventsPOST /v3/observe/hooks/:account_secret/events

Integration partners

Limits

  • Up to a total of 768 bytes are stored for each scalar value where each Array item and each Hash value can reach this limit.
  • See the full page on Limits for more information.
  • Any data received that exceeds this limit will be truncated at the 768th byte and a warning surfaced on the data management page for user data or for company data.

Normalization

  • Property names are normalized to lower case and underscored i.e. planName => plan_name.
  • See the full page on Normalization for more information.

Data out of Chameleon

A webhook is an agreed-upon method of data exchange across a secure channel. Since you will be adding a new endpoint to your backend servers to handle this webhook, is it strongly recommended that you verify the signature of any webhook requests before processing any included data. When sending a webhook to your backend Chameleon will:
  • Send a POST request to your https configured endpoints.
  • Attempt delivery right away from aws us-east, use a request timeout of 7 seconds and include a User-Agent header specific to the API version the webhook is being sent from.
  • Generate a SHA256-HMAC signature of the request body and include the signature in the X-Chameleon-Signature header
  • In case of non-200 status code, will retry a total of 9 times over 43 hours (giving you a chance to fix errors without losing track of these webhooks)
When receiving a webhook from Chameleon you should:
  • Only accept requests from Chameleon IP Addresses
  • Verify the Webhook request signature; respond with a status 400 if the signature does not match
  • Drop the request if the webhook is too old (to prevent replay attacks); respond with a status 400
  • Respond quickly with a 200 status code (or any 2xx status code)
  • Optional: Request any related data with the other APIs

Webhook topics

TopicExample PayloadIncluded modelsDescription
pingexampleAccountSent as a simple check to make sure the endpoint is working
response.finishedexampleResponse, Microsurvey, User ProfileSent when the Microsurvey is finished (all Steps completed; including text comment if configured)
alert.triggeredexampleAlert Group, ExperiencesSent when an Alert is triggered by a violation of the alerting conditions
helpbar.answerexampleAction, User ProfileSent when a Search query generates an AI Answer in HelpBar
helpbar.searchexampleAction, User ProfileSent when a Search query displays its results in the HelpBar
helpbar.item.actionexampleAction, User ProfileSent when an item in the HelpBar is clicked/actioned
helpbar.item.errorexampleAction, User ProfileSent when an action from an item in the HelpBar throws an error when running
tour.startedexampleAction, Tour, Step, User ProfileSent when the Tour is started; includes the first Step in the payload
tour.completedexampleAction, Tour, Step, User ProfileSent when the Tour is completed; includes the Step the user completed
tour.exitedexampleAction, Tour, Step, User ProfileSent when the Tour is exited; includes the Step the user exited
tour.snoozedexampleAction, Tour, Step, User ProfileSent when the Tour is exited on Step configured to snooze (re-display the Step at a later time).
tour.button.clickedexampleTour, Step, Button, User ProfileSent when the Tour is exited with the Step the user exited
survey.startedexampleAction, Microsurvey, Step, User ProfileSent when the Microsurvey is started with the first Step
survey.completedexampleAction, Microsurvey, Step, User ProfileSent when the Microsurvey is completed with the Step the user completed
survey.exitedexampleAction, Microsurvey, Step, User ProfileSent when the Microsurvey is exited with the Step the user exited
survey.snoozedexampleAction, Microsurvey, Step, User ProfileSent when the Tour is exited on Step configured to snooze (re-display the Step at a later time).
survey.button.clickedexampleMicrosurvey, Step, Button, User ProfileSent when the Tour is exited with the Step the user exited
embed.startedexampleAction, Embed, Step, User ProfileSent when the Embed is started; includes the first Step in the payload
embed.completedexampleAction, Embed, Step, User ProfileSent when the Embed is completed; includes the Step the user completed
embed.exitedexampleAction, Embed, Step, User ProfileSent when the Embed is exited; includes the Step the user exited
embed.snoozedexampleAction, Embed, Step, User ProfileSent when the Embed is exited on Step configured to snooze (re-display the Step at a later time).
embed.button.clickedexampleEmbed, Step, Button, User ProfileSent when the Embed is exited with the Step the user exited
demo.startedexampleDemo, DemoRun, User ProfileSent when the Demo is started
demo.revealexampleDemo, DemoRun, User ProfileSent after the Demo is started and Clearbit reveal is enabled and a match is found. The demo_run will have reveal_domain and reveal_name keys for the Company domain and Company name
demo.finishedexampleDemo, DemoRun, User ProfileSent when the Demo is finished; Either the last step is reached OR when approximately 30 minutes has passed and the user likely bounced. The demo_run will have finished_kind of either "last_step" or "timeout_30m".
demo.form.submittedexampleDemo, DemoRun, User ProfileSent when a Demo form is submitted. The action will have the submission as a DemoSubmission object. The final demo.finished webhook will contain all of the actions and submissions
Looking for a different topic? We’re excited to chat about your use case! Contact us

Schema (request body)

PropertyTypeDescription
idIDThe Chameleon ID
sent_attimestampThe current server time when this webhook was sent (used in verification)
kindenumThe topic identifier
dataobjectContains the webhook payload data. This can be any models included by singular or plural name

Request headers

HeaderExample valueDescription
X-Chameleon-Id5f3c4232c712de665632a2a3The Chameleon ID of this webhook
X-Chameleon-Signature5a17b…The SHA256-HMAC of the raw request body
User-AgentChameleon Webhooks/v3 (chameleon.io; integral)The request is from the Chameleon v3 API (integral environment)
Content-Typeapplication/jsonSignifying that the request body is JSON
Acceptapplication/jsonSignifying that the response should be JSON (or nothing)

Verifying the Webhook

The signature is the SHA256-HMAC of your Webhook Secret and the request body. As a second step, reject the message if it was sent outside of a few minutes (in the examples below 5 minutes is used; to prevent replay attacks)

Verification Examples

Rails
# Assumes this code runs in a Controller to access the `request` object
# Could easily be run in a background task or elsewhere by passing the `X-Chameleon-Signature` and `request.raw_post` exactly as-is

secret = ENV['CHAMELEON_VERIFICATION_SECRET']
received = request.headers['X-Chameleon-Signature']
expected = OpenSSL::HMAC.hexdigest('SHA256', secret, request.raw_post)

verified = ActiveSupport::SecurityUtils.secure_compare(received, expected) &&
 (sent_at = Time.zone.parse(params[:sent_at])) &&
 (sent_at > 5.minutes.ago && sent_at < 5.minutes.from_now)
Have an example from your production app to add? Submit a PR to this file and we’ll give you $25 Amazon credit via our Docs Bounty program!

Action

Each Webhook can contain an action key in the payload. It will contain contextual information about the webhook, the source of the webhook, the state of a user, etc.
PropertyTypeDescription
idIDThe Chameleon ID of this Action

Action

Applies to tour.started, tour.completed, tour.exited, survey.started, survey.completed, survey.exited, embed.started, embed.completed, embed.exited
PropertyTypeDescription
idIDThe Chameleon ID of this Action
group_kindstringType of group association. One of null, link, api_js, launcher, experiment, campaign, delivery, helpbar, or agent
group_idIDThe ID of associated group, this can be a Launcher ID, another Tour ID, or null if no associated ID

Action

Applies to tour.snoozed, survey.snoozed, embed.snoozed
PropertyTypeDescription
idIDThe Chameleon ID of this Action
deferred_untiltimestampThe ending time of the snooze
deferred_hoursintegerThe number of hours that this was snoozed for
deferred_countintegerThe number of times in a row this has been snoozed
PropertyTypeDescription
idIDThe Chameleon ID of this Action
querystringThe search query text that was submitted by the user
results_countintegerTotal number of search results returned for this query

Action (helpbar.item.error)

PropertyTypeDescription
idIDThe Chameleon ID of this Action
querystringThe search query text that was submitted by the user
item_uidstringUnique identifier for the search result item that encountered an error
titlestringThe title or display name of the search result item
action_infostringAdditional action information or metadata related to the error
urlstringThe URL or link associated with the search result item
action_kindsarray<string>Array of action types or categories that describe the error context

Action (helpbar.item.action)

PropertyTypeDescription
idIDThe Chameleon ID of this Action
querystringThe search query text that was submitted by the user
item_uidstringUnique identifier for the search result item that was acted upon
titlestringThe title or display name of the search result item
hrefstringThe URL or link that the user can interact with for this search result
kindsarray<string>Array of action types or categories that describe what actions are available

Action (helpbar.answer)

PropertyTypeDescription
idIDThe Chameleon ID of this Action
querystringThe search query text that was submitted by the user
answerstringThe generated or retrieved answer content in response to the search query
urlstringThe page that the user was on when the answer was generated
results_countintegerNumber of source results that were used to generate this answer
referencesarray<string>Array of reference URLs or sources that support the provided answer

Payload Examples

Example ping
Typically do process Verification for this topic but nothing really to be done when topic is received. It’s simply part of how Chameleon determines active/inactive/performance of webhook endpoints.
{
  "id": "5fb70dcbc39330000325a817",
  "kind": "ping",
  "sent_at": "2029-12-11T00:28:59.650Z",
  "data": {
    "account": {
      "id": "58918bc07de121000432e9c0",
      "domain": "acme.co",
      "name": "Acme Corp"
    }
  }
}
Example response-finished
Every Microsurvey that is finished will send a webhook to this topic.
{
  "id": "5fb70dcbc39330000325a81a",
  "kind": "response.finished",
  "sent_at": "2029-12-11T00:28:59.651Z",
  "data": {
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "response": {
      "id": "5fb7afb5ea19724169374269",
      "survey_id": "5fb7936edee1f70011bfc4c9",
      "profile_id": "5f884e1e03d9f4000ebcbb59",
      "href": "https://app.acme.co/setup/tough-thing-to-do",
      "button_text": "Very Easy",
      "button_order": 0,
      "input_text": "I was able to figure it out quickly.",
      "finished_at": "2029-12-11T00:28:59.641Z"
    },
    "survey": {
      "id": "5fb7936edee1f70011bfc4c9",
      "name": "2029-11 Role question",
      "segment_id": "5f885a88e7daf3000e3eb4f7",
      "published_at": "2029-11-11T00:12:59.002Z",
      ...
      "steps": [
        {
          "id": "5fb7936d566535d75a87507c",
          "body": "How was that?",
          "preset": "survey_five",
          "dropdown_items": [
          ]
        },
        {
          "id": "5fb7936d566535d75a87507e",
          "body": "Thanks so much for your feedback! 🙏",
          "preset": "thank_you"
        }
      ],
      "user": {
        "id": "5490e42d65353700020030fa",
        "email": "[email protected]",
        "name": "Jim B"
      }
    }
  }
}
Example helpbar-answer
This is the most important HelpBar webhook; it can directly inform your roadmap for additional updated/documentation.
  • Chameleon AI Answering operates best when:
  • A headline (h2/h3) in the Help center article is relevant to the question being asked
  • Multiple inputs corroborate from different angles
  • Seeing a results_count less than 3 is an important metric to track
  • Use references to know where to make improvements
{
  "id": "5eb7c393300000dcb381a25a",
  "kind": "helpbar.answer",
  "sent_at": "2029-12-11T00:28:59.651Z",
  "data": {
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "query": "What is a widget?",
      "answer": "A widget is the generic name for the work product of a production run. One might use this term to describe something generic as an example in place of an unimportant specific item.",
      "results_count": 7,
      "references": ["https://help.your-product.com/hc/articles/925844-widgets-galore", "https://help.your-product.com/hc/articles/559284-widgets-n-more"],
      "url": "https://app.your-product.com/widgets/start"
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    }
  }
}
Example helpbar-search
When a User searches for "data importing" only 0 results were found. This indicates a gap in your Help center.
{
  "id": "5eb7c393300000dcb381a25a",
  "kind": "helpbar.search",
  "sent_at": "2029-12-11T00:29:59.651Z",
  "data": {
    "action": {
      "id": "5f885a88e7daf3000e3eb4f7",
      "query": "data importing",
      "results_count": 2,
      "url": "https://app.your-product.com/widgets/import"
    },
    "profile": {
      "id": "5f885a88f30e7da00e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 85,
      ...
    }
  }
}
When a User searches for "widget categories" only 7 results were found.
{
  "id": "5eb7c393300000dcb381a25a",
  "kind": "helpbar.search",
  "sent_at": "2029-12-11T00:28:30.651Z",
  "data": {
    "action": {
      "id": "5f885a8af30008e7de3eb4f9",
      "query": "widget categories",
      "results_count": 7,
      "url": "https://app.your-product.com/widgets/import"
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 93,
      ...
    }
  }
}
Example helpbar-item-action
When a helpbar search result item is clicked (or actioned)
{
  "id": "5eb7c393300000dcb381a25a",
  "kind": "helpbar.item.action",
  "sent_at": "2029-12-11T00:28:18.651Z",
  "data": {
    "action": {
      "id": "5f885a8af30008e7de3eb4f9",
      "item_uid": "data-onboarding",
      "href": "https://help.your-product.com/hc/articles/559284-data-onboarding",
      "kinds": ["url"]
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 93,
      ...
    }
  }
}
Example helpbar-item-error
When a helpbar search result item is clicked (or actioned) and then encounters an error processing the actions. In the example below, the script item is not working properly and should be checked
{
  "id": "5eb7c393300000dcb381a25a",
  "kind": "helpbar.item.action",
  "sent_at": "2029-12-11T00:28:18.651Z",
  "data": {
    "action": {
      "id": "5f885a8af30008e7de3eb4f9",
      "item_uid": "demo-upgrade",
      "href": "https://calendly.com/your-product/demo-upgrade-chat",
      "kinds": ["script", "calendly"]
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 93,
      ...
    }
  }
}
Example tour-all
A Tour is started, runs through a sequence of 1 or more Steps and finishes by being Exited or Completed. Tours by default show once to any one User but can, depending on their settings, show multiple times.
{
  "id": "5fb70dcbc39330000325a818",
  "kind": "tour.started",
  "sent_at": "2029-12-11T00:28:59.652Z",
  "data": {
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "group_kind": "api_js",
      "group_id": null
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "tour": {
      "id": "5fb6e4ab8af58a00073f0d98",
      "name": "Usage upsell banner - A",
      "segment_id": "5f885a88e7daf3000e3eb4f7",
      "published_at": "2029-11-11T00:12:59.002Z",
      ...
    },
    "step": {
      "id": "5fb6e4ab8af58a00073f0d99",
       "body": "You've grown beyond your current plan by {{mau_blocks fallback='a lot'}}! 🎉 -- Next billing cycle, you will be charged for the additional users or pre-pay to save",
       ...
    }
  }
}
Example tour-snooze
When a Tour is snoozed it is set to come back after a certain amount of time has passed (i.e. 1 day, 2 weeks, 2 hours etc.).
Look for data.action to be an object with the information on when this snooze ends, how many hours, and how many snoozes this totals.
{
  "id": "5fb70dcbc39330000325a818",
  "kind": "tour.snoozed",
  "sent_at": "2029-12-11T00:28:59.652Z",
  "data": {
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "deferred_until": "2029-12-14T00:28:58.622Z",
      "deferred_hours": 72,
      "deferred_count": 2
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "tour": {
      "id": "5fb6e4ab8af58a00073f0d98",
      "name": "Usage upsell banner - A",
      "segment_id": "5f885a88e7daf3000e3eb4f7",
      "published_at": "2029-11-11T00:12:59.002Z",
      ...
    },
    "step": {
      "id": "5fb6e4ab8af58a00073f0d99",
       "body": "You've grown beyond your current plan by {{mau_blocks fallback='a lot'}}! 🎉 -- Next billing cycle, you will be charged for the additional users or pre-pay to save",
       ...
    }
  },
}
Example tour-button-clicked
Every Button that is clicked in a Tour / Microsurvey will send a webhook to this topic. It includes the Step and the Button configuration.
{
  "id": "5fb70dcbc39330000325a819",
  "kind": "tour.button.clicked",
  "sent_at": "2029-12-11T00:28:59.653Z",
  "data": {
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "tour": { // or "survey" or "embed"
      "id": "5fb6e4ab8af58a00073f0d98",
      "name": "Usage upsell banner - A",
      "segment_id": "5f885a88e7daf3000e3eb4f7",
      "published_at": "2029-11-11T00:12:59.002Z",
      ...
    },
    "step": {
      "id": "5fb6e4ab8af58a00073f0d99",
       "body": "You've grown beyond your current plan by {{mau_blocks fallback='a lot'}}! 🎉 -- Next billing cycle, you will be charged for the additional users or pre-pay to save",
       ...
    },
    "button": {
      "id": "5fb6e4ab8af58a00073f0d9a",
       "text": "Check pricing",
       "tour_action": "next",
       "position": "bottom_right",
       ...
    },
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6"
    }
  }
}
Example embed-all
An Embed is started, runs through a sequence of 1 or more Steps and finishes by being Exited or Completed. Embeds by default show once to any one User but can, depending on their settings, show multiple times.
{
  "id": "5fb70dcbc39330000325a818",
  "kind": "embed.started",
  "sent_at": "2029-12-11T00:28:59.652Z",
  "data": {
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "group_kind": "api_js",
      "group_id": null
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "embed": {
      "id": "5fb6e4ab8af58a00073f0d98",
      "name": "Usage upsell banner - A",
      "segment_id": "5f885a88e7daf3000e3eb4f7",
      "published_at": "2029-11-11T00:12:59.002Z",
      ...
    },
    "step": {
      "id": "5fb6e4ab8af58a00073f0d99",
       "body": "You've grown beyond your current plan by {{mau_blocks fallback='a lot'}}! 🎉 -- Next billing cycle, you will be charged for the additional users or pre-pay to save",
       ...
    }
  }
}
Example embed-snooze
When an Embed is snoozed it is set to come back after a certain amount of time has passed (i.e. 1 day, 2 weeks, 2 hours etc.).
Look for data.action to be an object with the information on when this snooze ends, how many hours, and how many snoozes this totals.
{
  "id": "5fb70dcbc39330000325a818",
  "kind": "embed.snoozed",
  "sent_at": "2029-12-11T00:28:59.652Z",
  "data": {
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "deferred_until": "2029-12-14T00:28:58.622Z",
      "deferred_hours": 72,
      "deferred_count": 2
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "embed": {
      "id": "5fb6e4ab8af58a00073f0d98",
      "name": "Usage upsell banner - A",
      "segment_id": "5f885a88e7daf3000e3eb4f7",
      "published_at": "2029-11-11T00:12:59.002Z",
      ...
    },
    "step": {
      "id": "5fb6e4ab8af58a00073f0d99",
       "body": "You've grown beyond your current plan by {{mau_blocks fallback='a lot'}}! 🎉 -- Next billing cycle, you will be charged for the additional users or pre-pay to save",
       ...
    }
  },
}
Example alert-triggered
When Experiences are in violation of the Alert conditions. The primary use case for this is to notify the person in charge of the Experience when X days have passed without activity (on something that is otherwise expected to have activity).
Experiences are either kind=tour for a Tour or kind=survey for a Microsurvey
For Tags and Environments see the "tags" and "url_groups" keys below and see Experience page.
{
  "id": "6fd85a88e7daf3000e3eb4f7",
  "kind": "alert.triggered",
  "sent_at": "2029-12-12T01:28:59.654Z",
  "data": {
    "alert_group": {
      "id": "6de85a88e7daf3000e3eb4f6",
      "name": "Tour + Microsurvey 5-day dropoff",
      "summary": "Checks for Experiences that are not Seen in the past 5 days.",
      "interval": 5,
      "kind": "all",
      "style": "unseen",
      "created_user": {
        "id": "63165266260fe8000781b161",
        "email": "[email protected]",
        ...
      },
      "urls": {
        "dashboard": "https://app.chameleon.io/alerts/6de85a88e7daf3000e3eb4f6"
      },
      ...
    },
    "experiences": [
      {
        "id": "6fd85a88e7daf3000e3eb4f8",
        "name": "Usage upsell banner - A",
        "kind": "tour",
        "segment_id": "6d885a88e7daf3000e3eb4f9",
        "published_at": "2029-11-06T00:12:59.002Z",
        ...
      },
      {
        "id": "6fd85a88e7daf3000e3eb4e8",
        "name": "Usage upsell banner - C",
        "kind": "tour",
        "segment_id": "6d885a88e7daf3000e3eb4f8",
        "published_at": "2029-11-11T00:12:59.002Z",
        "tags": [
          {
            "id": "6a885a880e3e4b8fe7daf300",
            "uid": "announcement",
            "name": "Feature announcement",
            "urls": {
              "dashboard": "https://app.chameleon.io/data/tags/6a885a880e3e4b8fe7daf300"
            },
            ...
          },
          ...
        ],
        "url_groups": [
          {
            "id": "6f885a88e7daf3000e3e4b8f",
            "name": "Production",
            "urls": {
              "dashboard": "https://app.chameleon.io/domains/6f885a88e7daf3000e3e4b8f"
            },
            ...
          }
        ],
        ...
      },
      {
        "id": "6fd85a88e7daf3000e3eb4e8",
        "name": "Request for research participants - 2029-11",
        "kind": "survey",
        "segment_id": "6d885a88e7daf3000e3eb4f8",
        "published_at": "2029-11-01T00:12:59.002Z",
        ...
      }
    ],
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "summary": "3 Experiences went 5 days without being Seen."
    }
  }
}
Example survey-all
These three topics are considered lifecycle events and occur when the user is presented with or interacts with a Chameleon Microsurvey. The response.finished Webhook is only sent when we consider the user done with the Microsurvey and will no longer interact with it. A Microsurvey Response is generated when the Survey Step + associated Response Step are finished; it sends a response.finished Webhook. A Microsurvey is started on the Survey Step and either completed or exited when the first step is “actioned”. It then automatically branches through a sequence of optional Response Steps and finishes with an optional Thank You Step.
The Steps corresponding to a Response Step have preset=response; The Thank You Steps have preset=thank_you
{
  "id": "5fb70dcbc39330000325a818",
  "kind": "survey.completed",
  "sent_at": "2029-12-11T00:28:59.652Z",
  "data": {
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "group_kind": "api_js",
      "group_id": null
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "survey": {
      "id": "5fb7936edee1f70011bfc4c9",
      "name": "2029-11 Role question",
      "segment_id": "5f885a88e7daf3000e3eb4f7",
      "published_at": "2029-11-11T00:12:59.002Z",
      "steps": [
        {
          "id": "5fb7936d566535d75a87507c",
          "body": "How was that?",
          "preset": "survey_five",
          ...
        },
        {
          "id": "5fb7936d566535d75a87507d",
          "body": "Why specifically did you struggle?",
          "preset": "response",
          ...
        }
        ...
      ],
      ...
    },
    "step": {
      "id": "5fb7936d566535d75a87507c",
      "body": "How was that?",
      "preset": "survey_five",
       ...
    }
  }
}
Example survey-snooze
When a Microsurvey is snoozed it is set to come back after a certain amount of time has passed (i.e. 1 day, 2 weeks, 2 hours etc.).
Look for data.action to be an object with the information on when this snooze ends, how many hours, and how many snoozes this totals.
{
  "id": "5fb70dcbc39330000325a818",
  "kind": "survey.snoozed",
  "sent_at": "2029-12-11T00:28:59.652Z",
  "data": {
    "action": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "deferred_until": "2029-11-15T00:02:19.002Z",
      "deferred_hours": 48,
      "deferred_count": 2
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "survey": {
      "id": "5fb7936edee1f70011bfc4c9",
      "name": "2029-11 Role question",
      "segment_id": "5f885a88e7daf3000e3eb4f7",
      "published_at": "2029-11-11T00:12:59.002Z",
      "steps": [
        {
          "id": "5fb7936d566535d75a87507c",
          "body": "How was that?",
          "preset": "survey_five",
          ...
        },
        {
          "id": "5fb7936d566535d75a87507d",
          "body": "Why specifically did you struggle?",
          "preset": "response",
          ...
        }
        ...
      ],
      ...
    },
    "step": {
      "id": "5fb7936d566535d75a87507d",
      "body": "Why specifically did you struggle?",
      "preset": "response",
      ...
    }
  }
}
Example demo-started
Right when the Demo is first started in this session. Chameleon calls this a Demo “run”. Demos can also sync Contact data into the CRM
For an anonymous user (e.g. on your marketing website) the data.profile will be null and demo_run.anonymous_id will be stable until local cache is cleared
{
  "id": "6fb70330dcbc39000325a94a",
  "kind": "demo.started",
  "sent_at": "2029-12-11T00:28:59.331Z",
  "data": {
    "action" : {
      "id": "6f885a88e7daf34f6000e3eb"
    },
    "profile": {
      "id": "5f885a88e7daf3000e3eb4f6",
      "email": "[email protected]",
      "uid": "92340834",
      "name": "Jane E",
      "last_seen_at": "2029-12-11T00:21:59.109Z",
      "last_seen_session_count": 83,
      ...
    },
    "demo_run": {
      "id": "5fb7afb5ea19724169374269",
      "referrer":  "https://www.acme.co/products/analytics",
      "created_what":  "Chrome 191.0 (Mac)",
      "created_where": "Oakland CA, US 🇺🇸",
      "anonymous_id": "5fb7afb5ea19724169374269",
      "consent_mode": "granted",
      ...
    },
    "demo": {
      "id": "5fb7936edee1f70011bfc4c9",
      "name": "Demo of Analysis quickstart",
      "description": "Our analysis goes deeper than you'd typically see in a trial",
      "href": "https://app.acme.co/setup/tough-thing-to-do",
      "page_title": "Analytics",
      ...
      "user": {
        "id": "5490e42d65353700020030fa",
        "email": "[email protected]",
        "name": "Jim B"
      }
    }
  }
}
Example demo-finished
This webhook topic only differs from demo.started by the addition of the following keys in the demo_run.
  1. In the demo_run, an actions array of DemoActions
  2. In the demo_run, a submissions array of DemoSubmissions with a data key of DemoSubmissionData
  3. finished_kind in the demo_run as either "last_step" or "timeout_30m" to give an indication of how this Demo was finished
It will be sent when the last step of the Demo is reached with finished_kind=last_step OR approximately 30 minutes after the last activity in the Demo and finished_kind=timeout_30m.
{
  "id": "6fb70330dcbc39000325a94b",
  "kind": "demo.finished",
  "sent_at": "2029-12-11T00:28:59.331Z",
  "data": {
    "action" : {
      "id": "6f885a88e7daf34f6000e3eb"
    },
    "demo_run": {
      ...,
      "finished_kind": "last_step",
      "actions": [
        {
          "id": "",
          "name": "Demo Started",
          ...
        },
        {
          "id": "",
          "name": "Demo Step Started",
          ...
        },
        ...
      ],
      "submissions": [
        {
          "id": "6f885a84f600b0e38e7daf3e",
          "step_id": "5fb7936edee1f70011bfc4c9",
          "data": [
            {
              "field": {
                "id": "6fa88e7daf34f6000e3eb885",
                "type": "email",
                "name": "Email address",
                "description": ""
              },
              "value": "[email protected]"
            },
            {
              "field": {
                "id": "6fa88e7daf34f6000e3eb885",
                "type": "select",
                "name": "Urgency",
                "description": "Knowing how quickly you want to evaluate Acme helps us mirror your urgency"
              },
              "value": "this week"
            },
            ...
          ]
        }
      ],
    },
    "demo": {
      "id": "5fb7936edee1f70011bfc4c9",
      ...
    }
  }
}
Example demo-reveal
This webhook topic only differs by the addition of reveal_domain, reveal_name, and clearbit_uid in the demo_run. It will be sent when the following conditions are met
  1. Clearbit Reveal is configured in your dashboard
  2. The consent_mode of the Demo was set to granted (e.g. data-consent-mode="granted" on the iframe element for the embed)
  3. A match is found to the IP address of anonymous traffic
{
  "id": "6fb70330dcbc39000325a94b",
  "kind": "demo.reveal",
  "sent_at": "2029-12-11T00:28:59.331Z",
  "data": {
    "action" : {
      "id": "6f885a88e7daf34f6000e3eb"
    },
    "demo_run": {
      ...,
      "reveal_domain": "zenflex.io",
      "reveal_name": "Zen Flexing Aura Ltd.",
      "clearbit_uid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "consent_mode": "granted"
    },
    "demo": {
      "id": "5fb7936edee1f70011bfc4c9",
      ...
    }
  }
}
Example demo-form-submitted
This webhook topic is meant to sync any form data to an external system; typically involving adding a new contact to your CRM. The action.submission is a DemoSubmissions with a data key of DemoSubmissionData and each data item has a field as DemoFormField and value.
{
  "id": "6fb70330dcbc39000325a94b",
  "kind": "demo.form.submitted",
  "sent_at": "2029-12-11T00:28:59.331Z",
  "data": {
    "action" : {
      "id": "6f885a88e7daf34f6000e3eb",
      "submission": {
        "id": "6f885a84f600b0e38e7daf3e",
        "step_id": "5fb7936edee1f70011bfc4c9",
        "data": [
          {
            "field": {
              "id": "6fa88e7daf34f6000e3eb885",
              "type": "email",
              "name": "Email address",
              "description": ""
            },
            "value": "[email protected]"
          },
          {
            "field": {
              "id": "6fa88e7daf34f6000e3eb885",
              "type": "select",
              "name": "Urgency",
              "description": "Knowing how quickly you want to evaluate Acme helps us mirror your urgency"
            },
            "value": "this week"
          },
          ...
        }
      ],
    },
    "demo_run": {
      ...,
    },
    "demo": {
      "id": "5fb7936edee1f70011bfc4c9",
      ...
    }
  }
}
Example demo-email-added
This webhook topic is meant to capture the moment when previously taken anonymous Demos receive an email address. The flow can be arbitrarily complex but typically follows one of these paths:
  1. Demos taken => Submits interest form
    1. User takes 1 or more Demos on the marketing site, help documentation, etc.
    2. In one of the Demos, the User submits a form with their email
    3. Chameleon will then update all the previous DemoRuns from [1i] (e.g. those connected with the anonymous_id)
    4. Chameleon sends one demo.email.added webhook per updated DemoRun
  2. Demos taken => Product signup
    1. User takes 1 or more Demos on the marketing site, help documentation, etc.
    2. User sign up for the product and is identified with their email address
    3. Chameleon will then update all the previous DemoRuns from [2i] (e.g. those connected with the anonymous_id)
    4. Chameleon sends one demo.email.added webhook per updated DemoRun
action.email will have email address as a copy of the email address now found in demo_run.email.
{
  "id": "6fb70330dcbc39000325a94b",
  "kind": "demo.email.added",
  "sent_at": "2029-12-11T00:28:59.331Z",
  "data": {
    "action" : {
      "id": "6f885a88e7daf34f6000e3eb",
      "email": "[email protected]"
    },
    "demo_run": {
      ...,
    },
    "demo": {
      "id": "5fb7936edee1f70011bfc4c9",
      ...
    }
  }
}