Skip to main content

Find a person

Use GET /users. It answers every lookup, with pagination and a total. Order the whole list with sortBy (createdAt, updatedAt, email or name; default updatedAt) and sortOrder (asc or desc; default desc); pages keep a stable order, so no row moves between them.

# by your own identifier
curl "https://api-eu1.joryio.com/api/users?externalId=user_123" \
-H "Authorization: Bearer jry_live_your_api_key"

# by email
curl "https://api-eu1.joryio.com/api/[email protected]" \
-H "Authorization: Bearer jry_live_your_api_key"

# partial - anything starting with "jane", plus phone and id matching
curl "https://api-eu1.joryio.com/api/users?q=jane" \
-H "Authorization: Bearer jry_live_your_api_key"

Which parameter​

You haveUseMatching
Your own id?externalId=exact
An email address?email=exact, case-insensitive
Joryio's 24-hex id?userId=exact
Part of something - a name, the start of an email, a phone?q=prefix on email, externalId, first and last name; digits anywhere in the phone; whole-value on a 24-hex id or a UUID anonymousId

Exact parameters combine (?email=…&externalId=… requires both). q is ignored when an exact parameter is present - "email equals X" and "any field starts with Y" cannot both narrow one request, and quietly combining them would answer a question you did not ask.

Nothing found​

An empty page, not a 404:

{ "data": [], "pagination": { "total": 0, "limit": 50, "offset": 0, "hasMore": false } }

A userId that is not 24-hex returns the same empty page rather than an error - a malformed id is a lookup that matches nobody, not a broken request.

A parameter we do not recognise​

If a parameter looks like a misspelling of a real one, or if none of your parameters are recognised, the request is refused:

{ "statusCode": 400,
"message": "Unknown query parameter 'externalid'. Did you mean 'externalId'? Valid parameters: limit, offset, email, externalId, userId, q, bots, sortBy, sortOrder" }

This used to be a silent 200 with the full unfiltered page, which is how a typo cost an integrator a day - a filter that does nothing looks exactly like a filter that found everything.

Parameters that arrive without you choosing to send them are still accepted and ignored: _ and _* (jQuery's cache-buster), utm_*, gclid, fbclid, msclkid, and t / v / cb. So [email protected]&_=1724500000 works, and so does ?_=1724500000 on its own.

An unfamiliar parameter that resembles nothing of ours - a gateway's correlation id, say - is also accepted, as long as at least one parameter we understand is present. The rule is not "reject anything unknown", it is "refuse a request that could not have done what you meant".

The other two routes​

Both still work. Neither does anything GET /users cannot.

RouteStill useful when
GET /users/by-user-id/:externalIdyou want the record itself, not a page containing it - it returns the user object directly
GET /users/search?query=you want the older shape: a bare array, capped, no total

GET /users/:userId (Joryio's internal id) is the canonical single-record route and is not going anywhere - it is what id in every response refers to.

Anonymous contacts​

Someone tracked before they identified has no email, no phone and no name. The only handle you have is the anonymousId the SDK generated, and ?q= matches it when the term is UUID-shaped:

curl "https://api-eu1.joryio.com/api/users?q=3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d" \
-H "Authorization: Bearer jry_live_your_api_key"

To attach that session's history to a known person, see POST /users/identify.

  • Users API - the full reference
  • Segments - for "everyone who…", rather than one person