Skip to main content

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.

Vibefollow’s data model is two primitives: users and events.

User

Anyone you want to communicate with. Identify them once with an external ID (your primary key) and a bag of traits.

Event

Something the user did, with optional properties. Events drive audience membership and trigger rules.
You send both from your backend. Everything else — drafting, scheduling, sending, audience matching — is downstream of these two calls.

The contract

// 1. Tell Vibefollow who the user is.
await vf.users.identify('usr_42', {
  email: 'jane@acme.io',
  name: 'Jane Doe',
  plan: 'trial',
});

// 2. Tell Vibefollow what they did.
await vf.users.signedUp('usr_42', { plan: 'trial', source: 'organic' });
Identify and track are independent. You can call track before identify for the same user; the events buffer until the user is seen and are then attached. Re-identifying with the same ID upserts traits in place.

What happens after you send an event

1

Enqueue

The event is enqueued and returns 202 Accepted immediately.
2

Normalise

A background worker normalises it, attaches it to the user, and updates derived state (last-seen timestamp, audience membership flags).
3

Trigger evaluation

The hourly trigger evaluator runs all 8 rule kinds against every user, in case this event newly satisfies one.
4

Draft and send

If a rule matches and the project is in autopilot, a draft is generated, scheduled, and sent at deadline.
Event delivery is fire-and-forget from your side. The 202 confirms enqueue, not processing. If the worker can’t make sense of an event — malformed properties, unknown user — it’s quarantined for review in the dashboard rather than discarded.

Standard vs custom events

Vibefollow ships with 9 canonical lifecycle events — signup, trial started, feature used, etc. These have first-class typed helpers in the SDK and they’re what every default trigger rule looks for. You can also emit any name you want through events.track(). Custom event names are accepted as-is and become usable in audience filters and custom trigger rules.

Lifecycle events

The canonical 9 with typed helpers.

Custom events

events.track() and events.batch().

Idempotency

Every event POST carries an Idempotency-Key header (auto-generated by the SDK). The backend dedupes within a 24-hour window — safe to retry an events.track() call after a network blip without producing duplicate events. The key is a v4 UUID; you can override it by passing Idempotency-Key manually if you’re calling REST directly.

Privacy and data retention

Identify traits are stored in the user’s traits JSON column. PII (email, name) lives in dedicated columns under access control.
Event payloads are stored verbatim in the events table. Don’t put secrets in properties — treat them as data, not as a private channel.
Retention is project-configurable. Default is unlimited; talk to support to set a TTL.