Skip to main content
POST
/
api
/
v1
/
users
Upsert user
curl --request POST \
  --url https://api.example.com/api/v1/users \
  --header 'Content-Type: application/json' \
  --data '
{
  "external_user_id": "<string>",
  "email": "<string>",
  "traits": {}
}
'
{
  "data.accepted": true
}

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.

Upserts a user. Same call works for first-touch and updates — the backend deduplicates by external_user_id.

Request

POST /api/v1/users HTTP/1.1
Host: api.vibefollow.com
Authorization: Bearer sk_live_••••
Content-Type: application/json
Idempotency-Key: 7b6c7e9e-2c2d-4a8d-9d3a-4f3d2c1b0a99

Body

{
  "external_user_id": "usr_42",
  "email": "jane@acme.io",
  "traits": {
    "name": "Jane Doe",
    "plan": "trial",
    "signupDate": "2026-05-17T14:00:00Z",
    "company": "Acme Inc.",
    "role": "engineering_lead"
  }
}
external_user_id
string
required
Your primary key for the user. Stable across re-identifies.
email
string
Email address. Stored in a dedicated column for fast lookup and PII access control.
traits
object
Trait bag. Known keys (name, plan, signupDate, company, role) are stored in dedicated columns; any other key flows into the traits JSON column.

Response

HTTP/1.1 202 Accepted
Content-Type: application/json
{ "data": { "accepted": true } }
data.accepted
boolean
Always true on success. The upsert is enqueued and processed asynchronously — downstream views (audiences, etc.) reflect the new state within a few hundred milliseconds.

Examples

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

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

await vf.users.identify('usr_42', {
  email: 'jane@acme.io',
  name: 'Jane Doe',
  plan: 'trial',
});

Common errors

Missing or malformed Authorization header.
API key valid but not authorised for this resource.
Body failed schema validation; errors[0].field indicates the offending field.
Wait Retry-After seconds.
Retry — the Idempotency-Key prevents duplicates.