Get the current user
GET /users/me
Description
Retrieves the user your token authenticates as, with their team and active
budget embedded inline. The response is the same shape
Get a user returns, resolved from the token instead of from an
id.
When to use
Reach for this endpoint to answer "who am I, and what can I spend" at the start of a session: to show the signed-in user's name, to label sends with their team, or to check budget before you queue gifts. It's also the cheapest way to confirm a token works and which user it belongs to.
This endpoint needs user-context authentication. A service or system token has
no connecting user, so it gets a 400 here; use Get a user with an
explicit id from a service integration, or List users to find
one.
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.
The token is the only thing that selects the user. This endpoint takes no path or query parameters.
Worked examples
A read is a plain GET with no request body. The JavaScript, Python, and Ruby
versions fetch the user and read their team and remaining budget.
- cURL
- JavaScript
- Python
- Ruby
curl -X GET "https://api.andopen.co/users/me" \
-H "Authorization: Bearer <api_key>" \
-H "AndOpen-API-Version: 2026-05"
const response = await fetch("https://api.andopen.co/users/me", {
headers: {
Authorization: "Bearer <api_key>",
"AndOpen-API-Version": "2026-05",
},
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const user = await response.json();
console.log(user.name, user.team?.name);
if (user.budget) {
console.log(user.budget.remaining.amount, user.budget.remaining.currency);
}
import requests
response = requests.get(
"https://api.andopen.co/users/me",
headers={
"Authorization": "Bearer <api_key>",
"AndOpen-API-Version": "2026-05",
},
)
response.raise_for_status()
user = response.json()
team = user["team"]
print(user["name"], team["name"] if team else None)
budget = user["budget"]
if budget:
print(budget["remaining"]["amount"], budget["remaining"]["currency"])
require "net/http"
require "json"
uri = URI("https://api.andopen.co/users/me")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer <api_key>"
request["AndOpen-API-Version"] = "2026-05"
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request(request)
end
response.value # raises on a non-2xx response
user = JSON.parse(response.body)
puts "#{user['name']} #{user.dig('team', 'name')}"
budget = user["budget"]
puts "#{budget['remaining']['amount']} #{budget['remaining']['currency']}" if budget
Response shape
A successful call returns 200 OK with the user as a flat top-level JSON
object, identical to what Get a user returns.
| Field | Description |
|---|---|
id (string · uuid · required) | The connecting user's identifier. Pass it as the sender filter on List gift requests, or as owner on List campaigns, to scope a list to yourself. Both filters also accept the literal me. |
name (string · required) | The user's full name. |
email (string · email · required) | Their email address. Both this and the name are account-internal, so keep them away from recipient-facing surfaces. |
team (object · required · nullable) | The user's team, embedded as an { id, name } summary, or null when they belong to none. |
budget (object · required · nullable) | Their single active budget for the current period, or null when they have none. Its time_unit is one of monthly, quarterly, annually, and it carries four money figures: total, spent, committed, and remaining. |
{
"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"
}
}
}
Per-field notes
budget.total.amount(integer · required) shows the shape all four figures share: a whole number in the smallest unit of the budget'scurrency, never a decimal. Aremainingof{ "amount": 260000, "currency": "EUR" }is €2,600.00 left to spend.remainingalready accounts for gifts in flight. It istotallessspentandcommitted, floored at zero, wherecommittedis gifting drawn against the budget but not yet redeemed. Checkremainingbefore you queue more sends.budgetisnullfor a user with no active budget, and that is not the same as a zero budget. See Get a user for the full per-field detail, which applies identically here.
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.
| Status | Meaning |
|---|---|
| 400 | The 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). |
| 401 | Authentication failed: missing or invalid bearer token. |
| 403 | Authorized but not permitted to access this resource. |
| 429 | Too many requests. Rate limit exceeded. |
| 500 | Internal server error. |
| 503 | Service 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 400 is the one worth planning for, because it fires on a perfectly valid
token:
400 validation_error: the token has no connecting user, which is what a service or system token looks like. The code isinvalid_format, and this one carries noparam, because no parameter caused it.400 api_error:unsupported_api_versionwhen theAndOpen-API-Versionheader 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 read users (forbidden).429 rate_limit_error: too many requests; back off and retry (rate_limited). TheRateLimit-*response headers tell you the budget and reset time.500/503 api_error: a fault on our side; rare, and safe to retry after a short delay (honorRetry-Afteron a503).