> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thecleanlife.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Response Models

> All response shapes with full field descriptions.

Complete reference for all response shapes returned by the Partner API.

***

## Catalog Category (List Services)

Returned by: `GET /partners/services` (each item in paginated `data`)

```json theme={null}
{
  "id": "cccccccc-0000-0000-0000-000000000003",
  "code": "REGULAR_CLEANING",
  "nameEn": "Regular Cleaning",
  "nameAr": "تنظيف عادي",
  "descriptionEn": "Standard home cleaning service",
  "descriptionAr": "خدمة تنظيف منزلية",
  "isActive": true,
  "services": [
    {
      "id": "dddddddd-0000-0000-0000-000000000004",
      "name": "2 Hours Cleaning",
      "price": 150
    }
  ]
}
```

| Field           | Type           | Description                                           |
| --------------- | -------------- | ----------------------------------------------------- |
| `id`            | UUID           | Category ID (display only — do not send when booking) |
| `code`          | string \| null | Category code                                         |
| `nameEn`        | string         | English name                                          |
| `nameAr`        | string         | Arabic name                                           |
| `descriptionEn` | string         | English description                                   |
| `descriptionAr` | string         | Arabic description                                    |
| `isActive`      | boolean        | Whether the category is active                        |
| `services`      | array          | Nested services available at the requested address    |

**Nested service object**

| Field   | Type   | Description                                                                                                                                                                                                                                                              |
| ------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`    | UUID   | Service ID — use as `serviceId` in booking requests                                                                                                                                                                                                                      |
| `name`  | string | Service name                                                                                                                                                                                                                                                             |
| `price` | number | Price in SAR for your partner account. `0` means deferred payment (no upfront charge). When a positive partner-specific price is configured, that value is returned; otherwise the platform default price applies. This is the amount locked on the booking at creation. |

***

## Timeslots Response

Returned by: `GET /partners/timeslots/available`

```json theme={null}
{
  "date": "2026-06-20",
  "slots": [
    {
      "startAt": "09:00",
      "endAt": "12:00"
    }
  ]
}
```

| Field             | Type   | Description                           |
| ----------------- | ------ | ------------------------------------- |
| `date`            | string | Requested service date (`YYYY-MM-DD`) |
| `slots`           | array  | Available timeslots                   |
| `slots[].startAt` | string | Start time (Riyadh local)             |
| `slots[].endAt`   | string | End time (Riyadh local)               |

***

## Booking Response

Returned by: `POST /partners/bookings`, `GET /partners/bookings/:id/status`, `PATCH /partners/bookings/:id/cancel`, `POST /partners/bookings/:id/confirm-payment`

```json theme={null}
{
  "bookingId": "11111111-0000-0000-0000-000000000001",
  "externalReference": "ORDER-20260615-001",
  "appointmentId": "22222222-0000-0000-0000-000000000002",
  "status": "in progress",
  "paymentStatus": "NOT_REQUIRED",
  "trackingReference": "SA-0042",
  "date": "2026-06-20T00:00:00.000Z",
  "timeslot": {
    "startAt": "09:00",
    "endAt": "12:00",
    "endsAtNextDay": false
  },
  "appointment": {
    "id": "22222222-0000-0000-0000-000000000002",
    "name": "SA-0042",
    "status": "Scheduled",
    "scheduledStartDateTime": "2026-06-20T09:00:00+03:00",
    "scheduledEndDateTime": "2026-06-20T12:00:00+03:00"
  }
}
```

| Field                                | Type    | Nullable | Description                                                                                                   |
| ------------------------------------ | ------- | -------- | ------------------------------------------------------------------------------------------------------------- |
| `bookingId`                          | UUID    | No       | CleanLife booking identifier                                                                                  |
| `externalReference`                  | string  | Yes      | Your external reference, or `null` if not provided                                                            |
| `appointmentId`                      | UUID    | Yes      | Service appointment ID; `null` if not yet assigned                                                            |
| `status`                             | string  | No       | Booking status (see [Enums](enums#booking-status))                                                            |
| `paymentStatus`                      | string  | No       | Payment status (see [Enums](enums#payment-status))                                                            |
| `trackingReference`                  | string  | No       | Human-readable reference for customer communication. Falls back to `bookingId` if no appointment is assigned. |
| `date`                               | string  | No       | Service date                                                                                                  |
| `timeslot.startAt`                   | string  | No       | Appointment start time                                                                                        |
| `timeslot.endAt`                     | string  | No       | Appointment end time                                                                                          |
| `timeslot.endsAtNextDay`             | boolean | No       | `true` if the appointment spans midnight                                                                      |
| `appointment`                        | object  | Yes      | Service appointment details; `null` if not assigned                                                           |
| `appointment.id`                     | UUID    | —        | Appointment ID                                                                                                |
| `appointment.name`                   | string  | —        | Appointment name (tracking reference)                                                                         |
| `appointment.status`                 | string  | —        | Appointment status (see [Enums](enums#appointment-status))                                                    |
| `appointment.scheduledStartDateTime` | string  | —        | ISO 8601 scheduled start datetime                                                                             |
| `appointment.scheduledEndDateTime`   | string  | —        | ISO 8601 scheduled end datetime                                                                               |

***

## Contact Response

Returned by: `POST /partners/contacts`

```json theme={null}
{
  "id": "aaaaaaaa-0000-0000-0000-000000000001",
  "name": "Ahmed Ali",
  "phone": "+966500000000",
  "addressId": "bbbbbbbb-0000-0000-0000-000000000002",
  "isNewContact": true
}
```

| Field          | Type    | Nullable | Description                                                            |
| -------------- | ------- | -------- | ---------------------------------------------------------------------- |
| `id`           | UUID    | No       | Contact ID — pass as `contactId` when creating a booking               |
| `name`         | string  | No       | Contact name                                                           |
| `phone`        | string  | No       | Normalized phone number                                                |
| `addressId`    | UUID    | Yes      | Service address ID when address fields were provided; `null` otherwise |
| `isNewContact` | boolean | No       | `true` when a new contact record was created                           |

***

## Cancellation Reason (List)

Returned by: `GET /partners/bookings/cancellation-reasons` (each item in `data`)

```json theme={null}
{
  "id": "aaaaaaaa-0000-0000-0000-000000000001",
  "nameEn": "Customer changed plans",
  "nameAr": "العميل غيّر خطته"
}
```

| Field    | Type   | Description                                  |
| -------- | ------ | -------------------------------------------- |
| `id`     | UUID   | Pass as `reasonId` when cancelling a booking |
| `nameEn` | string | English label                                |
| `nameAr` | string | Arabic label                                 |

***

## Success Envelope

All single-resource responses are wrapped in:

```json theme={null}
{
  "success": true,
  "data": { /* resource object */ }
}
```

***

## Paginated Envelope

All list responses are wrapped in:

```json theme={null}
{
  "success": true,
  "data": [ /* array of resource objects */ ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 100,
    "totalPages": 5
  }
}
```

***

## Error Envelope

```json theme={null}
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable description",
    "details": { /* optional, for validation errors */ },
    "requestId": "uuid"
  }
}
```
