# Bookings - Users

Guest user search and creation for bookings

## POST /api/v1/users/guests

Resolve or create guest user

Resolve an existing guest or create a new one. At least email or phone is required. Returns 200 when an existing guest is resolved and 201 when a new guest is created.

**Permissions:** 🟢 `bookings.create`

Request body:

```ts
{
  name?: string
  email?: string // email
  phone?: string
}
```

Response 200 — Default Response

```ts
{
  status: "success"
  data: {
    id: number
    email?: string | null
    phone?: string | null
    name?: string | null
    lastSeenDate?: string | null // date-time
    bookingCount: number
    lastBookingDate?: string | null // date
    vip: boolean
    flags: Record<string, unknown>
    hasLocationOverride: boolean
  }
  meta: {
    requestId: string
    timestamp: string // date-time
    executionTimeMs: number
  }
}
```

Response 201 — Default Response

```ts
{
  status: "success"
  data: {
    id: number
    email?: string | null
    phone?: string | null
    name?: string | null
    lastSeenDate?: string | null // date-time
    bookingCount: number
    lastBookingDate?: string | null // date
    vip: boolean
    flags: Record<string, unknown>
    hasLocationOverride: boolean
  }
  meta: {
    requestId: string
    timestamp: string // date-time
    executionTimeMs: number
  }
}
```

## GET /api/v1/users/search

Search guest users

Search for guest users by email, phone, or name. Returns users with their booking history at the location.

**Permissions:** 🔵 `bookings.read`

Query parameters:
- `q` (string, required) — Search query (email, phone, or name)
- `locationId` (number, optional) — Location ID for booking history context
- `limit` (number, optional) — Maximum results to return

Response 200 — Default Response

```ts
{
  status: "success"
  data: {
    users: Array<{
        id: number
        email?: string | null
        phone?: string | null
        name?: string | null
        lastSeenDate?: string | null // date-time
        bookingCount: number
        lastBookingDate?: string | null // date
        vip: boolean
        flags: { … }
        hasLocationOverride: boolean
      }>
  }
  meta: {
    requestId: string
    timestamp: string // date-time
    executionTimeMs: number
  }
}
```
