When to call
Call track whenever a meaningful user action occurs. Every event has a name and optional properties that describe what happened.
-
Lifecycle eventsSignup, account creation, subscription changes, cancellations.
-
Feature engagementEach time a user interacts with a core or secondary product feature.
-
Onboarding stepsCompletion of profile setup, first actions, guided tour steps.
-
Viral actionsInvitations sent, referrals, team member additions.
Event naming conventions
Use a consistent object + past-tense verb format for all event names. This keeps your event taxonomy readable across teams and tools.
| Good | Avoid |
|---|---|
signed_up | signup, user_signup_event |
account_created | create_account, new_account |
feature_used | event_12, clicked |
invite_sent | send_invite, invitation |
profile_completed | profile_done, onboarding |
Endpoint
POST /api/track
Authentication
Pass your API key in the x-api-key header on every request. You can find your key in the ThriveStack dashboard under Settings → API Keys.
accept: */*
content-type: application/json
x-api-key: YOUR_API_KEY
Request body
Send an array containing one or more track objects.
| Field | Type | Required | Description |
|---|---|---|---|
event_name | string | Yes | Name of the action that occurred. Use past-tense, descriptive names (e.g., "signed_up", "feature_used"). |
user_id | string | Yes | The user who performed the action. |
properties | object | No | Free-form key-value pairs describing the event. See Reserved properties below. |
context.group_id | string | No | The account associated with this event. Required for account-level signal correlation. |
context.device_id | string | No | Unique identifier for the user's device. |
context.session_id | string | No | Current session identifier. |
context.source | string | No | "product" for in-app events, "marketing" for public-facing website events. |
timestamp | string | No | ISO 8601 timestamp. Defaults to the time the server receives the request. |
Reserved properties
ThriveStack recognises the following property names and gives them special handling in revenue and growth analytics.
| Property | Type | Description |
|---|---|---|
revenue | number | Dollar amount associated with the event (e.g., MRR change). Use decimal format: 49.99. |
currency | string | ISO 4217 currency code (e.g., "USD"). Defaults to "USD" if omitted. |
value | number | Abstract numeric value for non-revenue events (e.g., points, score). |
feature_name | string | Name of the product feature involved. |
feature_type | string | Classification of the feature: "core", "secondary", "add-on". |
page_url | string | Full URL of the page where the event occurred. |
page_path | string | Path portion of the URL (e.g., "/dashboard"). |
page_referrer | string | URL of the referring page. |
utm_source | string | UTM source parameter for attribution. |
utm_medium | string | UTM medium parameter for attribution. |
utm_campaign | string | UTM campaign parameter for attribution. |
Standard events
These are the ThriveStack lifecycle events that power the bow-tie revenue model and growth dashboards. Instrument them to unlock the full platform.
| event_name | When to fire | Key properties |
|---|---|---|
signed_up | New user completes registration | user_email, utm_source, utm_campaign |
account_created | New workspace/organization created | account_name, account_domain, account_id |
account_added_user | User linked to an existing account | account_name, user_email |
feature_used | User engages with a product feature | feature_name, feature_type, user_role |
profile_completed | User completes an onboarding step | completion_status, user_role |
invite_sent | User invites another person | invitee_email, invitee_role, feature_name |
page_visit | User visits a page | page_url, page_path, page_referrer, UTM fields |
Examples
Signup
curl --location 'https://api.app.thrivestack.ai/api/track' \
--header 'accept: */*' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '[
{
"event_name": "signed_up",
"properties": {
"user_email": "john.doe@acme.com",
"user_name": "John Doe",
"utm_campaign": "customer_success",
"utm_medium": "referral",
"utm_source": "twitter",
"utm_term": "free_trial"
},
"user_id": "18f716ac-37a4-464f-adb7-3cc30032308c",
"timestamp": "2024-01-15T10:30:00Z"
}
]'
Account created
curl --location 'https://api.app.thrivestack.ai/api/track' \
--header 'accept: */*' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '[
{
"event_name": "account_created",
"properties": {
"account_domain": "acme.com",
"account_id": "ac8db7ba-5139-4911-ba6e-523fd9c4704b",
"account_name": "Acme Corporation"
},
"user_id": "18f716ac-37a4-464f-adb7-3cc30032308c",
"timestamp": "2024-01-15T10:30:00Z",
"context": {
"group_id": "ac8db7ba-5139-4911-ba6e-523fd9c4704b"
}
}
]'
Feature engagement
curl --location 'https://api.app.thrivestack.ai/api/track' \
--header 'accept: */*' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '[
{
"event_name": "feature_used",
"properties": {
"feature_name": "export_report",
"feature_type": "core",
"user_role": "admin"
},
"user_id": "18f716ac-37a4-464f-adb7-3cc30032308c",
"timestamp": "2024-01-15T10:30:00Z",
"context": {
"group_id": "ac8db7ba-5139-4911-ba6e-523fd9c4704b"
}
}
]'
Invite sent
curl --location 'https://api.app.thrivestack.ai/api/track' \
--header 'accept: */*' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '[
{
"event_name": "invite_sent",
"properties": {
"feature_name": "report",
"invitee_email": "jane.doe@acme.com",
"invitee_role": "Admin",
"invitee_user_id": "ed1adb3a-9772-48ef-b620-e5e6d438fb82",
"sub_feature_name": "export_report",
"source_url": "https://acme.com/dashboard"
},
"user_id": "18f716ac-37a4-464f-adb7-3cc30032308c",
"timestamp": "2024-01-15T10:30:00Z",
"context": {
"group_id": "ac8db7ba-5139-4911-ba6e-523fd9c4704b"
}
}
]'
Page visit
curl --location 'https://api.app.thrivestack.ai/api/track' \
--header 'accept: */*' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '[
{
"event_name": "page_visit",
"properties": {
"page_title": "what is acme",
"page_url": "https://acme.com/what_is_acme",
"page_path": "/what_is_acme",
"page_referrer": "https://google.com",
"utm_campaign": "summer_promotion",
"utm_medium": "email",
"utm_source": "newsletter"
},
"user_id": "18f716ac-37a4-464f-adb7-3cc30032308c",
"timestamp": "2024-01-15T10:30:00Z",
"context": {
"group_id": "ac8db7ba-5139-4911-ba6e-523fd9c4704b",
"device_id": "7d08298f",
"session_id": "session_e2iukz3vduo",
"source": "product"
}
}
]'
JavaScript (generic)
const myHeaders = new Headers();
myHeaders.append("accept", "*/*");
myHeaders.append("content-type", "application/json");
myHeaders.append("x-api-key", "YOUR_API_KEY");
const raw = JSON.stringify([
{
event_name: "feature_used",
properties: {
feature_name: "export_report",
feature_type: "core",
user_role: "admin"
},
user_id: "18f716ac-37a4-464f-adb7-3cc30032308c",
timestamp: "2024-01-15T10:30:00Z",
context: {
group_id: "ac8db7ba-5139-4911-ba6e-523fd9c4704b"
}
}
]);
fetch("https://api.app.thrivestack.ai/api/track", {
method: "POST",
headers: myHeaders,
body: raw,
redirect: "follow"
})
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
Python (generic)
import requests
import json
url = "https://api.app.thrivestack.ai/api/track"
payload = json.dumps([
{
"event_name": "feature_used",
"properties": {
"feature_name": "export_report",
"feature_type": "core",
"user_role": "admin"
},
"user_id": "18f716ac-37a4-464f-adb7-3cc30032308c",
"timestamp": "2024-01-15T10:30:00Z",
"context": {
"group_id": "ac8db7ba-5139-4911-ba6e-523fd9c4704b"
}
}
])
headers = {
'accept': '*/*',
'content-type': 'application/json',
'x-api-key': 'YOUR_API_KEY'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
Response
200 OK
{
"success": true,
"eventId": "evt_abc123xyz"
}
Error codes
| Status | Meaning |
|---|---|
400 | Bad Request — invalid JSON or missing required fields |
401 | Unauthorized — invalid or missing API key |
429 | Rate Limit Exceeded |
500 | Server Error — try again later |