Users
Profiles and everything attached to one user: traits, the consent map, merged event history (alias-resolved), journey timeline, and the GDPR surfaces: one-call erasure and a full JSON export. Session-token auth; erasure requires org:admin.
GET /v1/users
Section titled “GET /v1/users”List and search profiles
Auth: Clerk session token.
Query parameters
{ "cursor": "string", "limit": 50, "direction": "asc", "q": "string", "trait": "string", "traitValue": "string", "segmentId": "string"}| Field | Type | Required | Constraints |
|---|---|---|---|
cursor |
string | no | |
limit |
integer | no | default 50; 1 ≤ x ≤ 100 |
direction |
“asc” | “desc” | no | default "asc" |
q |
string | no | length 0–200 |
trait |
string | no | length 1–200 |
traitValue |
string | no | length 1–500 |
segmentId |
string | no | length 1–200 |
Response 200
{ "data": [ { "id": "string", "orgId": "string", "environment": "development", "appId": "string", "sourceId": "string", "traits": { "key": {} }, "consent": { "key": true }, "mergedInto": "string", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "identifiers": [ { "kind": "anonymousId", "value": "string", "createdAt": "2026-01-15T09:30:00.000Z" } ], "anonymous": true } ], "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object[] | yes | |
data[] |
object | yes | |
data[].id |
string | yes | |
data[].orgId |
string | yes | |
data[].environment |
“development” | “production” | yes | |
data[].appId |
string | yes | |
data[].sourceId |
string | yes | |
data[].traits |
record<string, any> | yes | |
data[].consent |
record<string, boolean> | yes | |
data[].mergedInto |
string | null | yes | |
data[].createdAt |
string (date-time) | yes | |
data[].updatedAt |
string (date-time) | yes | |
data[].identifiers |
object[] | yes | |
data[].identifiers[] |
object | yes | |
data[].identifiers[].kind |
“anonymousId” | “userId” | “clerkId” | “email” | yes | |
data[].identifiers[].value |
string | yes | |
data[].identifiers[].createdAt |
string (date-time) | yes | |
data[].anonymous |
boolean | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no |
Errors follow the shared envelope and code table.
GET /v1/users/find
Section titled “GET /v1/users/find”Find a profile by one identifier (
Auth: Clerk session token.
Query parameters
{ "identifier": "string"}| Field | Type | Required | Constraints |
|---|---|---|---|
identifier |
string | yes | length 3–220 |
Response 200
{ "data": { "id": "string", "orgId": "string", "environment": "development", "appId": "string", "sourceId": "string", "traits": { "key": {} }, "consent": { "key": true }, "mergedInto": "string", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "identifiers": [ { "kind": "anonymousId", "value": "string", "createdAt": "2026-01-15T09:30:00.000Z" } ], "anonymous": true, "mergedIds": [ "string" ] }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.id |
string | yes | |
data.orgId |
string | yes | |
data.environment |
“development” | “production” | yes | |
data.appId |
string | yes | |
data.sourceId |
string | yes | |
data.traits |
record<string, any> | yes | |
data.consent |
record<string, boolean> | yes | |
data.mergedInto |
string | null | yes | |
data.createdAt |
string (date-time) | yes | |
data.updatedAt |
string (date-time) | yes | |
data.identifiers |
object[] | yes | |
data.identifiers[] |
object | yes | |
data.identifiers[].kind |
“anonymousId” | “userId” | “clerkId” | “email” | yes | |
data.identifiers[].value |
string | yes | |
data.identifiers[].createdAt |
string (date-time) | yes | |
data.anonymous |
boolean | yes | |
data.mergedIds |
string[] | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no |
Errors follow the shared envelope and code table.
GET /v1/users/{profileId}
Section titled “GET /v1/users/{profileId}”Fetch one profile with its identifiers
Auth: Clerk session token.
Response 200
{ "data": { "id": "string", "orgId": "string", "environment": "development", "appId": "string", "sourceId": "string", "traits": { "key": {} }, "consent": { "key": true }, "mergedInto": "string", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "identifiers": [ { "kind": "anonymousId", "value": "string", "createdAt": "2026-01-15T09:30:00.000Z" } ], "anonymous": true, "mergedIds": [ "string" ] }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.id |
string | yes | |
data.orgId |
string | yes | |
data.environment |
“development” | “production” | yes | |
data.appId |
string | yes | |
data.sourceId |
string | yes | |
data.traits |
record<string, any> | yes | |
data.consent |
record<string, boolean> | yes | |
data.mergedInto |
string | null | yes | |
data.createdAt |
string (date-time) | yes | |
data.updatedAt |
string (date-time) | yes | |
data.identifiers |
object[] | yes | |
data.identifiers[] |
object | yes | |
data.identifiers[].kind |
“anonymousId” | “userId” | “clerkId” | “email” | yes | |
data.identifiers[].value |
string | yes | |
data.identifiers[].createdAt |
string (date-time) | yes | |
data.anonymous |
boolean | yes | |
data.mergedIds |
string[] | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no |
Errors follow the shared envelope and code table.
DELETE /v1/users/{profileId}
Section titled “DELETE /v1/users/{profileId}”Erase a user (GDPR)
Auth: Clerk session token.
Response 200
{ "data": { "profileId": "string", "terminatedInstances": 42 }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.profileId |
string | yes | |
data.terminatedInstances |
integer | yes | 0 ≤ x ≤ ∞ |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no |
Errors follow the shared envelope and code table.
GET /v1/users/{profileId}/export
Section titled “GET /v1/users/{profileId}/export”Export everything held on a user (GDPR)
Auth: Clerk session token.
Response 200
{ "data": { "exportedAt": "2026-01-15T09:30:00.000Z", "user": { "id": "string", "orgId": "string", "environment": "development", "appId": "string", "sourceId": "string", "traits": { "key": {} }, "consent": { "key": true }, "mergedInto": "string", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "identifiers": [ { "kind": "anonymousId", "value": "string", "createdAt": "2026-01-15T09:30:00.000Z" } ], "anonymous": true, "mergedIds": [ "string" ] }, "events": [ { "id": "string", "orgId": "string", "environment": "development", "appId": "string", "sourceId": "string", "profileId": "string", "event": "string", "properties": { "key": {} }, "timestamp": "2026-01-15T09:30:00.000Z", "receivedAt": "2026-01-15T09:30:00.000Z", "messageId": "string" } ], "journeys": [ { "id": "string", "orgId": "string", "environment": "development", "journey": "string", "profileId": "string", "workflowId": "string", "runId": "string", "completedAt": "2026-01-15T09:30:00.000Z", "createdAt": "2026-01-15T09:30:00.000Z" } ], "deliveries": [ { "id": "string", "orgId": "string", "environment": "development", "profileId": "string", "journey": "string", "step": "string", "channel": "email", "status": "sent", "dryRun": true, "recipient": "string", "providerId": "string", "error": "string", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "sentAt": "2026-01-15T09:30:00.000Z", "settledAt": "2026-01-15T09:30:00.000Z" } ], "suppressedAddresses": [ { "id": "string", "orgId": "string", "address": "string", "type": "bounce", "reason": "string", "source": "string", "suppressedAt": "2026-01-15T09:30:00.000Z", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z" } ], "emailAddresses": [ { "id": "string", "orgId": "string", "environment": "development", "address": "string", "verifiedAt": "2026-01-15T09:30:00.000Z", "verificationMethod": "link", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z" } ], "quarantineEntries": [ { "id": "string", "orgId": "string", "environment": "development", "kind": "event", "name": "string", "appId": "string", "sourceId": "string", "profileId": "string", "payload": { "properties": { "key": {} }, "messageId": "string", "idempotencyKey": "string" }, "occurredAt": "2026-01-15T09:30:00.000Z", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z" } ] }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.exportedAt |
string (date-time) | yes | |
data.user |
object | yes | |
data.user.id |
string | yes | |
data.user.orgId |
string | yes | |
data.user.environment |
“development” | “production” | yes | |
data.user.appId |
string | yes | |
data.user.sourceId |
string | yes | |
data.user.traits |
record<string, any> | yes | |
data.user.consent |
record<string, boolean> | yes | |
data.user.mergedInto |
string | null | yes | |
data.user.createdAt |
string (date-time) | yes | |
data.user.updatedAt |
string (date-time) | yes | |
data.user.identifiers |
object[] | yes | |
data.user.identifiers[] |
object | yes | |
data.user.identifiers[].kind |
“anonymousId” | “userId” | “clerkId” | “email” | yes | |
data.user.identifiers[].value |
string | yes | |
data.user.identifiers[].createdAt |
string (date-time) | yes | |
data.user.anonymous |
boolean | yes | |
data.user.mergedIds |
string[] | yes | |
data.events |
object[] | yes | |
data.events[] |
object | yes | |
data.events[].id |
string | yes | |
data.events[].orgId |
string | yes | |
data.events[].environment |
“development” | “production” | yes | |
data.events[].appId |
string | yes | |
data.events[].sourceId |
string | yes | |
data.events[].profileId |
string | yes | |
data.events[].event |
string | yes | |
data.events[].properties |
record<string, any> | yes | |
data.events[].timestamp |
string (date-time) | yes | |
data.events[].receivedAt |
string (date-time) | yes | |
data.events[].messageId |
string | null | yes | |
data.journeys |
object[] | yes | |
data.journeys[] |
object | yes | |
data.journeys[].id |
string | yes | |
data.journeys[].orgId |
string | yes | |
data.journeys[].environment |
“development” | “production” | yes | |
data.journeys[].journey |
string | yes | |
data.journeys[].profileId |
string | yes | |
data.journeys[].workflowId |
string | yes | |
data.journeys[].runId |
string | yes | |
data.journeys[].completedAt |
string (date-time) | yes | |
data.journeys[].createdAt |
string (date-time) | yes | |
data.deliveries |
object[] | yes | |
data.deliveries[] |
object | yes | |
data.deliveries[].id |
string | yes | |
data.deliveries[].orgId |
string | yes | |
data.deliveries[].environment |
“development” | “production” | yes | |
data.deliveries[].profileId |
string | yes | |
data.deliveries[].journey |
string | yes | |
data.deliveries[].step |
string | yes | |
data.deliveries[].channel |
“email” | “webhook” | yes | |
data.deliveries[].status |
“sent” | “delivered” | “bounced” | “complained” | “failed” | “skipped_disabled” | “skipped_paused” | “skipped_suppressed” | “skipped_quota” | “skipped_frequency_cap” | “skipped_consent” | “skipped_domain” | “skipped_ssrf” | “would_send” | “would_skip_disabled” | “would_skip_paused” | “would_skip_suppressed” | “would_skip_quota” | “would_skip_frequency_cap” | “would_skip_consent” | “would_skip_domain” | “would_skip_ssrf” | yes | |
data.deliveries[].dryRun |
boolean | yes | |
data.deliveries[].recipient |
string | null | yes | |
data.deliveries[].providerId |
string | null | yes | |
data.deliveries[].error |
string | null | yes | |
data.deliveries[].createdAt |
string (date-time) | yes | |
data.deliveries[].updatedAt |
string (date-time) | yes | |
data.deliveries[].sentAt |
string (date-time) | null | yes | |
data.deliveries[].settledAt |
string (date-time) | null | yes | |
data.suppressedAddresses |
object[] | yes | |
data.suppressedAddresses[] |
object | yes | |
data.suppressedAddresses[].id |
string | yes | |
data.suppressedAddresses[].orgId |
string | yes | |
data.suppressedAddresses[].address |
string | yes | |
data.suppressedAddresses[].type |
“bounce” | “complaint” | “manual” | null | yes | |
data.suppressedAddresses[].reason |
string | null | yes | |
data.suppressedAddresses[].source |
string | null | yes | |
data.suppressedAddresses[].suppressedAt |
string (date-time) | yes | |
data.suppressedAddresses[].createdAt |
string (date-time) | yes | |
data.suppressedAddresses[].updatedAt |
string (date-time) | yes | |
data.emailAddresses |
object[] | yes | |
data.emailAddresses[] |
object | yes | |
data.emailAddresses[].id |
string | yes | |
data.emailAddresses[].orgId |
string | yes | |
data.emailAddresses[].environment |
“development” | “production” | yes | |
data.emailAddresses[].address |
string | yes | |
data.emailAddresses[].verifiedAt |
string (date-time) | null | yes | |
data.emailAddresses[].verificationMethod |
“link” | “imported” | “provider” | null | yes | |
data.emailAddresses[].createdAt |
string (date-time) | yes | |
data.emailAddresses[].updatedAt |
string (date-time) | yes | |
data.quarantineEntries |
object[] | yes | |
data.quarantineEntries[] |
object | yes | |
data.quarantineEntries[].id |
string | yes | |
data.quarantineEntries[].orgId |
string | yes | |
data.quarantineEntries[].environment |
“development” | “production” | yes | |
data.quarantineEntries[].kind |
“event” | “trait” | yes | |
data.quarantineEntries[].name |
string | yes | |
data.quarantineEntries[].appId |
string | yes | |
data.quarantineEntries[].sourceId |
string | yes | |
data.quarantineEntries[].profileId |
string | yes | |
data.quarantineEntries[].payload |
object | object | yes | |
data.quarantineEntries[].occurredAt |
string (date-time) | yes | |
data.quarantineEntries[].createdAt |
string (date-time) | yes | |
data.quarantineEntries[].updatedAt |
string (date-time) | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no |
Errors follow the shared envelope and code table.
PATCH /v1/users/{profileId}/consent
Section titled “PATCH /v1/users/{profileId}/consent”Update consent purposes
Auth: Clerk session token.
Request body
{ "data": { "emailMarketing": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
record<emailMarketing | dataProcessing, boolean> | yes |
Response 200
{ "data": { "id": "string", "orgId": "string", "environment": "development", "appId": "string", "sourceId": "string", "traits": { "key": {} }, "consent": { "key": true }, "mergedInto": "string", "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "identifiers": [ { "kind": "anonymousId", "value": "string", "createdAt": "2026-01-15T09:30:00.000Z" } ], "anonymous": true, "mergedIds": [ "string" ] }, "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object | yes | |
data.id |
string | yes | |
data.orgId |
string | yes | |
data.environment |
“development” | “production” | yes | |
data.appId |
string | yes | |
data.sourceId |
string | yes | |
data.traits |
record<string, any> | yes | |
data.consent |
record<string, boolean> | yes | |
data.mergedInto |
string | null | yes | |
data.createdAt |
string (date-time) | yes | |
data.updatedAt |
string (date-time) | yes | |
data.identifiers |
object[] | yes | |
data.identifiers[] |
object | yes | |
data.identifiers[].kind |
“anonymousId” | “userId” | “clerkId” | “email” | yes | |
data.identifiers[].value |
string | yes | |
data.identifiers[].createdAt |
string (date-time) | yes | |
data.anonymous |
boolean | yes | |
data.mergedIds |
string[] | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no |
Errors follow the shared envelope and code table.
GET /v1/users/{profileId}/segments
Section titled “GET /v1/users/{profileId}/segments”The segments a profile belongs to
Auth: Clerk session token.
Query parameters
{ "cursor": "string", "limit": 50}| Field | Type | Required | Constraints |
|---|---|---|---|
cursor |
string | no | |
limit |
integer | no | default 50; 1 ≤ x ≤ 100 |
Response 200
{ "data": [ { "segmentId": "string", "name": "string", "since": "2026-01-15T09:30:00.000Z" } ], "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object[] | yes | |
data[] |
object | yes | |
data[].segmentId |
string | yes | |
data[].name |
string | yes | |
data[].since |
string (date-time) | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no |
Errors follow the shared envelope and code table.
GET /v1/users/{profileId}/journeys
Section titled “GET /v1/users/{profileId}/journeys”A profile’s journey timeline
Auth: Clerk session token.
Query parameters
{ "cursor": "string", "limit": 50}| Field | Type | Required | Constraints |
|---|---|---|---|
cursor |
string | no | |
limit |
integer | no | default 50; 1 ≤ x ≤ 100 |
Response 200
{ "data": [ { "journey": { "orgId": "string", "environment": "development", "key": "string", "releaseId": "string", "tags": [ "string" ], "trigger": { "event": "string", "appId": "string" }, "purpose": "emailMarketing", "active": true, "spine": [ { "name": "sleep", "detail": "string" } ], "createdAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "enabled": true }, "execution": { "id": "string", "orgId": "string", "environment": "development", "journeyKey": "string", "profileId": "string", "workflowId": "string", "runId": "string", "releaseId": "string", "status": "running", "step": "string", "timerDeadline": "2026-01-15T09:30:00.000Z", "journalEntries": 42, "error": "string", "startedAt": "2026-01-15T09:30:00.000Z", "updatedAt": "2026-01-15T09:30:00.000Z", "endedAt": "2026-01-15T09:30:00.000Z" }, "deliveries": [ { "id": "string", "journey": "string", "step": "string", "channel": "email", "status": "sent", "dryRun": true, "error": "string", "createdAt": "2026-01-15T09:30:00.000Z" } ] } ], "meta": { "requestId": "string", "nextCursor": "string", "hasMore": true }}| Field | Type | Required | Constraints |
|---|---|---|---|
data |
object[] | yes | |
data[] |
object | yes | |
data[].journey |
object | yes | |
data[].journey.orgId |
string | yes | |
data[].journey.environment |
“development” | “production” | yes | |
data[].journey.key |
string | yes | |
data[].journey.releaseId |
string | yes | |
data[].journey.tags |
string[] | yes | |
data[].journey.trigger |
object | object | yes | |
data[].journey.purpose |
“emailMarketing” | “dataProcessing” | yes | |
data[].journey.active |
boolean | yes | |
data[].journey.spine |
object[] | yes | |
data[].journey.spine[] |
object | yes | |
data[].journey.spine[].name |
“sleep” | “waitForEvent” | “email.send” | “webhook.send” | “traits.set” | “traits.unset” | “profile.get” | “profiles.get” | “events.track” | “restart” | yes | |
data[].journey.spine[].detail |
string | no | length 0–200 |
data[].journey.createdAt |
string (date-time) | yes | |
data[].journey.updatedAt |
string (date-time) | yes | |
data[].journey.enabled |
boolean | yes | |
data[].execution |
object | null | yes | |
data[].execution.id |
string | yes | |
data[].execution.orgId |
string | yes | |
data[].execution.environment |
“development” | “production” | yes | |
data[].execution.journeyKey |
string | yes | |
data[].execution.profileId |
string | yes | |
data[].execution.workflowId |
string | yes | |
data[].execution.runId |
string | yes | |
data[].execution.releaseId |
string | yes | |
data[].execution.status |
“running” | “waiting” | “completed” | “failed” | “cancelled” | yes | |
data[].execution.step |
string | null | yes | |
data[].execution.timerDeadline |
string (date-time) | null | yes | |
data[].execution.journalEntries |
integer | yes | -2147483648 ≤ x ≤ 2147483647 |
data[].execution.error |
string | null | yes | |
data[].execution.startedAt |
string (date-time) | yes | |
data[].execution.updatedAt |
string (date-time) | yes | |
data[].execution.endedAt |
string (date-time) | null | yes | |
data[].deliveries |
object[] | yes | |
data[].deliveries[] |
object | yes | |
data[].deliveries[].id |
string | yes | |
data[].deliveries[].journey |
string | yes | |
data[].deliveries[].step |
string | yes | |
data[].deliveries[].channel |
“email” | “webhook” | yes | |
data[].deliveries[].status |
“sent” | “delivered” | “bounced” | “complained” | “failed” | “skipped_disabled” | “skipped_paused” | “skipped_suppressed” | “skipped_quota” | “skipped_frequency_cap” | “skipped_consent” | “skipped_domain” | “skipped_ssrf” | “would_send” | “would_skip_disabled” | “would_skip_paused” | “would_skip_suppressed” | “would_skip_quota” | “would_skip_frequency_cap” | “would_skip_consent” | “would_skip_domain” | “would_skip_ssrf” | yes | |
data[].deliveries[].dryRun |
boolean | yes | |
data[].deliveries[].error |
string | null | yes | |
data[].deliveries[].createdAt |
string (date-time) | yes | |
meta |
object | no | |
meta.requestId |
string | no | |
meta.nextCursor |
string | null | no | |
meta.hasMore |
boolean | no |
Errors follow the shared envelope and code table.