> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vibefollow.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Release notes for `@vibefollow/sdk` and the public API.

Semver. Major versions are breaking; minor are additive; patch are bug fixes and metadata.

<Info>
  The SDK version is exported as `SDK_VERSION` and flows into the `User-Agent` header on every request — the backend can flag outdated clients.
</Info>

<Tabs>
  <Tab title="latest">
    ```bash theme={null}
    npm install @vibefollow/sdk@latest
    ```
  </Tab>

  <Tab title="beta">
    ```bash theme={null}
    npm install @vibefollow/sdk@beta
    ```
  </Tab>
</Tabs>

<Note>
  This page mirrors `packages/sdk/CHANGELOG.md` — the npm package's `CHANGELOG.md` is the canonical record.
</Note>

<Update label="1.4.0" description="2026-06-08 — `trial_expiring` property fix + 10-event doc consistency + Stripe import guide">
  **Changed**

  * **Breaking:** [`users.trialExpiring(userId, { trialDays })`](/sdk/resources/users) — the property was renamed from `daysLeft` to `trialDays`. The live `trial_expiring` trigger reads `properties.trialDays`; the previous `daysLeft` was silently ignored, so the helper never actually drove the trigger. TypeScript callers passing `{ daysLeft }` get a compile error and must rename to `{ trialDays }`. In practice you rarely need this helper — the trigger is derived automatically from the most recent `trial_started` event's `trialDays`, so calling `trialStarted(userId, { trialDays })` once is enough.

  **Fixed**

  * The README and an internal `events.ts` comment described "canonical **9**" lifecycle events; corrected to **10** to match `package.json` and `STANDARD_EVENT_NAMES`. (The 10th helper, `usageThresholdReached`, shipped in 1.2.0; the prose lagged.)

  **Added**

  * "Importing existing customers from Stripe": founders with billing in Stripe can paste a read-only restricted key in the dashboard (**Import → Stripe**) for a one-time backfill of customers and subscription/invoice history as canonical lifecycle events, with welcome emails suppressed — a dashboard integration, not an SDK call.

  **Note**

  This property rename is technically a SemVer-major change. It ships as a minor because `2.0.0` is reserved for removing the deprecated `AIFollowups` alias, and the break is confined to one rarely-used helper (flagged above).
</Update>

