# OpenClaw Chatbot API Integration Guide

This guide is for direct OpenClaw integration with Champion Spirit chatbot endpoints.

Scope:
- place analytics (access logs, bookings, orders)
- booking discovery (schedule and catalog)
- booking execution (create/update order, pay, verify bookings)

All routes below are under `/v1/chatbot`.

Machine-readable contract file for OpenClaw:
- `docs/OPENCLAW_TOOL_CONTRACT.json`

Protected HTTP endpoints (require `X-API-KEY`) to retrieve these documents:
- `GET /v1/chatbot/docs/OPENCLAW_CHATBOT_API.md`
- `GET /v1/chatbot/docs/OPENCLAW_TOOL_CONTRACT.json`

Full URLs:
- Staging markdown guide: `https://api.staging.championspirit.com/v1/chatbot/docs/OPENCLAW_CHATBOT_API.md`
- Staging JSON contract: `https://api.staging.championspirit.com/v1/chatbot/docs/OPENCLAW_TOOL_CONTRACT.json`
- Production markdown guide: `https://api.championspirit.com/v1/chatbot/docs/OPENCLAW_CHATBOT_API.md`
- Production JSON contract: `https://api.championspirit.com/v1/chatbot/docs/OPENCLAW_TOOL_CONTRACT.json`

## 1) Authentication

Required headers:

```http
X-API-KEY: <chatbot_api_key>
Accept: application/json
Content-Type: application/json
```

Base URLs:

```text
Staging:    https://api.staging.championspirit.com/v1/chatbot
Production: https://api.championspirit.com/v1/chatbot
```

All request examples below use the staging domain.

Notes:
- In production, invalid/missing API key returns `401`.
- In non-production, invalid API key may be allowed by middleware configuration.

## 2) Response Conventions

### 2.1 Collection responses

Most list endpoints return:

```json
{
  "items": [
    {"id": "..."}
  ],
  "totalItems": 120,
  "totalPages": 3,
  "meta": {
    "page": 1,
    "size": 50
  }
}
```

### 2.2 Single-object responses

Single-object endpoints return a JSON object (or `{ "data": ... }` for specific endpoints like schedule/analytics overview).

### 2.3 Common error responses

```json
{"message":"Unauthorized"}
```

```json
{"message":"User not found."}
```

```json
{
  "message": "The given data was invalid.",
  "errors": {
    "date": ["The date field is required."]
  }
}
```

## 3) ID Rules (Critical)

- Always send public UUIDs from API payloads.
- Never send internal numeric IDs.
- Path params like `{place}`, `{customer}`, `{order}`, `{booking}` are public UUIDs (except legacy internal behavior in some old update paths; OpenClaw should always use public UUIDs from API responses).

## 4) Place Analytics Endpoints

## 4.1 Overview KPI

`GET /places/{place}/analytics`

Purpose:
- one-shot summary for access logs, bookings, and orders

Query params:
- `date_from` optional (`YYYY-MM-DD`)
- `date_to` optional (`YYYY-MM-DD`)

Example request:

```bash
curl -X GET \
  -H "X-API-KEY: $API_KEY" \
  -H "Accept: application/json" \
  "https://api.staging.championspirit.com/v1/chatbot/places/$PLACE_ID/analytics?date_from=2026-03-01&date_to=2026-03-24"
```

Example response:

```json
{
  "data": {
    "place": {
      "id": "8a4f0c85-503f-4d40-8be8-257d5741ff3f",
      "name": "Champion Spirit Paris",
      "timezone": "Europe/Paris"
    },
    "period": {
      "date_from": "2026-03-01",
      "date_to": "2026-03-24"
    },
    "access_logs": {
      "total": 842,
      "granted": 810,
      "denied": 32,
      "arrived": 760,
      "left": 625,
      "guest_pass": 71
    },
    "bookings": {
      "total": 412,
      "active": 398,
      "canceled": 14,
      "today": 26,
      "upcoming": 119,
      "past": 253,
      "by_type": {
        "service": 170,
        "group_course": 121,
        "personal_course": 86,
        "place": 35
      }
    },
    "orders": {
      "total": 295,
      "paid": 271,
      "pending": 24,
      "paid_money_total_minor": 1815200,
      "paid_money_currency": "EUR",
      "paid_credits_total": 7260.5
    }
  }
}
```

## 4.2 Access Logs List

`GET /places/{place}/analytics/access-logs`

Query params:
- `date_from`, `date_to` (`YYYY-MM-DD`)
- `status` = `arrived|left|not_arrived`
- `user_public_id`
- `guest_public_id`
- `access_granted` = `true|false`
- `is_guest_pass` = `true|false`
- `page` (default `1`)
- `size` (default `50`, max `200`)

