CohorlyDocs
GitHub

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

LimitValueOn exceed
Batch size500 records per request400 batch too large
Rate limit (per IP)100 requests / 10 seconds429 rate limited
Request body1 MB413

The rate limit applies to /track and /engage.

POST /track

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.

bash
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:

FieldRequiredNotes
distinct_idYesWho the event belongs to.
timeNoUnix milliseconds. Defaults to server receipt time.
$insert_idNoIdempotency key for deduplication.
tokenNoPer-event project token; overrides the header, stripped before storage.
...customNoAny other properties are stored as JSON.

Response:

json
{ "status": 1, "inserted": 2 }

POST /engage

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.

bash
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 }
  }'
VerbTypeEffect
$setobjectSet properties, overwriting existing values.
$set_onceobjectSet properties only if not already present.
$addobject of numbersIncrement numeric properties.
$unsetstring[]Remove the named properties.
$deletebooleanDelete the entire profile.

Response:

json
{ "status": 1, "applied": 1 }

POST /alias

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).

bash
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:

json
{ "status": 1 }