API Documentation

Reference docs for events ingestion, identity, and integration patterns.

Events API v2

Compatibility disposition review — 2026-09-05: this retained contract advertises a legacy-input Sunset: 2026-09-01; the cited changelog does not record whether removal occurred, was extended, or was abandoned. That disposition is unresolved here. The responsible API maintainer must reconcile an exact server release and compatibility tests before asserting support/removal or changing clients. No endpoint was exercised by this review. Other v2 contract sections are not blanket-superseded by this uncertainty; see the docs map.

v2 supports custom events and batch ingestion.

Event naming

Events use a two-part naming scheme:

  • event_type — entity noun (e.g. project, invite, billing)
  • action — verb describing what happened (e.g. created, sent, invoice_paid)

Both fields use snake_case: pattern ^[a-z][a-z0-9_]*$

Preferred format (recommended)

Send event_type and action as separate fields:

event_type action canonical_name
project created project_created
invite sent invite_sent
checkout abandoned checkout_abandoned
billing invoice_paid billing_invoice_paid

Unified event format (new)

Send a single event string. The server auto-splits it into event_type and action using the first separator found (dot, colon, or underscore):

event event_type action
user.signed_up user signed_up
billing:invoice_paid billing invoice_paid
project_created project created

No deprecation headers are returned for this format.

Legacy format (deprecated)

The pre-sunset contract accepts a flat event_type string without action for backward compatibility and auto-splits it (e.g. project_created → event_type: "project", action: "created"). Continued acceptance after the advertised date is not established by this note.

Documented pre-sunset legacy response headers:

  • Deprecation: true
  • Sunset: 2026-09-01

Single event endpoint

POST /api/v2/events

Accepts:

  • event — unified event name with separator (one of event/event_type required)
  • event_type — entity noun (one of event/event_type required)
  • action — verb (omit for unified or legacy flat format)
  • subject_type (user, account, subscription)
  • subject_id
  • occurred_at
  • properties (object)
  • metadata (alias of properties)
  • external_id (idempotency key)

Example (preferred format)

bash
curl -X POST "/api/v2/events" \
  -H "Authorization: Bearer YOUR_EVENTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event_type": "project",
    "action": "created",
    "subject_type": "user",
    "subject_id": "user_123",
    "occurred_at": "2026-02-10T12:00:00Z",
    "properties": {
      "workspace_id": "ws_1",
      "template": "kanban"
    }
  }'

Response:

json
{
  "data": {
    "uuid": "evt_abc123",
    "event_type": "project",
    "action": "created",
    "canonical_name": "project_created",
    "source": "api",
    "subject_type": "user",
    "subject_id": "user_123",
    "occurred_at": "2026-02-10T12:00:00Z",
    "external_id": null
  }
}

Example (unified event format)

bash
curl -X POST "/api/v2/events" \
  -H "Authorization: Bearer YOUR_EVENTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event": "user.signed_up",
    "subject_type": "user",
    "subject_id": "user_123",
    "occurred_at": "2026-02-10T12:00:00Z",
    "properties": {
      "source": "organic",
      "plan": "free"
    }
  }'

Batch endpoint

POST /api/v2/events/batch

Use this for higher throughput and fewer network round-trips.

Example

bash
curl -X POST "/api/v2/events/batch" \
  -H "Authorization: Bearer YOUR_EVENTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event_type": "invite",
        "action": "sent",
        "subject_type": "user",
        "subject_id": "user_1",
        "occurred_at": "2026-02-10T12:00:00Z",
        "external_id": "evt_1",
        "properties": { "channel": "email" }
      },
      {
        "event_type": "invite",
        "action": "accepted",
        "subject_type": "user",
        "subject_id": "user_2",
        "occurred_at": "2026-02-10T12:00:10Z",
        "external_id": "evt_2",
        "properties": { "channel": "email" }
      }
    ]
  }'

Example (batch with unified event format)

bash
curl -X POST "/api/v2/events/batch" \
  -H "Authorization: Bearer YOUR_EVENTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event": "feature.enabled",
        "subject_type": "user",
        "subject_id": "user_1",
        "occurred_at": "2026-02-10T12:00:00Z"
      },
      {
        "event": "feature.disabled",
        "subject_type": "user",
        "subject_id": "user_2",
        "occurred_at": "2026-02-10T12:00:10Z"
      }
    ]
  }'

Idempotency

Use external_id to safely retry requests.

Deduplication is scoped by:

  • product
  • source
  • external_id