HTTP API¶
Authenticated routes require a logged-in session unless DISABLE_AUTH=true.
Health¶
- GET
/healthz→{ "ok": true }
Auth¶
- GET
/login→ Login page (always available) - GET
/login/oidc→ Starts OIDC authorization code flow - GET
/auth/callback→ Completes login, stores session, redirects to/ - GET
/logout→ Clears session; if provider exposesend_session_endpoint, redirects there withpost_logout_redirect_uri
Session¶
- GET
/me→ current user session
Example
{
"sub": "42",
"email": "user@example.com",
"name": "User",
"picture": "https://.../avatar.png"
}
Users¶
- GET
/guest-users→ users inAK_GUESTS_GROUP_UUID - GET
/members-users→ users inAK_MEMBERS_GROUP_UUID - GET
/search-users?q=neo&limit=25→ lightweight search proxy
Shapes
// group listing
{
"group_name": "Guests",
"users": [
{"pk": 1, "username": "alpha", "email": "a@example.test"}
]
}
// search
{
"query": "neo",
"users": [
{"pk": 9, "username": "neo", "email": "n@example.test", "name": "Neo"}
]
}
Membership¶
- POST
/promote→ move user Guests → Members - POST
/demote→ move user Members → Guests - POST
/promote/bulk→ promote multiplepks(optionally send email) - POST
/demote/bulk→ demote multiplepks
Requests
// promote one
{"pk": 123, "send_mail": true}
// demote one
{"pk": 123}
// bulk promote
{"pks": [1,2,3], "send_mail": true}
// bulk demote
{"pks": [1,2,3]}
Responses
// single
{"status": "ok", "add": 200, "remove": 200}
// bulk
{
"count_ok": 2,
"count_failed": 1,
"results": [
{"pk": 1, "ok": true, "detail": {"add": 200, "remove": 200}},
{"pk": 2, "ok": false, "detail": "..."}
]
}
Invites¶
- POST
/invites→ create invitation; optionally sends email whenemailprovided and an invite URL is returned.
Request
{
"name": "Ada",
"username": "ada",
"email": "ada@example.test",
"single_use": true,
"expires_days": 7,
"flow": "invite-via-email"
}
Response
{
"pk": "abc123",
"invite_url": "https://auth.example/if/flow/invite-via-email/?itoken=abc123",
"expires": "2030-01-01T00:00:00Z",
"expires_friendly": "Tue, Jan 01, 2030, 12:00 AM UTC"
}
PWA assets¶
- GET
/manifest.webmanifest→ PWA manifest - GET
/sw.js→ Service worker (no-cache)
Errors¶
- Transport failures →
502 {"detail": "backend unavailable"} - Unhandled exceptions →
500 {"detail": "backend unavailable"} - Validation errors →
422with JSON body