---
title: "Create the tenant, user and membership rows for a verified token, idempotently"
method: POST
path: "/v1/me/provision"
tags: ["me"]
---

# Create the tenant, user and membership rows for a verified token, idempotently

`POST /v1/me/provision`

## Request

- Base URL: `https://api.sixminute.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.sixminute.ai/v1/me/provision`
- Auth: HTTP bearer

Safe to call on every sign-in. A token that names an organisation is provisioned straight away and the answer's `action` is `ready`. A token that names none has its PENDING INVITATIONS looked up by the address WorkOS holds for it: the oldest is accepted, which creates the WorkOS membership with the invited role, the rows follow, and `action` is `refresh` because the caller's token predates that membership and must be refreshed with `tenant.workos_org_id`. Nobody invited: 403 `no-firm`, and nothing is written (D-73).

## Request body

- object
  - `tenant_name` string
  - `email` string, email
  - `name` string

## Response `200`

The rows, and what the caller must do next.

- object
  - `user` object, required
    - `id` string, required
    - `workos_user_id` string, required
    - `email` string, email, required
    - `name` string
    - `avatar` object, nullable
      - `updated_at` string, date-time, required
    - `created_at` string, date-time, required
  - `tenant` object, required
    - `id` string, required
    - `workos_org_id` string, required
    - `name` string, required
    - `policy` object
      - `excluded_bundles` string[]
      - `security_tier` 'standard' | 'confidential'
      - `raw_archive` boolean
      - `research_export` boolean
      - `context_retention_days` integer
      - `demo` object
        - `enabled` boolean, required
    - `settings` object
      - `unit_minutes` integer
      - `narrative` object
        - `max_chars` integer, nullable
        - `language` 'nl' | 'en' | 'de' | 'fr' | 'es' | 'it' | 'pt' | 'pl' | 'sv' | 'da' | 'en-GB' | 'pt-PT', nullable
        - `guidance` string
        - `lowered_to_system` object, nullable
          - `kind` 'urios' | 'legalsense' | 'fake', required
          - `at` string, date-time, required
      - `capture` object
        - `always_on` 'member_choice' | 'enforced'
      - `timesheet_pet` object
        - `on` boolean
        - `on_since` string, date-time, nullable
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `connector` object, nullable, required
      - `kind` 'urios' | 'legalsense' | 'fake', required
      - `narrative_max_chars` integer, nullable, required
      - `note_max_chars` integer, nullable
      - `supplies_languages` boolean
      - `identity` 'mapping' | 'sign_in'
    - `administrators` string[]
  - `member` object, required
    - `id` string, required
    - `user_id` string, required
    - `role` 'timekeeper' | 'billing' | 'admin', required
    - `active` boolean
    - `narrative_language` 'nl' | 'en' | 'de' | 'fr' | 'es' | 'it' | 'pt' | 'pl' | 'sv' | 'da' | 'en-GB' | 'pt-PT', nullable
    - `entry_size` 'fewer' | 'balanced' | 'more', nullable
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `system_link` object, nullable
      - `system` 'urios' | 'legalsense' | 'fake', required
      - `name` string, required
      - `code` string, nullable, required
      - `status` 'connected' | 'needs_reconnect'
      - `synced` boolean
      - `narrative_language` 'nl' | 'en' | 'de' | 'fr' | 'es' | 'it' | 'pt' | 'pl' | 'sv' | 'da' | 'en-GB' | 'pt-PT', nullable
      - `approval` 'review' | 'auto'
    - `time_zone` string, nullable
    - `time_zone_next` string, nullable
    - `time_zone_next_from` string, nullable
  - `permissions` string[]
  - `judgment_pipeline` 'standard' | 'jev'
  - `legalsense_connector` boolean
  - `timesheet_pet` boolean
  - `calendar_offered` boolean
  - `swallow_short_pauses` boolean
  - `pipeline_shadow` boolean
  - `narrative_limit` object
    - `limit` integer, required
    - `by` 'firm' | 'house' | 'system' | 'max', required
  - `practice` object, nullable
  - `narrative_style` boolean
  - `action` 'ready' | 'refresh'

## Other responses

- `400`: The body, query or path did not validate; `errors` lists the fields.
- `401`: No bearer token, or one that does not verify or has expired.
- `403`: The token verified but may not do this: no organisation, not provisioned, wrong role, or a device problem.
- `429`: Too many requests; `Retry-After` says how long to wait.
- `502`: An upstream this service depends on failed or answered nonsense.
- `503`: A capability this service was not configured with, or a practice system that could not be reached; the `type` says which.

## Changes

- **2026-11-04** `605577eadc10`: 2 info
  - added the optional property `tenant/settings/timesheet_pet` to the response with the `200` status
  - added the optional property `timesheet_pet` to the response with the `200` status

[Operation history](https://skmtc.dev/sixminute/apis/sixminute-api/changes/v1/me/provision/post.md)

---

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