Skip to main content
Version: 2026-05

List users

GET /users

Description

Lists the users on your account, newest first, as a cursor-paginated collection. Each item carries the full user shape: the same object Get a user returns, with the team and active budget embedded inline.

What you get back depends on the token you send. An admin or service token lists every user in the account. A non-admin user token lists only itself, so the page holds a single item.

When to use

Use this endpoint to build a picker of who can send gifts, to reconcile budgets across a team, or to resolve a set of sender and owner ids in one call instead of fetching each user separately.

When you already have a user's id, fetch it directly with Get a user. To read the user your own token authenticates as, use Get the current user.

Parameters

Headers

AndOpen-API-Version (string · required) is the API version this request targets. Always send 2026-05. Requests authenticate with a bearer token; see Authentication for how to present it and Environments for the regional base URL to send it to.

Query parameters

All three are optional, and this endpoint takes no filters: page and sort are the only controls it offers.

limit (integer · optional) is how many users to return per page. Defaults to 25, which is also the maximum. A larger value is clamped to 25 server-side rather than rejected; a non-numeric, zero, or negative value is rejected with a 400.

after (string · uuid · optional) is the keyset pagination cursor. Pagination is cursor-based, not page-numbered: to fetch the next page, pass the id of the last user in the page you just received. Omit it for the first page. A cursor that references no existing record is rejected with a 400. Stop paging when the response's has_more is false.

sort (string · optional) is the field to order by, - prefix for descending. Defaults to -created_at (newest first); created_at, email, and -email are also accepted. Any other field is rejected with a 400.

Worked examples

The cURL version is the raw HTTP call; the JavaScript, Python, and Ruby versions are idiomatic equivalents. Each requests the first page ordered by email.

curl -X GET "https://api.andopen.co/users?sort=email" \
-H "Authorization: Bearer <api_key>" \
-H "AndOpen-API-Version: 2026-05"

Paging through every user

To walk the whole collection, keep fetching while has_more is true, passing the last user's id as the after cursor each time. The cURL version shows a single follow-up request; the others loop until the last page.

curl -X GET "https://api.andopen.co/users?after=9f8e7d6c-5b4a-3210-fedc-ba9876543210" \
-H "Authorization: Bearer <api_key>" \
-H "AndOpen-API-Version: 2026-05"

Response shape

A successful call returns 200 OK with a page object: a data array of users plus a boolean cursor flag. Paging is driven by has_more and the after cursor.

FieldDescription
data (array · required)The users in this page. Each entry is a full user object, identical to what Get a user returns; see that page for the per-field detail of the team and budget.
has_more (boolean · required)Whether more users exist beyond this page. When true, fetch the next page by passing the last item's id as the after cursor; when false, you've reached the end.
data.team (object · required · nullable)Each user's team summary, embedded inline.
data.budget (object · required · nullable)Each user's active budget, also inline. See Get a user for the per-field detail of both.
{
"data": [
{
"id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"name": "Dana Okafor",
"email": "dana@acme.example",
"team": {
"id": "1122aabb-ccdd-eeff-0011-223344556677",
"name": "Sales EMEA"
},
"budget": {
"id": "7c1f5e2a-9b3d-4f8a-b1c2-0d4e6f8a1b2c",
"time_unit": "monthly",
"total": {
"amount": 500000,
"currency": "EUR"
},
"spent": {
"amount": 180000,
"currency": "EUR"
},
"committed": {
"amount": 60000,
"currency": "EUR"
},
"remaining": {
"amount": 260000,
"currency": "EUR"
}
}
}
],
"has_more": false
}

Per-field notes

  • Every item is the full user, budget included. There is no trimmed list variant, so a single page gives you every figure you'd otherwise fetch one user at a time.
  • has_more drives paging, not a total count. The response carries no total and no next URL. Treat has_more: false as the only signal to stop, and build the next request from the last item's id.
  • data[].team and data[].budget are each null when unset. A null budget means no budget governs that user's sends, which reads differently from a budget whose remaining is zero.
  • Budget figures are money objects in the smallest currency unit, and each user carries their own currency. Convert before you total a mixed-currency page.

Error cases

Every failure uses the shared error model: a top-level errors array of objects carrying type, code, message, and (for field-level problems) param. See Errors for the full type/code taxonomy and how to handle each category; the codes below are the ones this endpoint produces.

StatusMeaning
400The request is malformed or violates a precondition. Typical triggers are a missing or unsupported `AndOpen-API-Version` header, a request body that is not valid JSON, or pagination parameters that fail server-side validation (`limit` non-numeric or non-positive, `after` referencing a record that does not exist).
401Authentication failed: missing or invalid bearer token.
403Authorized but not permitted to access this resource.
429Too many requests. Rate limit exceeded.
500Internal server error.
503Service unavailable. The account may be under maintenance. Check the `Retry-After` header.

Every error carries a type, one of: validation_error, authentication_error, authorization_error, not_found_error, rate_limit_error, api_error.

The ones you'll meet in practice:

  • 400 validation_error: a query parameter was rejected, each naming the offending one in param. An after cursor referencing no existing record is invalid_reference. A limit that is not a positive integer and an unsupported sort field are both invalid_format.
  • 400 api_error: unsupported_api_version when the AndOpen-API-Version header is missing or unsupported (returned before authentication).
  • 401 authentication_error: the bearer token is missing, invalid, or expired (unauthorized).
  • 403 authorization_error: the token is valid but not permitted to list users (forbidden).
  • 429 rate_limit_error: too many requests; back off and retry (rate_limited). The RateLimit-* response headers tell you the budget and reset time.