API reference
Accounts API reference
Login, sessions, accounts, organizations, invitations and API-key management routes.
Every route of the accounts service at https://accounts.aggre.org that a signed-in person's browser uses. Read the accounts API overview first: these routes take a session cookie (not an API key), an allowed Origin and, for anything but GET, the header X-Aggre-CSRF: 1. The OpenAPI file is /openapi/accounts.yaml (also JSON).
The platform-staff routes under /v1/admin/* are not part of this reference.
Public console configuration (login buttons, limits, defaults)#
GET /v1/config
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | Config | yes |
Start a login (full-page navigation, answers 302 to the provider)#
GET /login/{provider}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
provider | path | yes | string | |
audience | query | no | app | admin (default app) | |
return_to | query | no | string, uri | Absolute URL on the audience origin; otherwise ignored. |
link | query | no | 1 | Attach this provider to the signed-in user. |
Errors: 302, 400, in the shared envelope (Errors).
OAuth redirect URI. Sets the session cookie and answers 302 to return_to or {origin}/login?error=<code>#
GET /login/callback/{provider}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
provider | path | yes | string | |
code | query | no | string | |
state | query | no | string | |
error | query | no | string |
Errors: 302, 400, in the shared envelope (Errors).
Revoke the current session and clear its cookie#
POST /v1/auth/logout
Response 204.
Revoke every session of the user (both audiences)#
POST /v1/auth/logout-all
Response 204.
The signed-in user, identities, memberships and session#
GET /v1/me
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | Me | yes |
Errors: 401, in the shared envelope (Errors).
Delete the personal account (keys revoked, identities and sessions removed, handle stays reserved)#
DELETE /v1/me
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
confirm | query | yes | string | Must equal the user's handle. |
Response 204.
Errors: 401, 409, in the shared envelope (Errors).
Unlink a login method (409 if it is the last one)#
DELETE /v1/me/identities/{identity_id}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
identity_id | path | yes | string, uuid |
Response 204.
Errors: 404, 409, in the shared envelope (Errors).
Is this handle usable? (signed-in users only)#
GET /v1/handles/{handle}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | object | yes | |
data.handle | string | yes | |
data.available | boolean | yes | |
data.reason | invalid | reserved | taken | null | no |
One account you can see (self, member, or staff)#
GET /v1/accounts/{handle}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | Account | yes |
Errors: 404, in the shared envelope (Errors).
Change display_name and/or handle (user: self; org: owner). First rename free, then once per 30 days.#
PATCH /v1/accounts/{handle}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
display_name | nullable, string | no | |
handle | string | no |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | Account | yes |
Errors: 403, 404, 409, in the shared envelope (Errors).
Request counts per UTC day and per key over the last N days#
GET /v1/accounts/{handle}/usage
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string | |
days | query | no | integer, 1–90, default 30 |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | Usage | yes |
Errors: 404, in the shared envelope (Errors).
Audit log of the account (owner/admin/staff), newest first#
GET /v1/accounts/{handle}/audit
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string | |
limit | query | no | integer, 1–100, default 50 | |
before | query | no | integer, int64 | Return entries with id < before. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | array of AuditEntry | yes | |
next_before | nullable, integer, int64 | yes |
Errors: 403, 404, in the shared envelope (Errors).
Keys of the account, newest first, revoked ones included (max 200). Never contains secrets.#
GET /v1/accounts/{handle}/api-keys
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | array of ApiKey | yes |
Errors: 404, in the shared envelope (Errors).
Create a key. The secret is in the response once and never again.#
POST /v1/accounts/{handle}/api-keys
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | |
usage_limit | nullable, integer, int64 | no | Omit = server default. null (Unlimited) and values above the default: staff only. |
usage_period | day | month | total | no | |
rate_policy | default | exempt | no | exempt: staff only. |
internal | boolean, default false | no | true gives the key the internal scope (the data API's /v1/internal/* per-row routes). Platform staff on an admin session, freshly signed in; anyone else gets 403. |
ip_allowlist | array of string | no | |
expires_at | nullable, string, date-time | no |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
data | ApiKey | yes | |
secret | string | yes |
Errors: 400, 403, 404, 409, in the shared envelope (Errors).
Rename a key or replace its ip_allowlist#
PATCH /v1/accounts/{handle}/api-keys/{key_id}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string | |
key_id | path | yes | string, uuid |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | no | |
ip_allowlist | array of string | no | CIDRs or bare addresses; [] = open. |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | ApiKey | yes |
Errors: 400, 403, 404, in the shared envelope (Errors).
Revoke a key (takes effect on the gateway within ~30 s)#
DELETE /v1/accounts/{handle}/api-keys/{key_id}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string | |
key_id | path | yes | string, uuid |
Response 204.
Errors: 403, 404, in the shared envelope (Errors).
Create an org; the caller becomes its owner#
POST /v1/orgs
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
handle | string | yes | |
display_name | string | no |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
data | Account | yes |
Errors: 400, 409, in the shared envelope (Errors).
Delete an org (owner). Keys are revoked, memberships removed, the handle stays reserved.#
DELETE /v1/orgs/{handle}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string | |
confirm | query | yes | string | Must equal the org handle. |
Response 204.
Errors: 403, 404, in the shared envelope (Errors).
Members of the org (any member, or staff)#
GET /v1/orgs/{handle}/members
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | array of Member | yes |
Errors: 404, in the shared envelope (Errors).
Change a member's role (owner). 409 if it would leave no owner.#
PATCH /v1/orgs/{handle}/members/{user_handle}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string | |
user_handle | path | yes | string |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
role | Role | yes |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | Member | yes |
Errors: 403, 404, 409, in the shared envelope (Errors).
Remove a member, or leave (user_handle = yourself). 409 for the last owner.#
DELETE /v1/orgs/{handle}/members/{user_handle}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string | |
user_handle | path | yes | string |
Response 204.
Errors: 403, 404, 409, in the shared envelope (Errors).
Pending invitations (owner/admin)#
GET /v1/orgs/{handle}/invitations
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | array of Invitation | yes |
Errors: 403, 404, in the shared envelope (Errors).
Invite an e-mail address. Re-inviting the same address replaces the pending invitation. No e-mail is sent; share the link.#
POST /v1/orgs/{handle}/invitations
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string |
Request body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
email | string, email | yes | |
role | Role | no |
Response 201
| Field | Type | Required | Description |
|---|---|---|---|
data | Invitation | yes | |
token | string | yes | One-time secret; the console links to {app}/invitations/{token}. |
Errors: 400, 403, 404, 409, in the shared envelope (Errors).
Revoke a pending invitation#
DELETE /v1/orgs/{handle}/invitations/{invitation_id}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
handle | path | yes | string | |
invitation_id | path | yes | string, uuid |
Response 204.
Errors: 403, 404, in the shared envelope (Errors).
What an invitation link is for (no session needed, so the page can ask the visitor to sign in first)#
GET /v1/invitations/{token}
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
token | path | yes | string |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | object | yes | |
data.org | object | yes | |
data.role | Role | yes | |
data.email_hint | string | yes | |
data.expires_at | string, date-time | yes |
Errors: 404, in the shared envelope (Errors).
Join the org. The caller's verified primary e-mail must equal the invited address (403 email_mismatch).#
POST /v1/invitations/{token}/accept
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
token | path | yes | string |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
data | object | yes | |
data.org | Account | yes | |
data.role | Role | yes |
Errors: 401, 403, 404, 409, in the shared envelope (Errors).
Generated from contracts/accounts.openapi.yaml when the site is built, so it matches the API contract.