Ingest one or a batch of tracking events
Primary event-collection endpoint. Accepts a single event object, a bare array of events, or a { "events": [...] } wrapper. Batch size is capped at 100 events (over → 400).
Auth (X-API-Key header, or ?_ak=<key> / ?key=<key> query params — the query forms exist only for navigator.sendBeacon() where headers cannot be set). No explicit scope gate on this route beyond a valid project key.
Validation modes (resolved: key-level validationMode > project settings.ingestValidation.mode > warn): off = no validation; warn = validate but accept; enforce = reject schema-violating events. Only property-schema errors (not envelope warnings like a missing visitorId) cause enforce rejection.
Response mode:
- default → 202
{ accepted, failed, queued, processed:false, invalid? }— events validated and dispatched intoctx.waitUntil; persistence is async and NOT proven. Do not treat 202 as durable persistence. ?sync=1orX-Trackly-Sync: 1→ 200{ accepted, failed, queued, processed:true, errors?, enforceRejected? }— non-metering events reached D1 + Analytics Engine before the response. For debugging/health checks only.- enforce mode + all events rejected (sync path) → 422.
Metering (conversion) events are enqueued synchronously to the metering ingest queue before any response; a missing queue binding or a send failure yields 503. ?debug=1 (or a per-event _debug flag) captures samples into DebugView.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”1 forces synchronous processing (200 with processed:true). Equivalent to the X-Trackly-Sync: 1 header.
When truthy, invalid/accepted event samples are captured into DebugView for the project (best-effort; never affects ingest outcome).
API key fallback (sendBeacon). Prefer the X-API-Key header.
API key fallback (lowest precedence). Prefer the X-API-Key header.
Header Parameters
Section titled “Header Parameters”1 forces synchronous processing (same effect as ?sync=1).
Request Bodyrequired
Section titled “Request Bodyrequired”A single event object, a bare array of events, or a { "events": [...] } wrapper. Max 100 events per request.
A single tracking event. eventName is required; everything else is optional. Every field accepts both camelCase and snake_case aliases (e.g. visitorId/visitor_id). Unknown top-level keys are preserved as part of the raw envelope, except the internal derived-event provenance fields (source, derivedRuleId, derivationDepth) which are hard-stripped from external payloads.
object
Event name (aliases event / event_name). Envelope validation expects ^[a-z0-9_]{1,100}$; a non-matching name is a warn-level error (still processed). A missing eventName marks the event invalid.
Device/browser-level ID (alias visitor_id). Defaults to "anon" if omitted (warn-level).
Logged-in user ID (alias user_id).
Session ID (alias session_id). Tier-1 attribution key.
Custom key-value payload. Monetary amounts go in amount (or value) in minor units (cents). currency defaults to CNY. Max ~32 KB serialized (warn-level properties_too_large over the limit).
object
Event time, ISO 8601 (aliases client_timestamp / timestamp). Unparseable values are a warn-level error.
Optional client-supplied idempotency/dedup key (alias event_id). Must match ^[A-Za-z0-9_.-]{8,64}$; otherwise it is ignored (with a warning) and the server generates one. REQUIRED for metering events on the backfill endpoint.
Short-link ID for explicit attribution (alias short_link_id).
Short code for direct-landing attribution (aliases _tk / short_link_code).
Recommended unified Click ID map covering all 29 ad platforms, e.g. { "bd_vid": "...", "gclid": "..." }. Alternatives: a top-level click_id, or legacy strongly-typed top-level fields (bdVid, gclid, fbclid, … — cover only the earlier ~15 platforms).
object
Full page URL; Click IDs are auto-extracted from its query string.
Alias utm_source
Alias utm_medium
Alias utm_campaign
Alias utm_term
Alias utm_content
A single tracking event. eventName is required; everything else is optional. Every field accepts both camelCase and snake_case aliases (e.g. visitorId/visitor_id). Unknown top-level keys are preserved as part of the raw envelope, except the internal derived-event provenance fields (source, derivedRuleId, derivationDepth) which are hard-stripped from external payloads.
object
Event name (aliases event / event_name). Envelope validation expects ^[a-z0-9_]{1,100}$; a non-matching name is a warn-level error (still processed). A missing eventName marks the event invalid.
Device/browser-level ID (alias visitor_id). Defaults to "anon" if omitted (warn-level).
Logged-in user ID (alias user_id).
Session ID (alias session_id). Tier-1 attribution key.
Custom key-value payload. Monetary amounts go in amount (or value) in minor units (cents). currency defaults to CNY. Max ~32 KB serialized (warn-level properties_too_large over the limit).
object
Event time, ISO 8601 (aliases client_timestamp / timestamp). Unparseable values are a warn-level error.
Optional client-supplied idempotency/dedup key (alias event_id). Must match ^[A-Za-z0-9_.-]{8,64}$; otherwise it is ignored (with a warning) and the server generates one. REQUIRED for metering events on the backfill endpoint.
Short-link ID for explicit attribution (alias short_link_id).
Short code for direct-landing attribution (aliases _tk / short_link_code).
Recommended unified Click ID map covering all 29 ad platforms, e.g. { "bd_vid": "...", "gclid": "..." }. Alternatives: a top-level click_id, or legacy strongly-typed top-level fields (bdVid, gclid, fbclid, … — cover only the earlier ~15 platforms).
object
Full page URL; Click IDs are auto-extracted from its query string.
Alias utm_source
Alias utm_medium
Alias utm_campaign
Alias utm_term
Alias utm_content
object
A single tracking event. eventName is required; everything else is optional. Every field accepts both camelCase and snake_case aliases (e.g. visitorId/visitor_id). Unknown top-level keys are preserved as part of the raw envelope, except the internal derived-event provenance fields (source, derivedRuleId, derivationDepth) which are hard-stripped from external payloads.
object
Event name (aliases event / event_name). Envelope validation expects ^[a-z0-9_]{1,100}$; a non-matching name is a warn-level error (still processed). A missing eventName marks the event invalid.
Device/browser-level ID (alias visitor_id). Defaults to "anon" if omitted (warn-level).
Logged-in user ID (alias user_id).
Session ID (alias session_id). Tier-1 attribution key.
Custom key-value payload. Monetary amounts go in amount (or value) in minor units (cents). currency defaults to CNY. Max ~32 KB serialized (warn-level properties_too_large over the limit).
object
Event time, ISO 8601 (aliases client_timestamp / timestamp). Unparseable values are a warn-level error.
Optional client-supplied idempotency/dedup key (alias event_id). Must match ^[A-Za-z0-9_.-]{8,64}$; otherwise it is ignored (with a warning) and the server generates one. REQUIRED for metering events on the backfill endpoint.
Short-link ID for explicit attribution (alias short_link_id).
Short code for direct-landing attribution (aliases _tk / short_link_code).
Recommended unified Click ID map covering all 29 ad platforms, e.g. { "bd_vid": "...", "gclid": "..." }. Alternatives: a top-level click_id, or legacy strongly-typed top-level fields (bdVid, gclid, fbclid, … — cover only the earlier ~15 platforms).
object
Full page URL; Click IDs are auto-extracted from its query string.
Alias utm_source
Alias utm_medium
Alias utm_campaign
Alias utm_term
Alias utm_content
Examples
Single purchase event
{ "eventName": "user_paid", "visitorId": "vid_abc123", "userId": "uid_456", "sessionId": "sess_789", "properties": { "amount": 9900, "currency": "CNY" }, "clickIds": { "bd_vid": "abc", "gclid": "xyz" }}Wrapped batch
{ "events": [ { "eventName": "page_view", "visitorId": "vid_abc123" }, { "eventName": "user_paid", "visitorId": "vid_abc123", "properties": { "amount": 4900 } } ]}Responses
Section titled “Responses”Synchronous result (?sync=1). processed:true proves non-metering events reached D1 + Analytics Engine.
Synchronous (?sync=1) ingest response — also the 422 body in enforce mode.
object
Events written to D1 + Analytics Engine (= total minus enforce-rejected).
Invalid events plus enforce-rejected events.
Metering events enqueued.
Always true on the sync path.
Per-event validation errors (present only when non-empty).
Validation errors for a single event (sync=1 / 422 response).
object
0-based batch index.
Structured validation error (envelope or property-schema).
object
Rule identifier, e.g. type, required, enum, pattern, minimum, maximum, maxLength, or envelope rules like envelope/event_name_format, envelope/visitor_id_missing.
Expected value/constraint (any type).
Actual value/type observed (any type).
Number of events rejected by enforce-mode schema validation (present only when > 0).
Accepted (default async). Events dispatched to background processing; persistence completes after the response and is not guaranteed.
Default 202 async ingest response.
object
Events validated and dispatched to background processing (NOT proof of persistence).
Count of invalid (unparseable / missing eventName) events.
Metering events enqueued to the metering ingest queue.
Always false on the async path.
Present only when there are invalid events.
An event rejected at the envelope/parse layer.
object
0-based position in the incoming batch.
Raw event sample truncated to ≤1KB.
Human-readable rejection reason (e.g. “缺少 eventName 字段”).
Example
{ "accepted": 2, "failed": 0, "queued": 2, "processed": false}Invalid JSON body, or batch exceeds 100 events.
object
Human-readable error message.
Seconds to wait before retrying (present on 429/503).
Examples
{ "error": "无效的 JSON 格式"}{ "error": "单次最多提交 100 个事件"}Missing or invalid API key.
object
Human-readable error message.
Seconds to wait before retrying (present on 429/503).
Examples
{ "error": "缺少 X-API-Key 请求头"}{ "error": "API Key 无效"}Enforce mode and every event was rejected (sync path only).
Synchronous (?sync=1) ingest response — also the 422 body in enforce mode.
object
Events written to D1 + Analytics Engine (= total minus enforce-rejected).
Invalid events plus enforce-rejected events.
Metering events enqueued.
Always true on the sync path.
Per-event validation errors (present only when non-empty).
Validation errors for a single event (sync=1 / 422 response).
object
0-based batch index.
Structured validation error (envelope or property-schema).
object
Rule identifier, e.g. type, required, enum, pattern, minimum, maximum, maxLength, or envelope rules like envelope/event_name_format, envelope/visitor_id_missing.
Expected value/constraint (any type).
Actual value/type observed (any type).
Number of events rejected by enforce-mode schema validation (present only when > 0).
Example
{ "accepted": 0, "failed": 1, "queued": 0, "processed": true, "enforceRejected": 1, "errors": [ { "index": 0, "eventName": "user_paid", "errors": [ { "field": "amount", "rule": "type", "expected": "number", "actual": "string", "message": "Field amount: expected number, got string" } ] } ]}Transient infra failure. SELECTOR_LOOKUP_FAILED (retryAfter 30) when the metering-selector lookup fails; QUEUE_UNAVAILABLE (retryAfter 60) when metering events are present but the queue binding is absent or the enqueue send failed.
503 transient error with a suggested retry delay.
object
Suggested seconds to wait before retrying (30 or 60).
Examples
{ "error": "SELECTOR_LOOKUP_FAILED", "retryAfter": 30}{ "error": "QUEUE_UNAVAILABLE", "retryAfter": 60}