Backfills and usage corrections

By default, Schematic stamps every event with the time it was received. Two optional flags on the track-event payload let you override that and submit an event with the time it actually happened:

  • trusted_client_clock — use the client-provided sent_at as the event’s effective timestamp. Billing side effects still fire (against the logical timestamp). Best for correcting recent usage that arrived late or with a bad timestamp.
  • backfill — analytics-only mode for importing historical usage. Events are stored at their logical time but skip all billing side effects.

Both flags require a secret API key (sch_ prefix) and a sent_at value on the event. See Authentication for key types.

When to use which mode

You want to…Use
Record usage that just happened (normal flow)Neither flag — server time is used
Correct an event that happened yesterday or earlier today, including billing impacttrusted_client_clock
Import months of historical usage for analytics, without re-billing customersbackfill

trusted_client_clock

When true, Schematic uses the sent_at you provide as the event’s effective timestamp (captured_at) instead of server receipt time.

Requirements for setting sent_at:

  • No more than 5 minutes in the future
  • No more than 34 days in the past

The 34-day past bound sits one day inside Stripe’s meter-event 35-day cap, to absorb wall-clock skew between Schematic and Stripe. For older events, use backfill.

All normal processing still happens — billing impact, webhooks, and activity updates fire as usual — just anchored to the logical timestamp instead of the receipt time. Feature usage counters only count the event toward periods that the logical timestamp falls within, so an event timestamped yesterday won’t show up in today’s daily counter.

1{
2 "api_key": "sch_secret_...",
3 "type": "track",
4 "sent_at": "2026-05-17T14:30:00Z",
5 "trusted_client_clock": true,
6 "body": {
7 "event": "api-call",
8 "company": { "your-company-key": "value" },
9 "quantity": 50
10 }
11}

backfill

backfill: true implies trusted_client_clocksent_at is the effective timestamp — but all billing side effects are skipped. Use this when you want historical usage to appear in analytics without re-running billing.

Requirements for setting sent_at when backfill: true:

  • No more than 5 minutes in the future
  • No more than 365 days in the past

Skipped:

  • Billing impact (credit consumption, Stripe meter reporting, auto-topup)
  • Webhooks
  • last_seen_at bumps on companies and users (historical events shouldn’t shift present-time activity)

Still happens:

  • The event is stored at its logical timestamp and shows up in analytics there.
  • Feature usage counters reflect the event for periods the logical timestamp falls within.
  • Companies and users referenced by the event are still created or linked from the event keys — their last_seen_at just isn’t touched.
1{
2 "api_key": "sch_secret_...",
3 "type": "track",
4 "sent_at": "2025-10-15T09:00:00Z",
5 "backfill": true,
6 "body": {
7 "event": "api-call",
8 "company": { "your-company-key": "value" },
9 "quantity": 1000
10 }
11}

Behavior matrix

BehaviorNormaltrusted_client_clockbackfill
Effective captured_atserver timesent_atsent_at
Billing impactYes (current time)Yes (logical time)No
WebhooksYesYesNo
Feature usage countersYes (all periods)Period-filteredPeriod-filtered
Company/user create or linkYesYesYes
Company/user last_seen_at bumpYesYesNo

SDK example

1import { SchematicClient } from "@schematichq/schematic-typescript-node";
2
3const client = new SchematicClient({ apiKey: process.env.SCHEMATIC_SECRET_KEY });
4
5// Usage correction: an api-call from yesterday that we missed
6await client.track({
7 event: "api-call",
8 company: { "your-company-key": "value" },
9 quantity: 50,
10 sentAt: new Date("2026-05-17T14:30:00Z"),
11 trustedClientClock: true,
12});
13
14// Historical backfill: import a month-old event for analytics only
15await client.track({
16 event: "api-call",
17 company: { "your-company-key": "value" },
18 quantity: 1000,
19 sentAt: new Date("2025-10-15T09:00:00Z"),
20 backfill: true,
21});

Retention

Events are retained for 365 days, measured from the event’s effective captured_at. A backfill submitted near the 365-day past bound therefore lands with very little remaining retention — by design. Aggregated feature usage is preserved separately on the same logical-period anchor, so usage charts and entitlement counters stay intact even after the underlying event expires.

Validation errors

ConditionError
trusted_client_clock or backfill with a publishable keytrusted_client_clock and backfill require a secret API key
trusted_client_clock or backfill without sent_atsent_at is required when trusted_client_clock or backfill is true
sent_at more than 5 minutes in the futuresent_at cannot be more than 5 minutes in the future
trusted_client_clock with sent_at more than 34 days in the pastsent_at cannot be more than 34 days in the past for trusted_client_clock; for older events use backfill (analytics-only, no billing side effects)
backfill with sent_at more than 365 days in the pastsent_at cannot be more than 365 days in the past