# Account sessions

Inspect and revoke the signed-in consumer user's root SSO login sessions.
These records represent root logins, not individual application refresh-token
sessions. A username such as `root` is an account label; it does not determine
the type of session. One root can have token descendants for several apps.

The [Sessions page](https://user.m7.org/members/settings/sessions) provides the
browser workflow. Click a session card to inspect it; eligible active records
show a revocation × with confirmation. Session payloads remain encrypted and
are not returned by these endpoints. Public lifecycle metadata can be inspected
without asking the original browser to decrypt that payload.

## Authentication and endpoints

Send the signed-in consumer user's access token and the required companion
headers for a [DPoP- or fingerprint-bound token](https://m7.org/docs/api/api.user.m7.org/authorization.md). The API
must authorize the corresponding `account.me.session.search`,
`account.me.session.view` or `account.me.session.revoke` scope. Machine credentials
do not authorize revocation. Ownership is derived from validated credentials;
request fields cannot select another user.

| Method | Route under `https://api.user.m7.org/api/v2` | Input |
| --- | --- | --- |
| POST | `/account/me/session/search` | Optional `id`, `status` and [pagination](https://m7.org/docs/api/api.user.m7.org/README.md#pagination) |
| POST | `/account/me/session/view` | Required `id` |
| POST | `/account/me/session/revoke` | Required `id` |

`id` is the local 64-character hexadecimal session record identifier returned
by search. It is not the OAuth client ID, a token, or the OIDC `sid`. Do not
send a raw token to these routes.

## Search and inspect

```bash
curl -sS https://api.user.m7.org/api/v2/account/me/session/search \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"status":"active","limit":20,"page_number":1}'
```

Search always uses the caller's user ID and `scope: user`. The default status
is `active`. Supported status filters are `reserve`, `active`, `logged_out`,
`expired`, `revoked` and `any`; `id` is an exact match. Status filtering occurs
before pagination. Active means the stored row is active and its expiry is in
the future. It does not establish that the browser is online or that a fresh
Identity state check would report the root as active.

Search records include `id`, `uid`, `scope`, `status`, `created`, `modified`,
`accessed`, `expires`, `is_expired` and decoded `public_data`. View adds the
record's principal type and host. Public metadata may include account label,
organization, IP/browser information and termination details. It does not expose
the encrypted session payload. A public termination explanation, when present,
is `public_data.identity_termination_public_reason`; a private operator note is
not included. Display public text as text, never executable HTML.

## Revoke a root login

```bash
curl -sS https://api.user.m7.org/api/v2/account/me/session/revoke \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"id":"SESSION_RECORD_ID_FROM_SEARCH"}'
```

Replace the placeholder with the exact returned 64-character ID. Revocation
checks ownership, the configured consumer SSO host, user scope, active/unexpired
state and stored root context. A stale legacy record without that root reference
cannot be revoked through this operation. Caller-supplied user, host or root
references cannot change the target authority.

The operation closes the local record as `revoked`, then revokes its Identity
root and token descendants. After confirmation it sends registered back-channel
logout notifications to participating applications. It does not load front-channel
iframes: the session's browser may be elsewhere or unavailable. This operation
terminates the root family, not just one application's refresh token.

A completed response has this shape (illustrative IDs):

```json
{
  "status": 1,
  "comment": "REVOKED",
  "data": {
    "id": "SESSION_RECORD_ID_FROM_SEARCH",
    "status": "revoked",
    "identity_confirmed": true,
    "identity_attempted": true,
    "pending": false,
    "backchannel": {
      "complete": true,
      "attempted": 1,
      "delivered": 1,
      "failed": 0,
      "results": [{"client_id": "PUBLIC_CLIENT_ID", "ok": true, "status": 200}]
    }
  }
}
```

| Result field | Meaning |
| --- | --- |
| `identity_confirmed` | Root-family revocation has been confirmed. |
| `identity_attempted` | This invocation attempted upstream revocation; an already completed request can return false. |
| `pending` | Identity revocation or back-channel delivery still needs completion. |
| `backchannel` | Delivery summary, or null before a result exists. Per-client failures may include recognized `receiver_reason` and `receiver_trace_id`. |

A pending result still has `status: 1` and local `data.status: revoked`, with
`comment: REVOCATION_PENDING` and `data.pending: true`. It must not be presented
as fully completed. The service retains pending work for reconciliation; a
completed repeat request is idempotent. A zero-attempt complete summary can
mean no applicable back-channel receiver was registered.

Show the actual API `comment` in action feedback. Treat `status: 0` as failure,
not as an empty successful search. Failure comments can report an invalid ID,
a missing/unowned session, missing root context, or an inactive session.
Use `data.pending` for completed-versus-pending handling rather than inferring
it from HTTP success or translating every result into a generic success banner.

Revoking the current root can invalidate the credentials used for the request;
a subsequent refresh or list request may require signing in again. The
back-channel success count records receiver acceptance, not proof of remote
application-session deletion. The current M7 Web/PHP SDK receiver validates
and acknowledges only. See the
[SSO logout guide](https://m7.org/docs/api/sso.user.m7.org/logout-notifications)
for the receiving contract and SDK limitation.
