---
title: "List Users"
method: GET
path: "/users"
tags: ["users"]
---

# List Users

`GET /users`

Get a paginated list of all users. Manager access required.

Optionally filter by one or more trades using a comma-separated string:
`?trades=hvac,plumbing` returns users whose trades array contains at least one of those values.

## Query parameters

- `trades` string, nullable — Comma-separated trade filter (e.g. hvac,plumbing)
- `page` integer — Page number
- `page_size` integer — Number of users per page (max 100)

## Response `200`

Successful Response

- UserListResponse — Paginated list of users, returned by GET /users.
  - `users` UserResponse[], required
    - `id` string, uuid, required
    - `clerk_id` string, required
    - `email` string, email, required
    - `first_name` string, nullable
    - `last_name` string, nullable
    - `phone_number` string, nullable
    - `twilio_phone_number` string, nullable
    - `role` 'sales_tech' | 'install' | 'noso_sales_admin', nullable
    - `auto_send_enabled` boolean
    - `invoice_synthesis_enabled` boolean
    - `push_all_inbound_messages` boolean
    - `office_route_enabled` boolean
    - `config` UserConfig — Strongly-typed configuration for a user. This model is stored in users.config column as JSONB.
      - `job_brief_enabled` boolean — Whether job brief feature is enabled for this user
      - `sender` SenderConfig — Customer-facing sender persona overrides for a user.
        - `display_name` string, nullable — Exact customer-facing display-name override for this sender
        - `technician_reference` 'by_name' | 'anonymous', nullable — Set for a sender who does not attend visits: every agent then writes as office staff, naming the field technician ('by_name') or not ('anonymous'). None = each lane's own default; a lane that is always office stays office.
        - `instructions` string, nullable — Optional wording and style guidance for this sender's messages
      - `sms_agent` SmsAgentUserConfig — Per-user overrides of the org-level SMS agent config.
        - `message_grouping_window_seconds` integer, nullable — Replaces the org grouping window for this user's conversations: the agent waits until the customer has been silent this long before acting. None = org default; 0 = act immediately.
      - `call_routing` CallRoutingUserConfig — Per-user inbound call routing overrides.
        - `office_forward_number` string, nullable — Inbound calls to this user's Twilio number ring here instead of their personal phone. Call routing ONLY: SMS forwarding, pushes, escalations and missed-call handling all stay normal, which is what separates this from office_route_enabled. Wins over office_route_enabled, campaign and after-hours redirects. Unparseable falls back to the personal number. None = ring the technician.
    - `trades` string[] — Trade types the technician belongs to (e.g. hvac, plumbing)
    - `priority` integer
    - `is_active` boolean, required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, nullable
  - `total_count` integer, required
  - `page` integer, required
  - `page_size` integer, required

## Other responses

- `404` — Not found
- `422` — Validation Error

---

[API](https://skmtc.dev/noso/apis/crucible-backend-api.md) · [All operations](https://skmtc.dev/noso/apis/crucible-backend-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/noso/crucible-backend-api/revisions/112efbdea3eb/schema)
