Skip to main content
Every Glyph SDK uses the same wire contract and delivery behavior. The options below control queueing, batching, retries, and error reporting.

Client options

JavaScript options are camelCase constructor fields; Python options are snake_case keyword arguments. Defaults are identical everywhere. Platform-specific options — autoFlush on the browser SDK, flushOnExit on the Node SDK — are documented on their SDK pages.

Batching

Messages queue in memory and are sent as JSON to POST /api/v1/ingest with the write key as a bearer token. A single queued message is sent as a bare object; multiple messages are wrapped in { "batch": [...] }. Batches are capped at 100 messages — a larger queue drains in successive requests. Each message includes an SDK-generated UUID in messageId. The value stays the same across retries, allowing the server to deduplicate a repeated delivery.

Timestamps

Without a timestamp, the SDK uses the call time in UTC with millisecond precision (2026-06-05T00:00:00.000Z). A JavaScript Date or Python datetime is serialized in the same format. Strings and numbers (epoch milliseconds) pass through unchanged for historical imports.

Validation

SDK methods validate input before queueing and throw TypeError for:
  • userId, event, and groupId must be non-empty strings of at most 256 characters.
  • profile traits must include a non-empty email.
  • page names, when provided, follow the same rules.
Traits and properties must be JSON-serializable objects. Use strings, numbers, booleans, null, arrays, and nested objects. Do not send functions, undefined, BigInt, class instances, or circular references. The complete method shapes are listed in Message model.

Retries

A delivery attempt that fails with a retryable status — 408, 429, 500, 502, 503, 504 — or a network error is retried up to maxRetries times with exponential backoff: 500 ms base, doubling per attempt, capped at 30 s, with jitter. A Retry-After header on a retryable response is honored. Non-retryable statuses (for example 401 from a revoked write key, or 422 from an invalid payload) fail immediately without retrying. The server responds after the transaction commits. If a request times out after committing, a retry sends the same messageId and the server deduplicates it.

Rate limits

Each write key has an ingest budget of 600 messages per 60-second sliding window by default; some plans have a higher limit. The budget counts messages, not requests. A 429 response includes Retry-After and is retryable. If maxRetries is exhausted, the SDK returns the batch to the queue for the next flush. Pace sustained sends such as backfills below the limit.

Error handling

When a batch exhausts its retries or encounters a non-retryable failure, the error callback receives the error, affected messages, and delivery context:
What happens to the batch depends on whether the failure was retryable:
  • Retryable (server errors, timeouts, network failures) — the batch goes back on the queue and is attempted again on the next flush. Nothing is lost while the process lives.
  • Non-retryable (auth or validation failures) — the batch is dropped after onError is called. The callback is your only chance to log or persist it.
HTTP delivery failures are reported through the error callback rather than thrown from track/profile/group/page. Input validation and serialization errors are programming errors and may still throw at the call site or during an explicit flush.