People API
Look someone up: their fields, tags, suppression state, money and where they are in every flow and sequence.
GET /api/v1/people/:id_or_email
Addressed by numeric id or email address — email is the universal key here, lowercased, and it's what imports and events upsert on.
GET /api/v1/people/ada@example.com
{ "person": {
"id": 41, "email": "ada@example.com", "name": "Ada Lovelace",
"unsubscribed": false,
"fields": { "plan": "trial" },
"tags": ["trial"],
"attribution": { "first_landing_page": "…", "utm_source": "…" },
"active_flow_runs": [ { "flow": "trial_journey", "step": "trial_journey.7-wait-for-pricing" } ],
"recent_events": [ … ] } }
Writing to a person
There is no person-update endpoint, and that's deliberate: record an event instead. An event upserts the person, sets fields and tags, captures first-touch attribution, records money — and leaves a timeline entry explaining why any of it changed. A silent write leaves no such account.
POST /api/v1/events
{ "email": "ada@example.com", "name": "plan_changed",
"details": { "from": "trial", "to": "pro" },
"person": { "fields": { "plan": "pro" }, "tags": ["customer"] } }
Suppression
Unsubscribing is the person's, through the
tokenized subscription endpoints —
which attribute it to the exact email it came from. Suppression state appears here
read-only: whether they're unsubscribed, when, why, and how it happened
(one_click, api, import,
provider_sync, provider_webhook, manual).
"It's people, not subscribers" is the rule the data model follows: someone who unsubscribes is still a person, with their history intact.
The queue
GET /api/v1/queue?person=ada@example.com&status=held
What's scheduled for them, what's holding and why, and what was dropped.
?status= takes pending, held,
dropped, canceled or sent;
?limit= caps at 200.
See also: Events API · Subscriptions API · People, for humans