Ingestion API
The ingestion endpoints are what the SDKs call to send data. They are authenticated by a project token, not the admin key. Send the token in the X-Cohorly-Token header (applies to the whole batch) or per record (which wins over the header).
Authentication
Pass your project token via the X-Cohorly-Token header. An unknown or missing token returns 401 with { "status": 0, "error": "invalid token" }. Per-record tokens (properties.token on /track, the token field on /engage and /alias) override the header and are stripped before storage.
Limits
| Limit | Value | On exceed |
|---|---|---|
| Batch size | 500 records per request | 400 batch too large |
| Rate limit (per IP) | 100 requests / 10 seconds | 429 rate limited |
| Request body | 1 MB | 413 |
The rate limit applies to /track and /engage.
POST /track
Record one event or an array of events (max 500). The body is a single event object or an array of them. Each event needs an event name and a properties object containing at least distinct_id.
curl -X POST https://api.cohorly.com/track \
-H "Content-Type: application/json" \
-H "X-Cohorly-Token: YOUR_PROJECT_TOKEN" \
-d '[
{
"event": "Signed Up",
"properties": { "distinct_id": "user_123", "plan": "pro" }
},
{
"event": "Page Viewed",
"properties": {
"distinct_id": "user_123",
"time": 1751600000000,
"$insert_id": "b1f2c3d4-...",
"path": "/pricing"
}
}
]'Fields inside each event's properties:
| Field | Required | Notes |
|---|---|---|
distinct_id | Yes | Who the event belongs to. |
time | No | Unix milliseconds. Defaults to server receipt time. |
$insert_id | No | Idempotency key for deduplication. |
token | No | Per-event project token; overrides the header, stripped before storage. |
| ...custom | No | Any other properties are stored as JSON. |
Response:
{ "status": 1, "inserted": 2 }POST /engage
Update user profiles. Body is a single operation or an array. Each operation targets a distinct_id and carries one or more of the profile update verbs.
curl -X POST https://api.cohorly.com/engage \
-H "Content-Type: application/json" \
-H "X-Cohorly-Token: YOUR_PROJECT_TOKEN" \
-d '{
"distinct_id": "user_123",
"$set": { "name": "Ada Lovelace", "plan": "pro" },
"$add": { "logins": 1 }
}'| Verb | Type | Effect |
|---|---|---|
$set | object | Set properties, overwriting existing values. |
$set_once | object | Set properties only if not already present. |
$add | object of numbers | Increment numeric properties. |
$unset | string[] | Remove the named properties. |
$delete | boolean | Delete the entire profile. |
Response:
{ "status": 1, "applied": 1 }POST /alias
Link an anonymous id to a known id so activity from both merges into one profile. Both alias and distinct_id are required (else 400).
curl -X POST https://api.cohorly.com/alias \
-H "Content-Type: application/json" \
-H "X-Cohorly-Token: YOUR_PROJECT_TOKEN" \
-d '{ "alias": "anon_abc", "distinct_id": "user_123" }'Response:
{ "status": 1 }