Builder API

Consumers

List and look up consumers who have interacted with your Chipp app

| View as Markdown
1 min read
# api # builder-api # rest # consumers # users # leads # contacts

Consumers are the people who interact with your Chipp app. Each consumer has a unique ID and may have an email, name, or other identifying information depending on how they authenticated.

ℹ️

Sensitive authentication fields (password hashes, tokens) are never exposed through the Builder API.

List Consumers

plaintext
GET /api/v1/apps/{appId}/consumers

Returns a paginated list of consumers. Uses offset-based pagination.

Query Parameters

ParameterTypeDefaultDescription
limitinteger25Results per page (1-100)
offsetinteger0Number of results to skip
searchstringSearch by name, email, or identifier
has_emailstringFilter by email presence: "true" or "false"
created_afterISO 8601Consumers created after this date
created_beforeISO 8601Consumers created before this date

Example

bash
curl "https://build.chipp.ai/api/v1/apps/YOUR_APP_ID/consumers?limit=20&has_email=true" \
  -H "Authorization: Bearer chipp_YOUR_API_KEY"

Response

json
{
  "data": [
    {
      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "identifier": "jane@example.com",
      "email": "jane@example.com",
      "name": "Jane Smith",
      "picture_url": null,
      "email_verified": true,
      "credits": 100,
      "subscription_active": false,
      "mode": "default",
      "is_anonymous": false,
      "created_at": "2025-05-20T10:00:00Z",
      "updated_at": "2025-06-15T10:00:00Z"
    },
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "identifier": "anon_x7k2m",
      "email": null,
      "name": null,
      "picture_url": null,
      "email_verified": false,
      "credits": 0,
      "subscription_active": false,
      "mode": "default",
      "is_anonymous": true,
      "created_at": "2025-06-10T15:30:00Z",
      "updated_at": "2025-06-10T15:30:00Z"
    }
  ],
  "pagination": {
    "has_more": true,
    "total": 142,
    "limit": 20,
    "offset": 0
  }
}

Response Fields

FieldTypeDescription
idUUIDUnique consumer identifier
identifierstringHuman-readable identifier (email or generated ID)
emailstring or nullConsumer’s email address, if provided
namestring or nullConsumer’s display name, if provided
picture_urlstring or nullURL to the consumer’s profile picture
email_verifiedbooleanWhether the consumer’s email has been verified
creditsintegerConsumer’s current credit balance
subscription_activebooleanWhether the consumer has an active subscription
modestringConsumer’s current mode
is_anonymousbooleanWhether the consumer is anonymous
created_atISO 8601When the consumer was first seen
updated_atISO 8601When the consumer was last updated

Paginating with Offset

bash
# Page 1
curl "https://build.chipp.ai/api/v1/apps/YOUR_APP_ID/consumers?limit=25&offset=0" \
  -H "Authorization: Bearer chipp_YOUR_API_KEY"

# Page 2
curl "https://build.chipp.ai/api/v1/apps/YOUR_APP_ID/consumers?limit=25&offset=25" \
  -H "Authorization: Bearer chipp_YOUR_API_KEY"

Filtering for Leads (Consumers with Email)

A common use case is syncing identified consumers to your CRM:

bash
curl "https://build.chipp.ai/api/v1/apps/YOUR_APP_ID/consumers?has_email=true&created_after=2025-06-01T00:00:00Z" \
  -H "Authorization: Bearer chipp_YOUR_API_KEY"

Get Consumer

plaintext
GET /api/v1/apps/{appId}/consumers/{consumerId}

Returns a single consumer by ID.

Example

bash
curl "https://build.chipp.ai/api/v1/apps/YOUR_APP_ID/consumers/7c9e6679-7425-40de-944b-e07fc1f90ae7" \
  -H "Authorization: Bearer chipp_YOUR_API_KEY"

Response

json
{
  "data": {
    "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "identifier": "jane@example.com",
    "email": "jane@example.com",
    "name": "Jane Smith",
    "picture_url": null,
    "email_verified": true,
    "credits": 100,
    "subscription_active": false,
    "mode": "default",
    "is_anonymous": false,
    "created_at": "2025-05-20T10:00:00Z",
    "updated_at": "2025-06-15T10:00:00Z",
    "session_count": 8
  }
}

The single-consumer response includes all fields from the list response, plus session_count (integer) — the total number of chat sessions for this consumer.

