GET /v1/projects/:projectId/events
Query the SDK event stream - filtered, paginated, PII-redacted by default.
/v1/projects/:projectId/events- Auth
- Bearer
- Scope
- events:read
Returns events the client SDK posted to in.layers.com/l/events, in reverse-chronological order. Use it to render a live activity feed, debug SDK wiring during install, or export raw telemetry into your own warehouse.
Identifiers that could reveal a user - email, phone, ip, and common PII property keys - are redacted to "[redacted]" by default. Create the key with the events:read+pii sub-scope and Layers returns the raw values. Keys without that sub-scope cannot opt in per-request.
projectIdstringrequiredProject ID.
appIdstringoptionalFilter to a single SDK app.eventNamesstring[]optionalComma-separated event names (e.g. `purchase_success,add_to_cart`). Omitted = all events.userIdstringoptionalFilter to a single `app_user_id`.sincestring (ISO 8601, UTC Z)optionalInclusive lower bound on `occurred_at`.untilstring (ISO 8601, UTC Z)optionalExclusive upper bound on `occurred_at`.cursorstringoptionalOpaque pagination token.limitintegeroptionaldefault: 50Page size, 1–200.
Example request
curl "https://api.layers.com/v1/projects/prj_254a4ce1-f4ca-42b1-9e36-17ca45ef3d39/events?eventNames=purchase_success&since=2026-04-18T00:00:00Z&limit=25" \
-H "Authorization: Bearer lp_..."const { items, nextCursor } = await layers.events.list(
"prj_254a4ce1-f4ca-42b1-9e36-17ca45ef3d39",
{
eventNames: ["purchase_success"],
since: "2026-04-18T00:00:00Z",
limit: 25,
}
);result = layers.events.list(
project_id="prj_254a4ce1-f4ca-42b1-9e36-17ca45ef3d39",
event_names=["purchase_success"],
since="2026-04-18T00:00:00Z",
limit=25,
)Response
receivedAt currently mirrors occurredAt (single-timestamp storage). A future schema bump will track ingest receipt independently for client-skew debugging. Today, treating either field interchangeably is safe.
Big-int identifiers in properties come back as strings. Postgres JSONB stores numbers without precision limits, but JSON's number type cannot represent integers above 2^53 - 1 (9_007_199_254_740_991). Meta ad_ids (17–19 digits) and TikTok event_ids (17-digit Snowflake) routinely exceed that. To prevent silent precision loss, the endpoint stringifies any integer property value outside ±(2^53 − 1) before serializing — so a properties.ad_id you sent as a number will read back as the same digits in a string. Floats (price 4.99, percentile 0.043) and small integers stay numeric. Recommendation: send big-int IDs as strings from the SDK so producer + consumer agree on the type.
{
"items": [
{
"eventId": "evt_01HXA9Z2R3S4T5U6V7W8X9Y0A",
"appId": "sdk_01HXA1NPQR5TVWXYZABCDEFGH",
"userId": "user_a7f3c1d9",
"eventName": "purchase_success",
"occurredAt": "2026-04-18T19:42:08.214Z",
"receivedAt": "2026-04-18T19:42:08.214Z",
"platform": "ios",
"sdkVersion": "1.4.0",
"properties": {
"order_id": "order_81422",
"value": 18.5,
"currency": "USD",
"items": [{ "sku": "latte-12oz", "qty": 2 }]
},
"identity": {
"email": "[redacted]",
"phone": "[redacted]",
"ip": "[redacted]"
}
}
],
"nextCursor": "evt_01HXA9Z1QPONM..."
}Errors
| Status | Code | When |
|---|---|---|
| 422 | VALIDATION | Bad since/until, unknown appId, invalid cursor. |
| 401 | UNAUTHENTICATED | Missing or invalid key. |
| 403 | FORBIDDEN_SCOPE | Key lacks events:read. |
| 404 | NOT_FOUND | Project does not exist. |
| 429 | RATE_LIMITED | Read budget exhausted. |
See also
GET /v1/projects/:projectId/conversions- aggregated rollupGET /v1/projects/:projectId/users/:appUserId/signal- per-user state