Skip to content

Events and retries

Assign a stable key to each product occurrence, such as lesson:completion-42. Reuse it after a timeout or connection failure. Do not generate a new key for every network attempt.

Keys are at most 200 characters and use letters, numbers, ., _, :, and -. Event types are at most 120 characters. An event type must exist in the released configuration.

occurred_at is an RFC 3339 timestamp. Supply local_date in YYYY-MM-DD form for the occurrence’s local day. The server SDK accepts a Date through occurredAt and serializes it for you.

Metadata has limits: 16 KiB serialized JSON, eight nesting levels, and 100 object keys. Event write bodies are limited to 256 KiB. Direct batch requests contain at most 100 events; the server facade chunks larger arrays.

A successful server track() call is committed. A rejected single event throws with a stable rejection code in its response body.

Batch responses include accepted and rejected counts and per-event results. Always inspect the results even when the HTTP request succeeds. Cooldowns, caps, unknown events, and conflicting keys can reject individual events.

import { StreaklineApiError } from "@streakline/sdk";
try {
await streakline.track(userId, "lesson.completed", {
idempotencyKey: `lesson:${completionId}`,
});
} catch (error) {
if (error instanceof StreaklineApiError) {
console.error(error.status, error.responseBody);
// Decide whether to retry based on status AND the rejection code.
}
throw error;
}
Status Typical meaning Next action
400 / 422 Invalid event or payload Inspect and fix the rejection
401 Invalid or expired credential Obtain a valid credential
403 Insufficient scope or access Check the credential’s permissions
409 Conflicting idempotency-key reuse Check the original occurrence and payload
410 User erased Stop sending events for that identity
413 Payload too large Reduce or split the payload
429 Rate limit, cooldown, or daily cap Inspect the response code before retrying
5xx Server failure Retry with the same key and bounded backoff

StreaklineApiError.retryable is true for 408, 429, and 5xx responses. It is a transport-level hint: a daily-cap rejection should not become an endless retry loop. Network and timeout errors can be native fetch errors rather than StreaklineApiError. The server facade does not automatically retry your calls.

Web and React Native clients retain queued events across transient failures when you supply persistent storage. On an event-validation HTTP response (400, 413, or 422), they split the batch to isolate invalid events. Valid siblings continue flushing; invalid singletons move to quarantine.

Quarantine retains up to 200 records for 48 hours. Authentication failures stay queued instead of being quarantined. Read the client snapshots for diagnostics:

const lastFailure = streakline.getLastFlushErrorSnapshot();
const invalidEvents = streakline.getQuarantinedEventsSnapshot();

A successful flush clears the last failure. Clearing user data also clears that user’s queue and quarantine.