Error: Consumer Not Found (404)

json
{
  "error": {
    "code": "not_found",
    "message": "Consumer not found"
  }
}

Authenticate a Consumer (Server-Side)

plaintext
POST /api/v1/apps/{appId}/consumers/auth

Mint a Bearer token for a signed-in user. Call this from your backend to bridge your own auth (WorkOS, Auth0, Clerk, Okta, custom SSO) into a Chipp app — the returned token authenticates the user inside the chat iframe without requiring them to sign in again.

Optionally inject per-user metadata (territory, project, role, named colleagues, internal IDs) that the agent’s system prompt automatically references on every session. No webhook, no template syntax, no builder config required.

ℹ️

Requires a Builder API key with write scope on the consumers resource. Ask the Alchemist to mint one (“Create a Builder API key for this app called ‘My integration’.”) — Alchemist-minted keys default to write on both sessions and consumers. To script the setup with a builder session cookie, see Requesting Write Scopes.

Request Body

FieldTypeRequiredDescription
emailstringyesUser’s email address. Lower-cased and trimmed before lookup.
namestringnoDisplay name. Max 255 chars. Updates the stored name on every call.
metadataobjectnoPer-user context. Bounds and schema below.

Example

bash
curl -X POST https://build.chipp.ai/api/v1/apps/YOUR_APP_ID/consumers/auth \
  -H "Authorization: Bearer chipp_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "name": "Jane Doe",
    "metadata": {
      "territory": "Northeast",
      "projectId": "PRJ-4821",
      "role": "Account Executive",
      "managerName": "Sam Reynolds",
      "vipFlag": true
    }
  }'

Response

json
{
  "data": {
    "token": "eyJhbGciOi...",
    "consumer": {
      "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "email": "jane@example.com",
      "name": "Jane Doe",
      "identifier": "jane@example.com",
      "credits": 0,
      "picture_url": null
    },
    "expires_at": "2025-07-15T10:00:00Z"
  }
}

Pass data.token to the widget via ChippWidget.setUser({ token }). See the embed widget guide for the full flow.

Metadata Schema

The metadata field accepts arbitrary key/value pairs that surface verbatim under an ## About this user block at the end of the system prompt. The builder does not need to pre-configure fields.

Limits

  • Up to 20 keys per request.
  • Keys must match ^[a-zA-Z][a-zA-Z0-9_]*$, max 64 chars. Either camelCase or snake_case works — the renderer humanizes both (projectId → “Project id”, project_name → “Project name”).
  • Values: string (max 2000 chars), number (finite), boolean, or null.
  • Total request body capped at 10 KB.
  • Reserved keys are rejected:
    • Top-level columns: email, name, id, password, identifier, credits, isAnonymous, profile
    • Dossier fields the LLM manages: timezone, language, preferences, context, notes

Merge semantics

metadata is upserted per key, not replaced wholesale. Call /consumers/auth on every page load with whatever your backend currently knows — keys you don’t send are preserved from previous calls.

bash
# First call: set territory + projectId
curl -X POST .../consumers/auth -d '{
  "email": "jane@example.com",
  "metadata": {"territory": "Northeast", "projectId": "PRJ-4821"}
}'

# Second call (later): update projectId only -- territory stays "Northeast"
curl -X POST .../consumers/auth -d '{
  "email": "jane@example.com",
  "metadata": {"projectId": "PRJ-9000"}
}'

# Third call: explicitly delete projectId by passing null
curl -X POST .../consumers/auth -d '{
  "email": "jane@example.com",
  "metadata": {"projectId": null}
}'

Rendering

The values appear in the system prompt before the user’s first message:

plaintext
## About this user
- Name: Jane Doe
- Territory: Northeast
- Project id: PRJ-9000
- Role: Account Executive
- Manager name: Sam Reynolds
- Vip flag: true
  • Missing keys never error and never render an empty line — the row is simply omitted.
  • A key that collides with a customFields (Collection Form) key only renders once, from the form value.
  • Builder-configured customFields and server-injected metadata coexist: the form is for things you ask the user, metadata is for things your backend already knows.

Errors

StatusCodeWhen
400auth_failedDatabase error or other internal failure. The error message contains details.
400(validation)Invalid email, oversized metadata, reserved key, value out of bounds. The error field contains a human-readable message.
403insufficient_scopeBuilder API key missing consumers:write scope.