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. See Rate limits for the full 429 contract, including the per-project limit and recommended retry behavior.
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.
bashcurl -X POST https://cohorly-service.velloalabs.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:
json{ "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.
bashcurl -X POST https://cohorly-service.velloalabs.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:
json{ "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).
bashcurl -X POST https://cohorly-service.velloalabs.com/alias \-H "Content-Type: application/json" \-H "X-Cohorly-Token: YOUR_PROJECT_TOKEN" \-d '{ "alias": "anon_abc", "distinct_id": "user_123" }'
Response:
json{ "status": 1 }