# User API reference

> The REST API for a signed-in user: your app calls it on the tenant's host with the user's own access token, which reaches only that user's profile, browser sessions and connected apps.

Source: https://docs.authalla.com/docs/user-api-reference

OpenAPI spec: https://api.authalla.com/me/v1/openapi.json (YAML: https://api.authalla.com/me/v1/openapi.yaml)
Base URL: https://{tenant}.authalla.com

## Overview

The User API is what a signed-in user's own app calls about that user:
their profile, the browsers they're signed in on and the apps connected
to their account. Use it to build "Where you're signed in" and "Apps with
access to your account" into your product without a backend of your own.

It is Authalla's only REST API for a signed-in user.

**Called with:** **the signed-in user's own access token**, not a secret
credential.

**Reaches:** only that user, so your app may call it from a browser or a
mobile app.

**Use another API when** you act on other users or on configuration:
call it from your server with a secret credential. The **Application
API** manages every user of a tenant with a client credentials token
([spec](https://api.authalla.com/api/v1/openapi.json)), and the
**Management API** configures tenants, apps and domains with an account
API key ([spec](https://api.authalla.com/management/v1/openapi.json)).
Which API, and which credential, for which job:
https://docs.authalla.com/docs/choosing-an-api

### Host

Call it on your tenant's own host, the one your app signs in through:
`https://{tenant}.authalla.com` or your custom domain. The tenant comes
from the host. `api.authalla.com` doesn't serve it. Browsers may call it
from the origins in the tenant's CORS settings.

### Access token

Send the user's access token: `Authorization: Bearer <access token>`.
The token must be:

- an access token of this tenant, issued to your app for a user (an ID
  token, or a `client_credentials` token, which has no user, is refused);
- issued for your app itself, not for a Resource server: an agent holding
  a token for your API or MCP server can't list or revoke the user's
  other apps;
- still active: it hasn't expired or been revoked, and the user is active.
  Authalla checks this on every call, as introspection does.

A token that fails any of these is `401` with a `WWW-Authenticate: Bearer
error="invalid_token"` header.

### Scopes

Each operation needs one scope. Add the scopes to the app's allowed
scopes and request them at sign-in; the user sees each one on the consent
screen. A token without the scope is `403` with
`WWW-Authenticate: Bearer error="insufficient_scope"`.

- `profile`: read and change the user's name
- `sessions:read` / `sessions:write`: list the user's browser sessions /
  end one
- `connected-apps:read` / `connected-apps:write`: list the apps connected
  to the user's account / revoke one

Ending a browser session never revokes an app, and revoking an app never
ends a browser session.

## Scopes

- `profile`: Read and change the user's name
- `sessions:read`: List the browsers the user is signed in on
- `sessions:write`: Sign the user out of one of their browsers
- `connected-apps:read`: List the apps connected to the user's account
- `connected-apps:write`: Revoke an app's access to the user's account

Errors use one JSON shape with a stable `error` code; see https://docs.authalla.com/docs/errors.

## Operations

### Get the user

`GET /me/v1` · Required scope: `profile`

Returns the signed-in user. `email` and `email_verified` are included
when the token also has the `email` scope.

Requires scope: `profile`.

Responses:

- `200` The signed-in user (Me)
- `401` Missing, invalid, expired or revoked access token, or one this API doesn't accept (Error)
- `403` The access token lacks the operation's scope (Error)
- `500` Something failed on Authalla's side (Error)

### Update the user

`PATCH /me/v1` · Required scope: `profile`

Changes the signed-in user's name and returns the user.

Requires scope: `profile`.

Request body (`application/json`, required): UpdateMeRequest

Responses:

- `200` The updated user (Me)
- `400` The request doesn't match the spec (Error)
- `401` Missing, invalid, expired or revoked access token, or one this API doesn't accept (Error)
- `403` The access token lacks the operation's scope (Error)
- `500` Something failed on Authalla's side (Error)

### List the user's sessions

`GET /me/v1/sessions` · Required scope: `sessions:read`

Lists the browsers the user is signed in on in this tenant, newest
first. The session the calling token was signed in from is marked
`current`; tokens issued before Authalla recorded sessions on tokens
have none.

Requires scope: `sessions:read`.

Responses:

- `200` The user's browser sessions (SessionList)
- `401` Missing, invalid, expired or revoked access token, or one this API doesn't accept (Error)
- `403` The access token lacks the operation's scope (Error)
- `500` Something failed on Authalla's side (Error)

### End a session

`DELETE /me/v1/sessions/{id}` · Required scope: `sessions:write`

Signs the user out of one browser: its next request to Authalla
starts signed out. The apps connected from that browser keep their
access; revoke them with the connected apps endpoints. Ending the
`current` session is allowed; the calling token keeps working.

Requires scope: `sessions:write`.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | The session's `id` from the session list |

Responses:

- `204` The session ended
- `401` Missing, invalid, expired or revoked access token, or one this API doesn't accept (Error)
- `403` The access token lacks the operation's scope (Error)
- `404` The user has no such session or connected app (Error)
- `500` Something failed on Authalla's side (Error)

### List the user's connected apps

`GET /me/v1/connected-apps` · Required scope: `connected-apps:read`

Lists the apps that can still act for the user: those holding a
remembered consent or a live refresh token. The app calling is marked
`current`.

Requires scope: `connected-apps:read`.

Responses:

- `200` The user's connected apps (ConnectedAppList)
- `401` Missing, invalid, expired or revoked access token, or one this API doesn't accept (Error)
- `403` The access token lacks the operation's scope (Error)
- `500` Something failed on Authalla's side (Error)

### Revoke a connected app

`DELETE /me/v1/connected-apps/{id}` · Required scope: `connected-apps:write`

Takes the app's access to the user's account away: its refresh and
access tokens are revoked, its sign-ins not yet finished can't be, and
the user's consent is forgotten, so connecting it again asks again.
A resource server that introspects tokens refuses the app's next
call; one that validates tokens locally accepts its access token
until it expires, within `access_token_lifetime_seconds`. The user's
browser sessions aren't touched. Revoking the `current` app is
allowed and revokes the calling token too.

Requires scope: `connected-apps:write`.

| Parameter | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string | yes | The app's `id` from the connected app list |

Responses:

- `204` The app's access was revoked
- `401` Missing, invalid, expired or revoked access token, or one this API doesn't accept (Error)
- `403` The access token lacks the operation's scope (Error)
- `404` The user has no such session or connected app (Error)
- `500` Something failed on Authalla's side (Error)

## Schemas

### Me

The signed-in user

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | The user's ID, the `sub` of their tokens |
| `name` | string | yes |  |
| `email` | string (email) | no | Present when the token has the `email` scope |
| `email_verified` | boolean | no | Present when the token has the `email` scope |
| `updated_at` | string (date-time) | yes |  |

### UpdateMeRequest

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | yes | The user's new name; surrounding whitespace is trimmed |

### Session

A browser the user is signed in on

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | The session's ID (not its cookie); end the session with it |
| `auth_method` | string | yes | How the user signed in, e.g. passkey, magic_link, pin_code, social-login-google |
| `ip_address` | string | yes | The browser's IP address when the user signed in |
| `user_agent` | string | yes | The browser's User-Agent when the user signed in |
| `created_at` | string (date-time) | yes | When the user signed in |
| `expires_at` | string (date-time) | yes | When the session ends on its own |
| `current` | boolean | yes | The calling token was signed in from this session |

### SessionList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `sessions` | Session[] | yes |  |

### ConnectedApp

An app that holds a remembered consent or a live refresh token for the user

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | The app's ID; revoke it with this |
| `client_id` | string | yes | The OAuth2 client_id the app signs in with (a URL for an app that registered itself) |
| `name` | string | yes |  |
| `self_registered` | boolean | yes | The app registered itself with a Client ID Metadata Document, such as Claude or ChatGPT, rather than being added by the tenant's administrator |
| `resource_servers` | ConnectedAppResourceServer[] | yes | The resource servers the app's live refresh tokens are for, such as an MCP server |
| `scopes` | string[] | yes | The scopes of the app's live tokens and remembered consent |
| `last_used_at` | string (date-time) | no | When the app was last issued a token for the user, at sign-in or refresh. Its calls to the resource server aren't seen by Authalla. |
| `current` | boolean | yes | This is the app calling |

### ConnectedAppResourceServer

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `identifier` | string | yes | The resource server's identifier, the `resource` the app asked for |
| `name` | string | no | The resource server's name; absent when the tenant has no resource server with this identifier |

### ConnectedAppList

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `connected_apps` | ConnectedApp[] | yes |  |
| `access_token_lifetime_seconds` | integer | yes | The tenant's access token lifetime. After a revoke, a resource server that validates tokens locally accepts the app's last access token for at most this long. |

### Error

Standard error response

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string (validation_error \\| unauthorized \\| forbidden \\| not_found \\| internal_error) | yes | Machine-readable error code. See https://docs.authalla.com/docs/errors. |
| `message` | string | yes | Human-readable error message |
| `documentation_url` | string (uri) | yes | Link to this error code on the Errors page. |
