List people
List resolved person profiles for the location, most-recent first. Each row carries resolved display fields top-level — display_name, email (falls back to an email-type identity when no $email property is set), and user_id (the person's first user_id-type identity) — so list UIs can label rows (e.g. user_id → email → name) without a per-row GET /people/{personId} fetch. Rows also include company, avatar, session_count, and first/last-touch channel fields. Use search to match against name, email, or identities.
To walk every person (bulk sync), use order=id and page with after: pass the previous response's next_after until it is null. Pages cost the same at any depth, unlike offset, which gets slow on large locations. The walk covers everyone who existed when it started. People created during it can land behind the cursor and be missed.
To catch up later, walk again with updated_since set to the start time of the previous walk minus 15 minutes. That returns only people created or changed since (each row's updated_at), including anyone the previous walk missed. Rows can repeat, so upsert by id. People merged away since drop out of this list; read GET /merges with since to remove them.
order=id requests share a rate limit of 30 per 10 seconds per agency, across all of its locations. That is one walk at full speed, so walk locations one after another, not in parallel.
curl -X GET "https://mythic-analytics.gulp.workers.dev/client/v1/data/people?location_id=acme-retail&limit=50&offset=0&order=last_seen&after=example_string&updated_since=2024-12-25T10%3A00%3A00Z&identified=true&search=example_string&segment_id=example_string" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Authorization: Bearer YOUR_API_TOKEN"
import requests
import json
url = "https://mythic-analytics.gulp.workers.dev/client/v1/data/people?location_id=acme-retail&limit=50&offset=0&order=last_seen&after=example_string&updated_since=2024-12-25T10%3A00%3A00Z&identified=true&search=example_string&segment_id=example_string"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
response = requests.get(url, headers=headers)
print(response.json())
const response = await fetch("https://mythic-analytics.gulp.workers.dev/client/v1/data/people?location_id=acme-retail&limit=50&offset=0&order=last_seen&after=example_string&updated_since=2024-12-25T10%3A00%3A00Z&identified=true&search=example_string&segment_id=example_string", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://mythic-analytics.gulp.workers.dev/client/v1/data/people?location_id=acme-retail&limit=50&offset=0&order=last_seen&after=example_string&updated_since=2024-12-25T10%3A00%3A00Z&identified=true&search=example_string&segment_id=example_string", nil)
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://mythic-analytics.gulp.workers.dev/client/v1/data/people?location_id=acme-retail&limit=50&offset=0&order=last_seen&after=example_string&updated_since=2024-12-25T10%3A00%3A00Z&identified=true&search=example_string&segment_id=example_string')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
response = http.request(request)
puts response.body
{
"success": true,
"data": [
{
"id": "8f3c1e00-4a2b-4c9d-9e11-1a2b3c4d5e6f",
"location_id": "acme-retail",
"display_name": "Dana Reyes",
"email": "dana@example.com",
"user_id": "usr_2841",
"company": "Example Co",
"avatar": "https://cdn.example.com/avatars/dana.png",
"session_count": 17,
"first_channel": "paid/google",
"last_channel": "direct/none",
"last_utm_source": "example_string",
"last_utm_medium": "example_string",
"last_utm_campaign": "example_string",
"last_geo_country_name": "United States",
"first_geo_country": "US",
"last_device_type": "desktop",
"first_landing_page": "https://example.com/pricing",
"last_landing_page": "https://example.com/blog/launch",
"updated_at": "2026-09-23 22:10:14.364",
"properties": {
"$name": "Dana Reyes",
"$email": "dana@example.com",
"$company": "Example Co",
"$avatar": "https://cdn.example.com/avatars/dana.png"
},
"first_seen_at": "2024-12-25T10:00:00Z",
"last_seen_at": "2024-12-25T10:00:00Z",
"identity_count": 3
}
],
"count": 50,
"next_after": "example_string"
}
{
"error": "Bad Request",
"message": "The request contains invalid parameters or malformed data",
"code": 400,
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}
{
"error": "Unauthorized",
"message": "Authentication required. Please provide a valid API token",
"code": 401
}
{
"error": "Forbidden",
"message": "You don't have permission to access this resource",
"code": 403
}
{
"error": "Not Found",
"message": "The requested resource was not found",
"code": 404
}
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Please try again later",
"code": 429,
"retryAfter": 3600
}
/people
Target server for requests. Edit to use your own host.
Agency key as bearer token. Format: Bearer ak_.... Must name a location via the location_id query parameter or X-Location-Id header. Scoped keys (mcp_) are accepted too and need people:read. See Using an mcp_ key over HTTP.
Bearer ak_.... Must name a location via the location_id query parameter or X-Location-Id header. Scoped keys (mcp_) are accepted too and need people:read. See Using an mcp_ key over HTTP.
Location secret key as bearer token. Format: Bearer sk_.... Resolves its own location — no location_id needed.
Bearer sk_.... Resolves its own location — no location_id needed.
Required for agency (ak_) keys. Ignored for secret (sk_) keys, which resolve their own location. May also be supplied via the X-Location-Id header.
Maximum results per page. Default 50, min 1, max 200.
Number of results to skip. Default 0. Only with order=last_seen.
last_seen (default) returns most-recently-seen first. id returns a stable order for walking every person with after.
Cursor for order=id. The previous page's next_after (its last id). Implies order=id.
ISO 8601 timestamp. Only people whose updated_at is at or after it (created or changed since). Inclusive, so a boundary row repeats rather than being dropped.
true returns only people with an email, user_id, or phone identity. false returns only anonymous visitors.
Substring match against name, email, or company. Composes with segment_id (and overrides the segment's own stored search filter, if it has one).
Scope the list to a stored segment's members (same segments as GET /builder/segments), keeping this endpoint's full row shape — the same scoping already available on /sessions, /sessions/breakdown, and /replays. search, limit, and offset compose. order=id, after, identified, and updated_since do not (400 invalid_param). Unknown ids return 404 segment_not_found.
Request Preview
Response
Response will appear here after sending the request
Authentication
Bearer token. Agency key as bearer token. Format: Bearer ak_.... Must name a location via the location_id query parameter or X-Location-Id header. Scoped keys (mcp_) are accepted too and need people:read. See Using an mcp_ key over HTTP.
Bearer token. Location secret key as bearer token. Format: Bearer sk_.... Resolves its own location — no location_id needed.
Query Parameters
Required for agency (ak_) keys. Ignored for secret (sk_) keys, which resolve their own location. May also be supplied via the X-Location-Id header.
acme-retailMaximum results per page. Default 50, min 1, max 200.
Number of results to skip. Default 0. Only with order=last_seen.
last_seen (default) returns most-recently-seen first. id returns a stable order for walking every person with after.
last_seenidCursor for order=id. The previous page's next_after (its last id). Implies order=id.
ISO 8601 timestamp. Only people whose updated_at is at or after it (created or changed since). Inclusive, so a boundary row repeats rather than being dropped.
true returns only people with an email, user_id, or phone identity. false returns only anonymous visitors.
Substring match against name, email, or company. Composes with segment_id (and overrides the segment's own stored search filter, if it has one).
Scope the list to a stored segment's members (same segments as GET /builder/segments), keeping this endpoint's full row shape — the same scoping already available on /sessions, /sessions/breakdown, and /replays. search, limit, and offset compose. order=id, after, identified, and updated_since do not (400 invalid_param). Unknown ids return 404 segment_not_found.
Responses
Number of rows returned.
Only with order=id. Pass as after for the next page. null when this page was the last.