---
title: "Accept terms of service"
method: POST
path: "/api/auth/accept-terms"
tags: ["internal"]
---

# Accept terms of service

`POST /api/auth/accept-terms`

## Request

- Base URL: `https://app.scanopy.net`
- URL: `https://app.scanopy.net/api/auth/accept-terms`
- Auth: none declared

## Response `200`

Terms accepted

- ApiResponseUser: Envelope for a successful response. Failures are sent with a non-2xx status and an `ApiErrorResponse` body instead.
  - `data` object: The result payload. Omitted on failure.
    - `display_settings` DisplaySettings: Per-user display preferences for dates and times in the UI. Stored as a JSONB blob with `#[serde(default)]` on the struct, so a stored object missing a key (including the `{}` every existing row starts with) reads as that field's default. Every default reproduces the UI's behaviour from before the setting existed, except `table_density`, which defaults to the tighter of its two layouts.
      - `clock` 'browser_default' | 'twelve_hour' | 'twenty_four_hour'
      - `date_order` 'browser_default' | 'iso' | 'day_first' | 'month_first'
      - `table_density` 'comfortable' | 'compact'
      - `time_zone` string, nullable: IANA time zone dates are shown in. `None` uses the browser's zone.
      - `timestamps` 'relative' | 'absolute'
      - `week_start` 'monday' | 'sunday'
    - `email` string, email, required: The user's email address, also their login identifier.
    - `email_settings` EmailSettings: Per-user toggles for the pausable email categories. Each field is named after one [`EmailCategory`] whose `pausable()` is true; required categories are never gated here. Stored as a JSONB blob, so new categories are added as new fields rather than via migration. New fields carry `#[serde(default = "default_true")]` so a category is opted in by default if its key is absent from the stored JSON.
      - `daemon_alerts` boolean: Send an alert when a daemon stops reporting.
      - `discovery_digest` boolean, required: Send a periodic summary of what discovery found.
      - `product_onboarding` boolean: Send getting-started guidance.
      - `product_updates` boolean: Send the release notes when this server upgrades.
      - `trial_and_usage` boolean: Send trial reminders and plan-usage warnings.
    - `email_verification_required` boolean: Whether the user must verify their email before the API serves their session (an org on a license plan, see `auth::verification_gate`). Computed and set like `terms_acceptance_required`.
    - `email_verified` boolean: Whether the user has verified their email address
    - `has_password` boolean: Whether the user has a password set — computed from password_hash, never stored in DB
    - `oidc_linked_at` string, date-time, nullable: When the account was linked to the identity provider.
    - `oidc_provider` string, nullable: Slug of the identity provider this account signs in through, when linked.
    - `organization_id` string, uuid, required: The organization that owns this record.
    - `permissions` 'Owner' | 'Admin' | 'Member' | 'Viewer', required
    - `site_ids` string[], required: The sites this entity applies to.
    - `terms_acceptance_required` boolean: Whether the user must accept the current terms before the API serves their session. Computed, never stored: set only on the signed-in user's own record (`/api/auth/me`, login, accept), false everywhere else.
    - `created_at` string, date-time, required: When this record was first created.
    - `id` string, uuid, required: Server-assigned unique identifier.
    - `updated_at` string, date-time, required: When this record was last modified.
  - `error` string, nullable: Not sent on a successful response. Failure messages arrive in an `ApiErrorResponse`.
  - `meta` ApiMeta, required: API metadata included in all responses
    - `api_version` integer, required: API version (integer, increments on breaking changes)
    - `server_version` string, required: Server version (semver)
  - `success` boolean, required: Always `true` on a successful response.

## Other responses

- `401`: Not authenticated

## Changes

- **2026-10-31** `c4e6ec11e35b`: 1 info
  - added the optional property `data/allOf[#/components/schemas/UserBase]/email_verification_required` to the response with the `200` status
- **2026-10-26** `c9d9d46d1ae8`: 1 info
  - api tag `auth` removed
- **2026-10-23** `9dda1a8b8ed1`: 5 breaking, 13 warning, 5 info
  - the `data/allOf[#/components/schemas/UserBase]/display_settings/clock` response's property type changed from no type to `string` for status `200`
  - the `data/allOf[#/components/schemas/UserBase]/display_settings/date_order` response's property type changed from no type to `string` for status `200`
  - the `data/allOf[#/components/schemas/UserBase]/display_settings/table_density` response's property type changed from no type to `string` for status `200`
  - the `data/allOf[#/components/schemas/UserBase]/display_settings/timestamps` response's property type changed from no type to `string` for status `200`
  - …19 more
- **2026-10-23** `586bf8d22950`: 1 warning
  - removed the optional property `data/allOf[#/components/schemas/UserBase]/terms_accepted_at` from the response with the `200` status
- **2026-10-14** `e2c8e252c025`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/scanopy/apis/scanopy-api/changes/api/auth/accept-terms/post.md)

---

[API](https://skmtc.dev/scanopy/apis/scanopy-api.md) - [All operations](https://skmtc.dev/scanopy/apis/scanopy-api/llms.txt) - [OpenAPI document](https://skmtc.dev/scanopy/apis/scanopy-api/revisions/966ba786bdb5?raw)
