Event feed & parity

Consumers read the global append-only feed, page it with a cursor, and reconcile against what they emitted. Delivery is at-least-once and a late merge can repoint an event's customerId, so consumers key on eventId and make processing idempotent. All read endpoints take the read scope (global) or read:own (own source only).


GET/v1/events/feed

The feed

GET /v1/events/feed serves the append-only stream in two modes:

  • Ascending (default), by ingestion id. Pass afterId (exclusive) and persist the returned nextAfterId as your own cursor. There is no server-side consumer offset.
  • Descending, by occurred time. Pass order=desc for newest-first browsing. Page older by passing both nextBeforeOccurredAt and nextBeforeId back as beforeOccurredAt and beforeId (a keyset cursor).

Query params: afterId (int >= 0, default 0), beforeId (int >= 1), beforeOccurredAt (ISO-8601), order (asc or desc, default asc), limit (1..1000, default 200), types (csv), source (string).

A read:own key is confined to its own source: source is forced to the caller's callerId, and a different requested source returns 403.

Request

GET
/v1/events/feed
curl "https://c360-api.lioncapventures.com/v1/events/feed?afterId=0&limit=200&types=order.paid,billpay.completed" \
  -H "X-API-Key: $C360_API_KEY"

Response (ascending)

{
  "success": true,
  "data": {
    "events": [
      {
        "id": 1234,
        "publicId": "evt_9f2c...",
        "source": "smilemall",
        "eventId": "mall-order-paid-ord_abc123",
        "type": "order.paid",
        "schemaVersion": 1,
        "occurredAt": "2026-08-10T09:15:00.000Z",
        "receivedAt": "2026-08-10T09:15:02.114Z",
        "customerId": "cus_a1b2c3",
        "zbIdSubject": "b1e5c8a0-...",
        "identity": { "platform": "smilemall", "userId": "42" },
        "payload": { "orderId": "ord_abc123", "subtotal": "40.00" }
      }
    ],
    "nextAfterId": 1234,
    "hasMore": true,
    "count": 200
  }
}

Response (order=desc)

{
  "success": true,
  "data": {
    "events": [ /* ... newest first by occurredAt ... */ ],
    "nextBeforeOccurredAt": "2026-08-10T08:59:00.000Z",
    "nextBeforeId": 1180,
    "hasMore": true,
    "count": 200
  }
}

GET/v1/events/{publicId}

A single event

GET /v1/events/{publicId} returns one event by its publicId. An unknown id returns 404 with { "detail": "Event not found" }.

For a read:own key, an event outside the caller's own source also returns 404 (not 403), so a partner never even learns another source's events exist.

Request

GET
/v1/events/{publicId}
curl https://c360-api.lioncapventures.com/v1/events/evt_9f2c... \
  -H "X-API-Key: $C360_API_KEY"

GET/v1/events/counts

Counts

GET /v1/events/counts returns event counts by type in one aggregate, the cheap cross-check for "did my N events land". Query params: source, types (csv), fromOccurredAt, toOccurredAt (an inclusive ISO-8601 window).

A read:own key is confined to its own source, and a different requested source returns 403.

Request

GET
/v1/events/counts
curl "https://c360-api.lioncapventures.com/v1/events/counts?fromOccurredAt=2026-08-10T00:00:00Z" \
  -H "X-API-Key: $C360_API_KEY"

Response (200)

{
  "success": true,
  "data": {
    "counts": { "order.paid": 120, "billpay.completed": 87 },
    "total": 207
  }
}

POST/v1/events/exists

Parity and repair

Producers reconcile what they emitted against what Customer 360 stored, then re-emit any gaps. Because ingest is idempotent on (source, eventId), this is always safe: a re-emit of an already-stored event is a duplicate no-op.

POST /v1/events/exists probes a batch of producer eventIds and splits them into present and missing. eventIds is 1 to 2000 ids, each 1 to 120 chars. source defaults to the caller's callerId, so a producer only ever reconciles its own dedupe scope. Re-emit the missing ids with the same stable eventIds.

A read:own key ignores any source in the body and always checks its own source. Pair exists with counts above for a complete "did everything land" reconciliation.

Request

POST
/v1/events/exists
curl -X POST https://c360-api.lioncapventures.com/v1/events/exists \
  -H "X-API-Key: $C360_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "eventIds": [
      "mall-order-paid-ord_a",
      "mall-order-paid-ord_b"
    ]
  }'

Response (200)

{
  "success": true,
  "data": {
    "present": ["mall-order-paid-ord_a"],
    "missing": ["mall-order-paid-ord_b"]
  }
}

Was this page helpful?