REST API
Use the HTTP API to send events from any language or environment where no SDK is available.
Use the HTTP API to send events from any language or environment where no SDK is available.
Base URL
https://sdk-api.trichidata.comAuthentication flow
The API uses a two-step authentication model:
init_sdk— authenticate with your project API key (Authorization: Bearer). The server creates a session and returns asdk_sessioncookie.- All other endpoints — authenticate with the
sdk_sessioncookie. No Bearer token required.
Cookie-based requests must include credentials:
fetch('https://sdk-api.trichidata.com/api/v1/track_event', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ... }),
});Cookie attributes: httpOnly, sameSite: none, secure in production, 7-day TTL (configurable).
Response format
All endpoints return a consistent envelope.
Success:
{
"success": true,
"message": "Event tracked successfully",
"data": { "eventId": "550e8400-e29b-41d4-a716-446655440000" }
}Error:
{
"success": false,
"code": "VALIDATION_ERROR",
"message": "Validation error",
"errors": [
{ "field": "eventName", "message": "Required" }
]
}| Status | Code | Meaning |
|---|---|---|
400 | VALIDATION_ERROR / BAD_REQUEST | Invalid request body or properties |
401 | UNAUTHORIZED | Missing or invalid API key / session cookie |
403 | FORBIDDEN | Workspace event limit reached |
404 | NOT_FOUND | Session not found |
500 | INTERNAL_ERROR | Server error |
POST /api/v1/init_sdk
Initializes an SDK session. Call this once per client before tracking events.
Auth: Authorization: Bearer <apiKey>
Request
POST /api/v1/init_sdk
Authorization: Bearer prj_ak_xxxxxxxxxxxx
Content-Type: application/json
{
"timestamp": 1743878400000,
"device": {
"ip": "203.0.113.42",
"userAgent": "Mozilla/5.0 ...",
"locale": "en-US",
"timezone": "EET"
},
"tracking": {
"ga4": {
"clientId": "717831353.1785147356"
},
"metaPixel": {
"fbp": "fb.1.1753809500123.123456789",
"fbc": "fb.1.1753809500123.IwAR2Qx3AbCdEfGhIjKlMnOpQrStUvWxYz123456789"
}
},
"sdkVersion": "0.5.2"
}| Field | Type | Required | Description |
|---|---|---|---|
timestamp | integer | ✅ | Unix timestamp in milliseconds |
device.ip | string (IPv4) | ✅ | Client IP address |
device.userAgent | string | ✅ | User agent string |
device.locale | string | No | Defaults to "en-US" |
device.timezone | string | No | Defaults to "UTC" |
tracking | object | ✅ | GA4 / Meta Pixel identifiers |
tracking.ga4.clientId | string | ✅ | GA4 client id |
tracking.metaPixel.fbp | string | No | Meta _fbp cookie |
tracking.metaPixel.fbc | string | No | Meta _fbc / constructed from fbclid |
sdkVersion | string | ✅ | Semver, e.g. "0.5.2" |
Response
{
"success": true,
"message": "SDK initialized successfully",
"data": { "sessionId": "550e8400-e29b-41d4-a716-446655440000" }
}The response also sets a sdk_session cookie with the session ID.
POST /api/v1/identify
Associates session context with the current session. At least one field is required. Omitted values default to "anonymous" for userId and "unknown" for appVersion in subsequent events.
Auth: Cookie sdk_session
Request
POST /api/v1/identify
Cookie: sdk_session=550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"userId": "usr_7f3a9b2c",
"appVersion": "2.4.1"
}| Field | Type | Required | Description |
|---|---|---|---|
userId | string | * | Anonymous user identifier from your system. Defaults to "anonymous" in events if omitted |
appVersion | string | * | Application version (e.g. "2.4.1"). Defaults to "unknown" in events if omitted |
* At least one of userId or appVersion must be provided.
Response
{
"success": true,
"message": "User identified successfully",
"data": { "userId": "usr_7f3a9b2c", "appVersion": "2.4.1" }
}POST /api/v1/track_event
Tracks a single event.
Auth: Cookie sdk_session
Request
Every event shares these base fields:
| Field | Type | Required | Description |
|---|---|---|---|
eventName | string | ✅ | Reserved name or any custom string |
eventId | string | ✅ | Unique event ID (UUID recommended) |
timestamp | integer | ✅ | Unix timestamp in milliseconds |
page | object | No | Page context: title, name, url, referrer |
properties | object | ✅ | Always an object; use {} when there are no parameters |
Example — page view:
POST /api/v1/track_event
Cookie: sdk_session=550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"eventName": "page",
"eventId": "660e8400-e29b-41d4-a716-446655440001",
"timestamp": 1710512520000,
"page": {
"title": "Pricing",
"url": "https://example.com/pricing"
},
"properties": {
"url": "https://example.com/pricing",
"referrer": "https://google.com"
}
}Example — order completed:
POST /api/v1/track_event
Cookie: sdk_session=550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"eventName": "order_completed",
"eventId": "770e8400-e29b-41d4-a716-446655440002",
"timestamp": 1710512580000,
"properties": {
"orderId": "ord_123",
"total": 49.90,
"currency": "USD",
"items": [
{
"productId": "prod_456",
"name": "Widget",
"price": 49.90,
"quantity": 1
}
]
}
}Example — custom event:
{
"eventName": "promo_banner_click",
"eventId": "880e8400-e29b-41d4-a716-446655440003",
"timestamp": 1710512600000,
"properties": { "slot": "hero" }
}Reserved event names
If eventName matches a reserved name below, properties are validated against that schema. Any other eventName is treated as a custom event (properties is a free-form object, max 50 keys / 3 nesting levels).
eventName | properties | Required fields |
|---|---|---|
page | url?, referrer?, title? | — |
product_viewed | productId, name, category?, price?, currency? | productId, name |
product_added | productId, name, price, currency, quantity? | productId, name, price, currency |
product_removed | productId, name, price, quantity? | productId, name, price |
checkout_started | total, currency, items[], orderId?, coupon? | total, currency, items |
payment_info_entered | orderId?, paymentType?, total, currency, coupon?, items[] | total, currency, items |
order_completed | orderId, total, currency, items[], coupon?, shipping?, tax? | orderId, total, currency, items |
order_refunded | orderId, items?, total?, currency? | orderId |
signed_up | method? | — |
logged_in | method? | — |
lead_submitted | value?, currency? | — |
searched | query | query |
level_achieved | level | level |
tutorial_completed | success, contentId? | success |
achievement_unlocked | achievementId, description? | achievementId |
spent_credits | contentId, contentType?, amount, currency? | contentId, amount |
ad_impression | adType, revenue? | adType |
ad_clicked | adType | adType |
adType must be one of: banner, interstitial, rewarded_video, native.
ProductItem (used in items arrays)
| Field | Type | Required |
|---|---|---|
productId | string | ✅ |
name | string | ✅ |
price | number | ✅ |
quantity | integer | ✅ |
category | string | No |
brand | string | No |
variant | string | No |
Response
{
"success": true,
"message": "Event tracked successfully",
"data": { "eventId": "770e8400-e29b-41d4-a716-446655440002" }
}Workspace event limits are checked on this endpoint. If the limit is reached, the API returns 403 Forbidden.
POST /api/v1/track_events_batch
Tracks multiple events in a single request.
Auth: Cookie sdk_session
Request
POST /api/v1/track_events_batch
Cookie: sdk_session=550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
{
"data": [
{
"eventName": "page",
"eventId": "880e8400-e29b-41d4-a716-446655440003",
"timestamp": 1710512600000,
"properties": { "url": "/pricing" }
},
{
"eventName": "product_viewed",
"eventId": "990e8400-e29b-41d4-a716-446655440004",
"timestamp": 1710512610000,
"properties": {
"productId": "prod_456",
"name": "Widget",
"price": 49.90,
"currency": "USD"
}
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
data | array | ✅ | Array of event objects (same shape as /track_event), minimum 1 |
Response
{
"success": true,
"message": "Events tracked successfully",
"data": {
"count": 2,
"eventIds": [
"880e8400-e29b-41d4-a716-446655440003",
"990e8400-e29b-41d4-a716-446655440004"
]
}
}Note: Workspace event limits are not checked on batch requests. Use
/track_eventif you need limit enforcement per event.
Property constraints
| Constraint | Value |
|---|---|
| Max nested object depth | 3 |
| Max top-level property keys | 80 |
Typed events may include nested objects and arrays (e.g. items in checkout_started). Exceeding depth or key limits returns 400 Bad Request.
{
"success": false,
"code": "BAD_REQUEST",
"message": "Invalid properties: nested object depth exceeds maximum of 3.",
"errors": [
{ "field": "properties", "message": "Nested object depth exceeds maximum of 3" }
]
}Limits summary
| Limit | Value |
|---|---|
| Min events per batch | 1 |
| Max events per batch | Not enforced by API |
| Property nesting depth | 3 |
| Top-level property keys | 80 |
| Workspace event limit | Enforced on /track_event only |