ingestlayer/docs/v0.4

docs · 02 concepts

Events.

The unit. Every event that crosses the gate gets one row: a stable ID, a type you control, an arbitrary JSON payload, and the source it came from. Stored once, immutable after.

The shape

Five fields you'll see everywhere.

one event · as stored↵ copy
{
  "id":          "evt_01HZK4...",
  "type":        "user.signup",
  "received_at": "2026-05-21T14:03:11.512Z",
  "source_id":   "src_01HZK3...",
  "payload": {
    "email": "ada@example.com",
    "plan":  "growth",
    "utm":   { "source": "twitter", "campaign": "launch" }
  }
}

type is your namespace — pick a convention (order.placed, user.signup, support.ticket.opened) and stick to it. Pipelines match on this string; filter and transform branches read it via $event.type.

Durability

A 202 means it's safe.

When the ingest call returns 202, your event is durable — it will be processed, even if our downstream systems hiccup in the next second. You don't need to retry on success; you don't need to keep a local copy "just in case." That's the contract.

The SDK throws on anything that isn't a 202; treat the throw as "not yet accepted" and retry.

Idempotency

Send the same event twice, safely.

Pass an idempotencyKey in your ingest call (SDK) or as a body field (HTTP). If we see the same key within the dedupe window, the second send is a no-op — same response, no duplicate row. Retries are free; deliberate replays cost.

Reading them back

Three places.

The dashboard's /events page is the live tail. /events/{id} shows a single event plus every delivery that fanned out from it. Pipelines themselves read events through $event.payload.<path> — see templates.


build a pipelineback to docsnext: sources