Example request:

```bash
curl -X GET \
  -H "X-API-KEY: $API_KEY" \
  -H "Accept: application/json" \
  "https://api.staging.championspirit.com/v1/chatbot/places/$PLACE_ID/analytics/access-logs?status=arrived&access_granted=true&page=1&size=2"
```

Example response:

```json
{
  "items": [
    {
      "id": "f5f4d60c-9a4b-4f8d-8d1b-378f2a01200f",
      "date": "2026-03-24T09:15:11+01:00",
      "status": "arrived",
      "firstname": "John",
      "lastname": "Doe",
      "email": "john@example.com",
      "access_granted": true,
      "reason": null,
      "is_guest_pass": false,
      "user": {
        "id": "f3fd4358-f9c2-4e06-a4df-8e8e2f06b628",
        "firstname": "John",
        "lastname": "Doe",
        "email": "john@example.com"
      },
      "guest": null,
      "booking_id": "7343d057-8c44-4dca-9d13-fd4b0d4f3286",
      "attachments": []
    }
  ],
  "totalItems": 146,
  "totalPages": 73,
  "meta": {
    "page": 1,
    "size": 2,
    "timezone": "Europe/Paris"
  }
}
```

## 4.3 Bookings Analytics List

`GET /places/{place}/analytics/bookings`

Query params:
- `status` = `all|upcoming|past|today|canceled`
- `type` = `place|service|activity|personal_course|wellness_course|group_course|event`
- `date_from`, `date_to` (`YYYY-MM-DD`)
- `attendee_public_id`
- `coach_public_id`
- `page`, `size`

Example request:

```bash
curl -X GET \
  -H "X-API-KEY: $API_KEY" \
  -H "Accept: application/json" \
  "https://api.staging.championspirit.com/v1/chatbot/places/$PLACE_ID/analytics/bookings?status=upcoming&type=group_course&page=1&size=2"
```

Example response (excerpt):

```json
{
  "items": [
    {
      "id": "d60291b1-97b4-4415-9a1e-7420c6c12e0a",
      "type": "group_course",
      "name": "HIIT Morning",
      "category": "Fitness",
      "can_be_refund": false,
      "is_guest_pass": false,
      "start_at": "2026-03-25T08:00:00.000000Z",
      "end_at": "2026-03-25T09:00:00.000000Z",
      "cancelled_at": null,
      "place": {
        "id": "8a4f0c85-503f-4d40-8be8-257d5741ff3f",
        "name": "Champion Spirit Paris"
      },
      "coach": {
        "id": "3f013bc6-b8e2-4a15-b35c-287cfe527d88",
        "firstname": "Nina",
        "lastname": "Smith"
      },
      "attendee": {
        "id": "f3fd4358-f9c2-4e06-a4df-8e8e2f06b628"
      }
    }
  ],
  "totalItems": 28,
  "totalPages": 14,
  "meta": {
    "page": 1,
    "size": 2,
    "timezone": "Europe/Paris",
    "status": "upcoming"
  }
}
```

## 4.4 Orders Analytics List

`GET /places/{place}/analytics/orders`

Query params:
- `status` = `all|paid|pending`
- `date_from`, `date_to` (`YYYY-MM-DD`)
- `customer_public_id`
- `page`, `size`

Example request:

```bash
curl -X GET \
  -H "X-API-KEY: $API_KEY" \
  -H "Accept: application/json" \
  "https://api.staging.championspirit.com/v1/chatbot/places/$PLACE_ID/analytics/orders?status=paid&page=1&size=2"
```

Example response:

```json
{
  "items": [
    {
      "id": "6c74f6ce-80b4-4af8-95bb-cad6f7706818",
      "created_at": "2026-03-24T08:53:21.000000Z",
      "status": 20,
      "status_code": "PAID",
      "payment_provider": "wallet",
      "payment_intent": null,
      "money_total": {
        "amount_minor": 2900,
        "currency": "EUR"
      },
      "credits_total": 29,
      "taxes_total": 2.9,
      "is_chatbot_order": true,
      "customer": {
        "id": "f3fd4358-f9c2-4e06-a4df-8e8e2f06b628",
        "firstname": "John",
        "lastname": "Doe",
        "email": "john@example.com"
      },
      "place_id": "8a4f0c85-503f-4d40-8be8-257d5741ff3f",
      "item_count": 1,
      "items": [
        {
          "id": "9bf5e958-28ff-4e8d-86f0-fbe8d04f4c6d",
          "orderable_type": "service",
          "orderable_id": "986cf3dd-f6ef-4054-ae77-5f8ff722205f",
          "is_guest_pass": false,
          "metadata": {
            "start_at": "2026-03-25T10:00:00+01:00",
            "end_at": "2026-03-25T11:00:00+01:00"
          },
          "money_price_minor": 2900,
          "money_price_currency": "EUR",
          "credits_price": 29,
          "credits_taxes": 2.9
        }
      ]
    }
  ],
  "totalItems": 17,
  "totalPages": 9,
  "meta": {
    "page": 1,
    "size": 2,
    "timezone": "Europe/Paris",
    "status": "paid",
    "paid": 17,
    "pending": 0,
    "money_total_minor": 80500,
    "money_currency": "EUR",
    "credits_total": 805
  }
}
```