<Update label="1.3.0" description="2026-05-28 — `suppressTriggers` flag on `events.batch()`">
  **Added**

  * [`events.batch({ suppressTriggers: true })`](/sdk/resources/events#batch-options) — opt-in trigger suppression for historical seeding. Every `TrackedUser` touched by a suppressed batch gets `suppressTriggersUntil` set to a far-future date server-side, so trigger rules (welcome, onboarding\_stall, etc.) won't fire retroactively when you're migrating customers into Vibefollow from an existing user base. The watermark dissolves automatically the first time the user emits a normal (non-suppressed) event — one-batch switch back to live mode.
  * [`POST /api/v1/events/batch`](/api-reference/events/batch) request body now documents the optional `suppressTriggers` field with a "seeding historical users" cURL example.

  **Why**

  Founders importing an existing user base were occasionally shipping retroactive "welcome" emails to customers who'd signed up months earlier — a real production incident on 2026-05-27 with one customer sending 145+ welcomes from a backfill. The CSV import path has the same semantic via `fire_welcome_emails: false`; this brings the realtime API in line.

  **Backwards compatibility**

  Fully additive. Calling `events.batch()` with no options (or with the prior `{ maxSize, maxAgeMs }` shape) sends `suppressTriggers: false` and behaves identically to 1.2.x. The server defaults missing field values to `false`, so older SDK versions remain compatible.
</Update>

<Update label="1.2.1" description="2026-05-25 — npm description + keywords cover the 10th helper">
  **Changed**

  * `package.json` `description` now explicitly names the 10 typed lifecycle helpers, the `chunk()` utility, automatic retries, the typed error hierarchy, and edge-runtime support. The previous wording understated v1.2.0 by stopping at "identify users, emit lifecycle events, bulk-backfill from existing data, and verify webhook signatures" — accurate but missing half the surface a discovery search would care about.
  * `keywords` extended with `webhooks`, `ai`, `claude`, `revenue-manager` for npm discovery.

  **Backwards compatibility**

  Metadata-only release. No runtime behaviour changes, no API changes, no type changes. The `User-Agent` header bumps from `vibefollow-sdk/1.2.0` → `vibefollow-sdk/1.2.1` so backend logs reflect the new patch.
</Update>

<Update label="1.2.0" description="2026-05-22 — bulk endpoints + chunk() helper for backfills">
  **Added**

  * [`users.identifyBulk(records)`](/sdk/resources/users#identifybulk-records) — upsert up to 1,000 users in one POST. Returns `BulkIngestResponse` with per-record validation errors so a single bad row never sinks the batch. Idempotent via the existing `(project_id, external_user_id)` unique on `tracked_users`; chunks that 429 or 5xx are safe to retry.
  * [`events.bulk(records)`](/sdk/resources/events#bulk-records) — same shape for events. Idempotent via the server-side `events_dedupe_unique` partial index; reimporting the same backfill twice is a no-op.
  * [`chunk(input, size)`](/sdk/types#chunk-input-size) — exported generator that slices large arrays into ≤size slices for backfills > 1,000 records. Doesn't materialise the source twice, so 5M-row backfills stay flat-memory.
  * New bulk types: `BulkUserRecord`, `BulkEventRecord`, `BulkIngestError`, `BulkIngestResponse`, plus the `BULK_INGEST_MAX_RECORDS = 1000` constant.
  * New API reference pages: [`POST /api/v1/users/bulk`](/api-reference/users/bulk) and [`POST /api/v1/events/bulk`](/api-reference/events/bulk).

  **Why**

  The two SDK paths that existed before — per-record `identify()` / `track()` for live writes and `events.batch()`'s in-memory buffer for high-volume streaming — both made backfills awkward. Bulk closes the gap: one POST per 1,000 records, partial-success error reporting, and `chunk()` so a 50k backfill is a 50-iteration `for` loop with predictable memory.

  **Backwards compatibility**

  Fully additive. The legacy `events.batch()` in-memory buffer and the `/api/v1/events/batch` endpoint behind it remain supported.
</Update>

<Update label="1.1.0" description="2026-05-19 — usage_threshold_reached canonical event">
  **Added**

  * `users.usageThresholdReached(userId, { usagePercent, meter?, limit? })` — 10th typed lifecycle helper. Emits `usage_threshold_reached`, the canonical event consumed by the backend's `plan_limit_upsell` trigger rule.
  * `STANDARD_EVENT_NAMES` now contains 10 entries (was 9); `StandardEventName` type updated transparently.
</Update>

<Update label="1.0.2" description="2026-05-18 — homepage repointed to docs site">
  **Changed**

  * `package.json` `homepage` repointed from `https://vibefollow.com` to `https://docs.vibefollow.com/sdk/overview` now that the docs site is live. `bugs.url` remains `https://vibefollow.com` until the `support@vibefollow.com` mailbox is provisioned.
</Update>

<Update label="1.0.1" description="2026-05-17 — metadata + prose casing fix">
  **Fixed**

  * `package.json` `description` brand casing: `VibeFollow` → `Vibefollow` (the SDK class identifier `VibeFollow` stays unchanged; only marketing prose was corrected).
  * `package.json` `homepage` was `https://docs.vibefollow.com/sdk` (DNS unresolvable at publish time) — now `https://vibefollow.com`.
  * Explicit `bugs.url` pointing at `https://vibefollow.com` so npm's auto-derivation no longer produces a `gitlab.com/.../issues` URL that leads to a sign-in wall.
  * README prose now uses `Vibefollow` consistently; code identifiers, env var names, and class names are unchanged.
  * Header literal corrected from `X-VibeFollow-Signature` to `X-Vibefollow-Signature` to match what the emission backend actually sends. HTTP headers are case-insensitive on read, so this is a documentation correction — verification continues to work for clients on `1.0.0`.
</Update>

<Update label="1.0.0" description="2026-05-17 — initial public release">
  **Added**

  * `VibeFollow` class with `users`, `events`, and `webhooks` resources.
  * 9 typed lifecycle helpers on `vf.users.*` (`signedUp`, `trialStarted`, …).
  * `events.track()` for custom events and `events.batch()` for buffered emission.
  * `webhooks.constructEvent()` for signed delivery verification.
  * Typed error hierarchy: `AuthError`, `ValidationError`, `RateLimitError`, `ServerError`, `NetworkError`, `WebhookSignatureError`.
  * Auto-retry with exponential backoff plus jitter on transient failures.
  * Auto-`Idempotency-Key` on every POST.
  * Edge-runtime support: Node 20+, Cloudflare Workers (with `nodejs_compat`), Vercel Edge, Deno.

  **Endpoints documented**

  * `POST /api/v1/users` — upsert user
  * `POST /api/v1/events` — track event
  * `POST /api/v1/events/batch` — batch track events
</Update>
