API Reference
Profile, Connections & Sessions

Profile, Connections & Sessions

User-scoped endpoints behind the session cookie (profile also accepts a bearer token).


GET /profile

curl -s -b cookies.txt "$ISSUER/profile"
{ "success": true, "data": { "user_id": "b3f1c92e-…", "display_name": "Amina Juma", "avatar_url": null } }

Missing profile data returns empty strings/nulls — not an error. Auth: session or bearer.

PATCH /profile

Partial update; omitted fields unchanged.

{ "display_name": "Amina J.", "avatar_url": "https://cdn.example.com/a.png" }

→ 200 with the updated object. Error: 400 display name must be 100 characters or fewer.

This is what feeds the name/picture userinfo claims (profile scope).


GET /connections

Every app the user has granted, newest grant first. Auth: session.

curl -s -b cookies.txt "$ISSUER/connections"
{
  "success": true,
  "data": [
    {
      "client_id": "bajeti-web-x7k2p9",
      "client_name": "Bajeti Web",
      "scope": "openid profile",
      "granted_at": "2026-07-17T12:00:00Z"
    }
  ]
}

DELETE /connections/{client_id}

The kill switch for one app. Deletes consent + revokes the refresh-token family + kills live access tokens — all immediately.

curl -s -b cookies.txt -X DELETE "$ISSUER/connections/bajeti-web-x7k2p9"
# { "success": true, "message": "connection revoked" }

Equivalent endpoint: POST /oauth/revoke with the same effect.


GET /sessions

Active browser sessions, most-recently-used first. Auth: session.

curl -s -b cookies.txt "$ISSUER/sessions"
{
  "success": true,
  "data": [
    {
      "id": "5e8a1c2b-…",
      "device_label": null,
      "ip_address": "41.86.176.12",
      "created_at": "2026-08-20T14:22:05Z",
      "last_used_at": "2026-08-26T08:15:31Z",
      "is_current": true
    },
    {
      "id": "c2d94f7a-…",
      "device_label": "google",
      "ip_address": "197.157.200.44",
      "created_at": "2026-07-02T10:03:00Z",
      "last_used_at": "2026-08-25T19:48:12Z",
      "is_current": false
    }
  ]
}

device_label = provider name (google/github) for social logins, else null. is_current marks the caller's own session — protect it in your UI ("Sign out everywhere else" = delete every row where is_current === false).

DELETE /sessions/{id}

Revoke one session (ownership-checked). Revoking your own session acts like logout.

curl -s -b cookies.txt -X DELETE "$ISSUER/sessions/c2d94f7a-…"
# { "success": true, "message": "session revoked" }   (404 "session not found")