## 5) Booking Discovery Endpoints

## 5.1 Unified Schedule

`GET /places/{place}/schedule`

Query params:
- `date` required (`YYYY-MM-DD`)
- `group_by` optional (`course_type|department`, default `course_type`)
- `customer_public_id` optional

Example request:

```bash
curl -X GET \
  -H "X-API-KEY: $API_KEY" \
  -H "Accept: application/json" \
  "https://api.staging.championspirit.com/v1/chatbot/places/$PLACE_ID/schedule?date=2026-03-24&group_by=course_type"
```

Example response (excerpt):

```json
{
  "data": [
    {
      "type": "group_courses",
      "label": "Group Courses",
      "categories_count": 2,
      "slots_count": 8,
      "categories": [
        {
          "id": "f0ff7b8f-d7f3-4027-b63f-92a9b2b2787e",
          "name": "Fitness",
          "courses": [
            {
              "id": "3a11121f-f2eb-4baf-a4b6-94782735dbad",
              "name": "HIIT Morning",
              "start_at": "2026-03-24T08:00:00+01:00",
              "end_at": "2026-03-24T09:00:00+01:00",
              "capacity": 20,
              "bookings_count": 12,
              "places_left": 8
            }
          ]
        }
      ]
    }
  ],
  "meta": {
    "place_id": "8a4f0c85-503f-4d40-8be8-257d5741ff3f",
    "date": "2026-03-24",
    "group_by": "course_type",
    "customer_public_id": null
  }
}
```

## 5.2 Specialized Catalog Endpoints

Use when you only need one type:
- `GET /places/{place}/services`
- `GET /places/{place}/activities`
- `GET /places/{place}/personal-courses/{coach_id?}/{category_id?}`
- `GET /places/{place}/wellness-courses/{coach_id?}/{category_id?}`
- `GET /places/{place}/group-courses/{coach_id?}/{category_id?}`
- `GET /places/{place}/events`
- `GET /places/{place}/categories`

## 6) Booking Execution Endpoints

## 6.1 Create Order (Draft)

`POST /customer/{customer}/orders`

Request body:

```json
{
  "assistant_id": "openclaw-prod-assistant",
  "items": [
    {
      "orderable_type": "service",
      "orderable_id": "986cf3dd-f6ef-4054-ae77-5f8ff722205f",
      "metadata": {
        "start_at": "2026-03-25T10:00:00+01:00"
      }
    }
  ]
}
```

Example request:

```bash
curl -X POST \
  -H "X-API-KEY: $API_KEY" \
  -H "Content-Type: application/json" \
  "https://api.staging.championspirit.com/v1/chatbot/customer/$CUSTOMER_ID/orders" \
  -d '{
    "assistant_id":"openclaw-prod-assistant",
    "items":[
      {
        "orderable_type":"service",
        "orderable_id":"986cf3dd-f6ef-4054-ae77-5f8ff722205f",
        "metadata":{"start_at":"2026-03-25T10:00:00+01:00"}
      }
    ]
  }'
```

Example response (excerpt):

```json
{
  "id": "6c74f6ce-80b4-4af8-95bb-cad6f7706818",
  "created_at": "2026-03-24T08:53:21.000000Z",
  "can_be_paid": true,
  "money_total": {
    "amount": 2900,
    "currency": "EUR"
  },
  "credits_total": 29,
  "taxes_total": 2.9,
  "status": 10,
  "status_label": "Waiting payment",
  "place_id": "8a4f0c85-503f-4d40-8be8-257d5741ff3f",
  "items": [
    {
      "id": "9bf5e958-28ff-4e8d-86f0-fbe8d04f4c6d",
      "orderable_type": "service",
      "orderable_id": "986cf3dd-f6ef-4054-ae77-5f8ff722205f"
    }
  ]
}
```

## 6.2 Update Existing Draft Order

`PUT /customer/{customer}/orders/{order}`

Same request body format as create. Use this when the user changes slot/orderable.

## 6.3 List Customer Orders

`GET /customer/{customer}/orders`

