# Bookings - Optimization

AI-powered booking table optimization

## PATCH /api/v1/bookings/{id}/lock

Toggle booking resource lock

Lock or unlock a booking to its assigned table. Locked bookings will not be moved by the optimizer.

**Permissions:** ⚪ `bookings.manage`

Path parameters:
- `id` (string, required) — Booking ID

Request body:

```ts
{
  locked: boolean
}
```

Response 200 — Default Response

```ts
{
  status: "success"
  data: {
    customFields?: Array<{
        fieldId?: string
        key?: string
        label?: string
        group?: string
        type?: string
        displayValue?: string
        value?: unknown // The stored value; its JSON type follows the field type
        version?: integer
        status?: string
      }>
    metadata?: {
      customFields?: Record<string, unknown>
    } | null
    id: string // uuid
    locationId: number
    tableId?: string | null // uuid
    bookingDate: string // date
    startTime: string
    endTime: string
    timezone: string
    primaryUserId?: number | null
    guestCount: number
    occasion?: "none" | "birthday" | "anniversary" | "business" | "date" | "celebration" | "other"
    specialRequests?: string | null
    internalNotes?: string | null
    notes?: Array<{
        uuid: string // uuid
        note: string
        sortOrder: number
        createdByRetailerUserId?: number | null
        updatedByRetailerUserId?: number | null
        createdAt: string // date-time
        updatedAt: string // date-time
      }>
    status: "pending" | "confirmed" | "checked_in" | "seated" | "completed" | "cancelled" | "no_show"
    paymentType?: "none" | "deposit" | "full_prepayment"
    depositAmountCents?: number | null
    purchaseId?: number | null
    confirmationCode: string
    bookingSource?: "direct" | "website" | "app" | "phone" | "walkin" | "third_party"
    estimatedRevenueCents?: number | null
    guestName?: string | null
    guestEmail?: string | null
    guestPhone?: string | null
    createdAt: string // date-time
    updatedAt: string // date-time
    confirmedAt?: string | null // date-time
    seatedAt?: string | null // date-time
    completedAt?: string | null // date-time
    cancelledAt?: string | null // date-time
    tabId?: string | null
    defaultTabStrategy: "single" | "per_resource"
    resources: Array<{
        qrCodeId: string // uuid
        isPrimary: boolean
        position: integer
      }>
    userName?: string | null
    userEmail?: string | null
    userPhone?: string | null
    tableName?: string | null
    location?: {
      id?: number
      name?: string | null
      city?: string | null
      latitude?: number | null
      longitude?: number | null
      logoImageUrl?: string | null
    } | null
    attribution?: {
      firstTouch?: {
        capturedAt: string // date-time
        utmSource?: string
        utmMedium?: string
        utmCampaign?: string
        utmContent?: string
        utmTerm?: string
        referrer?: string
        landingPage?: string
      }
      bookingTouch?: {
        capturedAt: string // date-time
        utmSource?: string
        utmMedium?: string
        utmCampaign?: string
        utmContent?: string
        utmTerm?: string
        referrer?: string
        landingPage?: string
      }
      reportedSource?: string
      recordedAt: string // date-time
    } | null
  }
  meta: {
    requestId: string
    timestamp: string // date-time
    executionTimeMs: number
  }
}
```

## POST /api/v1/locations/{locationId}/bookings/optimize

Optimize booking table assignments

Run the booking optimization algorithm to improve table utilization. Use dryRun=true to preview changes without applying them.

**Permissions:** ⚪ `bookings.manage`

Query parameters:
- `date` (string, required) — Date to optimize (YYYY-MM-DD)

Path parameters:
- `locationId` (number, required) — Location ID

Request body:

```ts
{
  dryRun?: boolean
}
```

Response 200 — Default Response

```ts
{
  status: "success"
  data: {
    changes: Array<{
        bookingId: string // uuid
        guestName?: string | null
        partySize: number
        fromTableId?: string | null // uuid
        fromTableName?: string | null
        toTableId: string // uuid
        toTableName: string
        reason: string
      }>
    stats: {
      totalBookings: number
      optimizedCount: number
      lockedCount: number
      tablesFreed: number
      utilizationImprovement: number
    }
  }
  meta: {
    requestId: string
    timestamp: string // date-time
    executionTimeMs: number
  }
}
```
