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.

The Vibefollow API is a small, JSON-over-HTTPS surface. The TypeScript SDK wraps it — everything documented here is what the SDK does under the hood.

Base URL

https://api.vibefollow.com/api/v1
All endpoints are namespaced under /api/v1. Future major versions will use a new namespace (/api/v2); v1 will remain available indefinitely.

Endpoint catalog

POST /api/v1/users

Upsert a user.

POST /api/v1/events

Track a single event.

POST /api/v1/events/batch

Track multiple events in one POST.
The customer-facing API surface is intentionally narrow. The Vibefollow backend exposes a much larger surface for the in-dashboard product (drafts, audiences, sequences, etc.) — those endpoints aren’t part of the public contract.

Response envelope

Successful responses always wrap their payload in { data, meta? }:
{
  "data": { "accepted": true }
}
Collection responses also include meta.pagination:
{
  "data": [ ... ],
  "meta": {
    "pagination": { "total": 142, "offset": 0, "limit": 50 }
  }
}

Error envelope

Errors return a non-2xx status and a body shaped as { errors: [{ code, message, field? }] }:
{
  "errors": [
    {
      "code": "validation_failed",
      "message": "required",
      "field": "external_user_id"
    }
  ]
}
code is a machine-readable identifier (snake_case). message is human-readable. field names the offending field when applicable. The SDK maps each status to a typed error class — see Errors.

Idempotency

Every mutating request should carry an Idempotency-Key header:
Idempotency-Key: 7b6c7e9e-2c2d-4a8d-9d3a-4f3d2c1b0a99
The SDK generates a v4 UUID on every request. The backend dedupes within a 24-hour window — if the same key arrives twice, the second request returns the first response and no work is duplicated.
Safe to retry on 5xx, 429, or network failures. The SDK does this automatically.

Rate limits

Per-project, per-endpoint limits apply. When you exceed a limit you get:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json

{ "errors": [{ "code": "rate_limited", "message": "Too many requests" }] }
Wait Retry-After seconds before retrying. The SDK does this for you — RateLimitError is only thrown after retries are exhausted.

Authentication

All endpoints require an API key in the Authorization header:
Authorization: Bearer sk_live_••••••••••••••••••••
See Authentication for the wire-level detail.

Content types

Requests must be Content-Type: application/json. Responses are always JSON. Bodies are UTF-8 encoded.

Timestamps

All timestamps in request and response bodies are ISO 8601 strings in UTC:
{ "occurred_at": "2026-05-17T14:00:00.000Z" }
The backend stores timestamps as TIMESTAMPTZ; UI renders them in the user’s timezone.