/api/v1/users/:user_id/tos
Whether an account has accepted the terms of service. Defined in
crates/rest/src/users.rs.
The answer matters outside the website: GET /oauth/authorize sends a user
who has not accepted the terms to /tos-accept before it will issue any
authorization code, so an account that has not answered cannot grant an OAuth
authorization.
GET
Returns the account's answer.
The caller must be the account's owner or an administrator. A guest, an OAuth token and a member reading someone else are all refused with 403 — this is not public information.
Example
GET /api/v1/users/28dbb0bf-0fdc-40fe-ae5a-dde193f9fea8/tos Cookie: sid=b8be19ef-2d61-44de-b7d2-9c34ccb8a763
{
"type": "GetUserTos",
"id": "28dbb0bf-0fdc-40fe-ae5a-dde193f9fea8",
"is_tos_accepted": true,
"acceptation_date": "2026-08-01T12:00:00.000Z"
}
| Field | Type | Meaning |
|---|---|---|
id | UUID | The account. |
is_tos_accepted | boolean | Whether the terms are accepted as of now. |
acceptation_date | timestamp or null | When they were accepted. null while they are not. |
Errors
| Status | Body | When |
|---|---|---|
| 403 | {"error": "forbidden"} | Not the owner and not an administrator. |
| 404 | {"error": "not found"} | No such account. |
| 500 | {"error": "internal error"} | — |
POST
Accepts the terms. Takes no body and answers 200 with an empty body.
Only the account holder may do this, administrators included: accepting terms on somebody else's behalf is not a thing an administrator should be able to do, so the check here is strict equality on the user id rather than the usual "owner or administrator".
There is no way to un-accept. Acceptance is an event, and the row records when it happened.
Example
POST /api/v1/users/28dbb0bf-0fdc-40fe-ae5a-dde193f9fea8/tos Cookie: sid=b8be19ef-2d61-44de-b7d2-9c34ccb8a763
HTTP/1.1 200 OK
Errors
| Status | Body | When |
|---|---|---|
| 403 | {"error": "forbidden"} | The caller is not this account. |
| 404 | {"error": "not found"} | No such account. |
| 409 | {"error": "already accepted"} | The terms were already accepted. |
| 500 | {"error": "internal error"} | — |