Summary and recommendation
Chameleon's REST API (base URL: https://api.trychameleon.com/v3) authenticates via a static account-level secret passed as the X-Account-Secret header. There is no scoped or per-user token system. The API splits cleanly into two namespaces: /v3/observe/ endpoints are write-only ingestion paths; /v3/analyze/ endpoints are read-only query paths.
The primary integration method for end-user data is the JavaScript snippet (chmln.identify()), not the REST API. The REST API is supplementary - useful for server-side upserts, bulk profile reads, and programmatic deletion, but not a replacement for the client-side identify call.
For teams managing Chameleon seat provisioning at scale, Stitchflow provides an MCP server with ~100 deep IT/identity integrations, enabling automated joiner/mover/leaver workflows across Chameleon and connected systems without custom pipeline work.
API quick reference
| Has user API | Yes |
| Auth method | API Key (secret token passed as HTTP header X-Account-Secret) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Any plan (SSO/SCIM add-on required; SSO must be configured first) |
Authentication
Auth method: API Key (secret token passed as HTTP header X-Account-Secret)
Setup steps
- Log in to Chameleon dashboard.
- Navigate to Settings > API.
- Copy the Account Secret token.
- Include it in all API requests as the header: X-Account-Secret:
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| uid | string | Unique identifier for the user in your system | required | required | Used as the primary key to identify users in Chameleon |
| string | User's email address | optional | optional | Recommended for identification and targeting | |
| name | string | Full name of the user | optional | optional | |
| role | string | User's role within their organization | optional | optional | Used for segmentation |
| plan | string | Subscription plan of the user or their company | optional | optional | Used for targeting tours to specific plan tiers |
| created_at | timestamp (ISO 8601) | When the user account was created in your system | optional | optional | |
| company | object | Company/account the user belongs to | optional | optional | Nested object with uid and properties |
| company.uid | string | Unique identifier for the user's company | optional | optional | Used for account-level segmentation |
| company.name | string | Name of the user's company | optional | optional | |
| custom properties | any | Arbitrary key-value pairs for user traits | optional | optional | Any additional properties sent are stored as custom user traits for segmentation |
Core endpoints
Upsert (create or update) a user profile
- Method: POST
- URL:
https://api.trychameleon.com/v3/observe/hooks/profiles - Watch out for: This is the primary way to send user data to Chameleon. It upserts based on uid. Custom properties are merged, not replaced.
Request example
POST /v3/observe/hooks/profiles
X-Account-Secret: <token>
Content-Type: application/json
{
"profile": {
"uid": "user_123",
"email": "user@example.com",
"plan": "growth"
}
}
Response example
{
"profile": {
"uid": "user_123",
"id": "5f3e..."
}
}
List user profiles
- Method: GET
- URL:
https://api.trychameleon.com/v3/analyze/profiles - Watch out for: Pagination uses a cursor parameter. Returns up to 50 profiles per page.
Request example
GET /v3/analyze/profiles?limit=50
X-Account-Secret: <token>
Response example
{
"profiles": [
{"uid": "user_123", "email": "user@example.com"}
],
"cursor": "abc123"
}
Get a single user profile
- Method: GET
- URL:
https://api.trychameleon.com/v3/analyze/profiles/:uid - Watch out for: The :uid segment is your system's user identifier, not Chameleon's internal ID.
Request example
GET /v3/analyze/profiles/user_123
X-Account-Secret: <token>
Response example
{
"profile": {
"uid": "user_123",
"email": "user@example.com",
"plan": "growth"
}
}
Delete a user profile
- Method: DELETE
- URL:
https://api.trychameleon.com/v3/analyze/profiles/:uid - Watch out for: Deletes the user profile and associated data from Chameleon. Irreversible.
Request example
DELETE /v3/analyze/profiles/user_123
X-Account-Secret: <token>
Response example
{
"profile": {
"uid": "user_123",
"deleted": true
}
}
Upsert company (account) data
- Method: POST
- URL:
https://api.trychameleon.com/v3/observe/hooks/companies - Watch out for: Company data is separate from user profiles. Associate users to companies via the company.uid field in the profile payload.
Request example
POST /v3/observe/hooks/companies
X-Account-Secret: <token>
Content-Type: application/json
{
"company": {
"uid": "company_456",
"name": "Acme Corp",
"plan": "enterprise"
}
}
Response example
{
"company": {
"uid": "company_456",
"id": "5f4a..."
}
}
Send a custom event (track)
- Method: POST
- URL:
https://api.trychameleon.com/v3/observe/hooks/events - Watch out for: Events are used for tour triggering and segmentation. profile_uid must match an existing profile uid.
Request example
POST /v3/observe/hooks/events
X-Account-Secret: <token>
Content-Type: application/json
{
"event": {
"name": "feature_used",
"profile_uid": "user_123"
}
}
Response example
{
"event": {
"id": "evt_789",
"name": "feature_used"
}
}
Rate limits, pagination, and events
Rate limits: Chameleon does not publicly document specific rate limit numbers. Rate limiting is enforced but thresholds are not published in official docs.
Rate-limit headers: Unknown
Retry-After header: Unknown
Rate-limit notes: No publicly documented rate limit tiers or headers found in official documentation. Contact Chameleon support for enterprise limits.
Pagination method: cursor
Default page size: 50
Max page size: 50
Pagination pointer: cursor
Webhooks available: Yes
Webhook notes: Chameleon supports outbound webhooks that fire on user interactions with Chameleon experiences (e.g., tour completion, survey response).
Alternative event strategy: Chameleon also supports native integrations with Segment, Heap, Mixpanel, and others for event forwarding.
Webhook events: tour_started, tour_completed, tour_dismissed, survey_started, survey_completed, button_clicked
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Any plan (SSO/SCIM add-on required; SSO must be configured first)
Endpoint: https://api.trychameleon.com/scim/v2
Supported operations: Create user, Update user, Deactivate user, List users, Get user by ID
Limitations:
- SSO must be configured as a prerequisite before SCIM can be enabled.
- SCIM is a paid add-on and not included by default on any plan.
- Only Okta is confirmed as a supported IdP in official documentation; Entra ID, Google Workspace, and OneLogin are not listed.
- Group provisioning support is not documented in official help articles.
- SCIM manages Chameleon team member (seat) provisioning, not end-user profile data.
Common scenarios
Three well-defined automation scenarios emerge from the API surface.
Sync new user on signup: POST to /v3/observe/hooks/profiles with uid, email, plan, and traits. If the user belongs to a company, also POST to /v3/observe/hooks/companies and include company.uid in the profile payload. The uid sent via REST API must exactly match the uid passed to chmln.identify() in the browser - mismatches create duplicate profiles that are not automatically merged.
Deprovision an end-user: Send DELETE to /v3/analyze/profiles/:uid to remove tracked data. Deletion is permanent and removes all associated tour and survey history. Confirm via GET returning 404. SCIM deactivation handles team seat removal only - end-user profile cleanup requires this separate REST call.
Provision an internal team member via SCIM (Okta): SSO must be fully configured before SCIM can be activated. Obtain the SCIM base URL (https://api.trychameleon.com/scim/v2) and bearer token from Chameleon Settings, configure the Okta app, and assign users. Deprovisioning in Okta sends PATCH active:false. Only Okta is confirmed as a supported IdP in official documentation; Entra ID, Google Workspace, and OneLogin are not listed.
Sync new user on signup
- After user signs up in your app, POST to /v3/observe/hooks/profiles with uid, email, plan, and any relevant traits.
- If the user belongs to a company, also POST to /v3/observe/hooks/companies with company uid and traits, and include company.uid in the profile payload.
- Chameleon will upsert the profile; subsequent JS snippet calls with the same uid will merge data.
Watch out for: Ensure the uid sent via REST API exactly matches the uid passed to chmln.identify() in the browser to avoid duplicate profiles.
Deprovision a user (offboarding)
- When a user is removed from your system, send a SCIM PATCH (active: false) or DELETE to deactivate their Chameleon team seat if they are an internal user.
- For end-user profile cleanup, send DELETE to /v3/analyze/profiles/:uid to remove their tracked data.
- Confirm deletion via GET /v3/analyze/profiles/:uid returning 404.
Watch out for: SCIM deactivation only affects Chameleon team members (seats). End-user profile deletion requires a separate REST API call.
Provision internal team member via SCIM (Okta)
- Ensure SSO is configured in Chameleon Settings.
- Purchase the SCIM add-on and obtain the SCIM base URL and bearer token from Chameleon Settings.
- In Okta, add the Chameleon SCIM app and configure the base URL (https://api.trychameleon.com/scim/v2) and API token.
- Assign Okta users to the Chameleon app; Okta will POST to /scim/v2/Users to provision seats.
- Deprovisioning in Okta will send PATCH active:false to deactivate the Chameleon seat.
Watch out for: SSO must be fully configured before SCIM can be activated. SCIM token is separate from the REST API account secret.
Why building this yourself is a trap
Several non-obvious constraints create integration risk. Rate limits are enforced but thresholds are not publicly documented - implement exponential backoff from the start and contact Chameleon support for enterprise-tier limits before building high-volume pipelines.
SCIM scope is narrower than it appears: it provisions Chameleon team members (internal seats) only, not the end-user profiles tracked in tours and surveys. A complete offboarding automation requires both a SCIM deactivation and a separate REST API profile deletion - treating them as equivalent will leave orphaned end-user data.
Group provisioning via SCIM is also not documented, limiting role assignment automation to individual user records.
API keys are account-level secrets with no scoping mechanism, meaning any service using the key has full read/write access to all profile and event data. There is no documented token rotation workflow in official sources.
Automate Chameleon workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.