Skip to main content
POST
/
api
/
v1
/
events
/
bulk
Bulk track events
curl --request POST \
  --url https://api.example.com/api/v1/events/bulk \
  --header 'Content-Type: application/json' \
  --data '
{
  "events": [
    {}
  ]
}
'
{
  "data.accepted": 123,
  "data.rejected": 123,
  "data.errors": [
    {}
  ],
  "meta.received": 123
}

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 backfill counterpart to single-event track. Send up to 1,000 event records in one POST. Replaces the older /api/v1/events/batch endpoint for new integrations — the bulk endpoint reports per-record errors instead of failing the whole batch.
SDK is the recommended path. vf.events.bulk() wraps this endpoint with strong typing and pairs with chunk() for backfills larger than 1,000 records.

Request

POST /api/v1/events/bulk HTTP/1.1
Host: api.vibefollow.com
Authorization: Bearer sk_live_••••
Content-Type: application/json

Body

{
  "events": [
    {
      "external_user_id": "usr_42",
      "name": "user_signed_up",
      "timestamp": "2024-01-15T10:00:00Z",
      "properties": { "plan": "trial" }
    },
    {
      "external_user_id": "usr_42",
      "name": "trial_started",
      "timestamp": "2024-01-15T10:00:05Z",
      "properties": { "trialDays": 14 }
    }
  ]
}
events
Event[]
required
Array of event records. Each entry has the same shape as the single-event body. Minimum 1, maximum 1,000 records.

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "data": {
    "accepted": 998,
    "rejected": 2,
    "errors": [
      { "index": 17, "code": "validation", "message": "name must be at least 1 character", "field": "name" },
      { "index": 423, "code": "validation", "message": "Invalid timestamp" }
    ]
  },
  "meta": { "received": 1000 }
}
data.accepted
number
Records that passed validation and were enqueued.
data.rejected
number
Records that failed validation. Each has a corresponding entry in data.errors.
data.errors
object[]
Per-record validation failures with the original array index.
meta.received
number
Total records in the request. accepted + rejected === meta.received.
Idempotency is automatic. The server-side events_dedupe_unique partial index on (project_id, tracked_user_id, name, occurred_at) means re-sending the same event is a no-op. Retry any chunk that returns 429 or 5xx — duplicates are silently dropped.

Examples

import { VibeFollow, chunk } from '@vibefollow/sdk';

const vf = new VibeFollow({ apiKey: process.env.VIBEFOLLOW_API_KEY! });

for (const slice of chunk(historicalEvents, 1000)) {
  await vf.events.bulk(slice);
}

Common errors

Missing or malformed Authorization header.
Envelope failed validation: events missing, not an array, empty, or > 1,000 records. Per-record validation failures surface in data.errors.
Standard per-project rate limit; honor Retry-After.
The project’s ingest queue is saturated (50,000+ jobs waiting or delayed). Back off, drain, then resume in smaller chunks.
Retry the same chunk — per-event dedup makes duplicate ingestion a no-op.

Sizing

Max records per request

1,000

Recommended chunk size

1,000

Backfill queue cap

50,000 waiting jobs / project