Query params:
- `status` = `all|paid|pending`
- `date_from`, `date_to` (`YYYY-MM-DD`)
- `page`, `size`

Example request:

```bash
curl -X GET \
  -H "X-API-KEY: $API_KEY" \
  -H "Accept: application/json" \
  "https://api.staging.championspirit.com/v1/chatbot/customer/$CUSTOMER_ID/orders?status=all&page=1&size=20"
```

Example response:

```json
{
  "items": [
    {
      "id": "6c74f6ce-80b4-4af8-95bb-cad6f7706818",
      "status": 10,
      "status_code": "WAITING_PAYMENT",
      "money_total": {
        "amount_minor": 2900,
        "currency": "EUR"
      },
      "item_count": 1
    },
    {
      "id": "3cedbe2d-2a3f-4c36-b82a-8870d65cf810",
      "status": 20,
      "status_code": "PAID",
      "money_total": {
        "amount_minor": 4500,
        "currency": "EUR"
      },
      "item_count": 2
    }
  ],
  "totalItems": 2,
  "totalPages": 1,
  "meta": {
    "page": 1,
    "size": 20,
    "status": "all",
    "customer_public_id": "f3fd4358-f9c2-4e06-a4df-8e8e2f06b628"
  }
}
```

## 6.4 Pay Order - Wallet

`POST /customer/{customer}/orders/{order}/wallet-payment`

Request body:

```json
{
  "assistant_id": "openclaw-prod-assistant"
}
```

Success response:

```json
{
  "message": "Order Successfully paid."
}
```

Common error examples:

```json
{"message":"Order not found."}
```

```json
{"message":"This order is not linked to the user."}
```

```json
{"message":"This order is already paid."}
```

## 6.5 Pay Order - Stripe

`POST /customer/{customer}/orders/{order}/stripe-payment`

Request body:

```json
{
  "assistant_id": "openclaw-prod-assistant"
}
```

Success response:

```json
{
  "url": "https://checkout.stripe.com/c/pay/cs_test_..."
}
```

## 6.6 Pay Order - NowPayments (Crypto)

`POST /customer/{customer}/orders/{order}/nowpayments-payment`

Request body:

```json
{
  "assistant_id": "openclaw-prod-assistant"
}
```

Response contains payment session/redirect payload from NowPayments integration.

## 6.7 Booking Verification Endpoints

- `GET /customer/{customer}/bookings`
- `GET /customer/{customer}/bookings/{booking}`
- `POST /customer/{customer}/bookings/{booking}/cancel`

Example booking list request:

```bash
curl -X GET \
  -H "X-API-KEY: $API_KEY" \
  -H "Accept: application/json" \
  "https://api.staging.championspirit.com/v1/chatbot/customer/$CUSTOMER_ID/bookings?past=false"
```

## 7) OpenClaw Playbooks

## 7.1 Data Analysis Playbook

1. Call `/places/{place}/analytics` with explicit `date_from` and `date_to`.
2. Call `/analytics/access-logs` for drill-down.
3. Call `/analytics/bookings` for booking mix and trend segmentation.
4. Call `/analytics/orders` for order/revenue segmentation.
5. Continue pagination (`page += 1`) until `page > totalPages`.

## 7.2 Booking Playbook

1. Discover options via `/places/{place}/schedule?date=...`.
2. Pick slot/orderable.
3. Create draft via `POST /customer/{customer}/orders`.
4. If user changes preference, update via `PUT /customer/{customer}/orders/{order}`.
5. Trigger payment endpoint.
6. Confirm via `GET /customer/{customer}/orders` then `GET /customer/{customer}/bookings`.

## 8) Validation and Retry Advice

- For `422` validation errors: fix request using `errors` object and retry once.
- For `404`: re-resolve IDs first (do not retry blind).
- For payment endpoints returning `403` on already-paid order: treat as idempotent success if order status is already paid when re-checked.
- Always include explicit `date_from/date_to` in analytics prompts for deterministic agent outputs.

## 9) Quick Endpoint Index

- `GET /places/{place}/analytics`
- `GET /places/{place}/analytics/access-logs`
- `GET /places/{place}/analytics/bookings`
- `GET /places/{place}/analytics/orders`
- `GET /places/{place}/schedule`
- `GET /customer/{customer}/orders`
- `POST /customer/{customer}/orders`
- `PUT /customer/{customer}/orders/{order}`
- `POST /customer/{customer}/orders/{order}/wallet-payment`
- `POST /customer/{customer}/orders/{order}/stripe-payment`
- `POST /customer/{customer}/orders/{order}/nowpayments-payment`
- `GET /customer/{customer}/bookings`
- `GET /customer/{customer}/bookings/{booking}`
- `POST /customer/{customer}/bookings/{booking}/cancel`
