Skip to content

Operator Users

Taxi & Private HireProductsACL › Operator Users

Generally available

Operator console users — the people who log in to the operator console to manage trips, customers, drivers, etc. Each User has a permission profile (determines what they can read/write), optional fleet and region scoping, email/password credentials, and optional passkey credentials. Authenticates via the USER auth method.

Example request

POST /client/{clientId}/user

{
  "firstName": "<string>",
  "lastName": "<string>",
  "email": "<string>",
  "userType": "HUMAN",
  "password": "<string>",
  "permissionProfile": {
    "id": "<id>"
  },
  "defaultRegion": {
    "id": "<id>"
  },
  "regions": [
    {
      "id": "<id>"
    }
  ]
}

Example shape, derived from the User fields — indicative, not the authoritative schema (that arrives with the API reference).

Endpoints

MethodPath
POST /client/{clientId}/user · primary
GET /client/{clientId}/user/{userId}
POST /client/{clientId}/user/{userId}

Full request/response schemas and an interactive explorer will live in the API reference (coming soon).

Fields

FieldTypeDescription
firstName string Given name of the operator user. Surfaced on audit logs + the operator console header.
lastName string Family name of the operator user.
email string Login email — unique per tenant (UNIQ_IDENTIFIER_EMAIL). Acts as the username for the USER auth method.
roles array Symfony security roles array (ROLE_ADMIN, ROLE_USER, etc.). Implicit ROLE_USER is added at runtime. Permission resolution still goes through PermissionProfile for fine-grained ACL.
userType UserType · HUMAN | AGENT Whether this staff member is a HUMAN operator or an AI AGENT acting as staff. Both authenticate via the USER auth method and are bound by the same PermissionProfile; the distinction drives audit attribution and lets the agent surface be governed / revoked independently.
password string Bcrypt hash of the user's password. writeOnly serialization — never read in responses. Set via setPassword() with raw input that the auth layer hashes.
permissionProfile PermissionProfile PermissionProfile that defines what this user can read/write. The runtime permission check walks this profile, not the bare `roles` array.
defaultRegion Region Default Region the user logs into. Drives the initial RegionFilter scope on login; user can switch regions if they have access to several.
regions Collection Regions this user is permitted to operate in. Multi-select; gates the region picker + RegionFilter access.
clientId bigint Tenant scope. Every tenant-aware entity carries this; `ClientFilter` enforces row-level isolation on read; the multi-tenancy routing layer (`/client/{clientId}`) sets it at create time. Surfaced only under `admin` / `tripLog` groups — never to end users.
internalKey string Optional client-supplied external reference / idempotency key. When present, lets external systems correlate platform-side records back to their own source-of-truth ids. Not persisted to a column — populated by the request handler when the caller sets it.
__objectType string Discriminator string (entity class short-name) emitted alongside the id in serialized output. Resolved at read time by `getObjectType()`; lets the FE dispatch entity-specific rendering without inspecting the URL.
id bigint Snowflake-style primary key (unsigned BIGINT). Generated by `IdFactory` at create time; surfaced to the FE / API as a `G`-prefixed string and stripped back to plain bigint server-side before Doctrine lookup.
createdDate integer Unix timestamp the row was first persisted. Set in the entity's PrePersist hook; never rewritten on subsequent updates.
updatedDate integer Unix timestamp the row was last touched. Bumped on every commit that hits the Doctrine UoW for this entity; drives FE invalidation + the listing change cursor.
passiveUpdatedDate int Read-through alias for `updatedDate` exposed under different serializer groups. Lets the FE distinguish "real edit" from "background touch" projections without changing the underlying column.
listingUpdatedDate int Listing-projection timestamp surfaced only under the `listMode` group. Driven by `TripCache` and other listing-shape refreshers separately from `updatedDate` so a listing rebuild doesn't trigger detail-page invalidation.