# AIBot Partner API v1 — Strategic Partner Integration Guide

> **Audience**: development teams of all AIBot strategic partners (this is a universal spec, applying to every partner). Partners bill their own customers directly; AIBot settles with the partner based on each tenant's plan and wholesale rates (Microsoft CSP model).
> **Base URL**: `https://wtsaibot.com` (the only public entry point) | **Online docs**: `https://wtsaibot.com/api`
> **Version**: v1 (2026-09-13; interface depth frozen — tenant creation, usage reporting and channel team data are exposed. Knowledge base (KB) and AI persona (prompt) settings are **not** available via API; AIBot serves each customer manually — partners collect customer materials and hand them to AIBot for follow-up.)

---

## 1. Authentication

All requests must include the header:

```
X-Partner-Key: <PARTNER_API_KEY>
```

- Keys are generated in the AIBot admin panel as a 64-character hex string, shown only once at creation/regeneration — store it safely immediately (a lost key can only be replaced; the old key is invalidated instantly).
- Keys are bound to the partner (not to tenants) — all tenants created via the API automatically fall under your partner account (the basis of wholesale settlement).
- Any authentication failure returns `401` (without revealing whether the key was ever valid).

## 2. Rate limiting

Each partner key allows a **maximum of 120 requests per minute** (strongly consistent counting via Durable Object). Exceeding the limit returns `429` with `Retry-After: 60`. Creating tenants is a low-frequency operation; a normal integration will not reach this limit.

## 3. Endpoint overview

| Endpoint | Method | Purpose |
|---|---|---|
| `/partner/v1/tenants` | `POST` | Create a tenant (immediately usable, automatically under your partner account) |
| `/partner/v1/tenants` | `GET` | List your tenants |
| `/partner/v1/usage?month=YYYY-MM` | `GET` | Usage aggregation for your tenants (conversation counts; wholesale settlement) |
| `/partner/v1/team` | `GET` | Channel team: agent funnel + latest closed orders |

---

## 4. `POST /partner/v1/tenants` — Create a tenant

### Request body (JSON)

| Field | Type | Required | Description |
|---|---|---|---|
| `name` | string | ✅ | Customer's shop or company name (display, ≤60 chars) |
| `phone` | string | ✅ | Customer contact number (E.164, digits only, 6-15, e.g. `85291234567`) — used as the tenant's registered phone |
| `plan` | string | ✅ | `lite199` (Lite) or `pro499` (Pro) |
| `notes` | string | ❌ | Notes (≤500 chars; e.g. customer industry, KB highlights — for AIBot's service team) |

### curl example

```bash
curl -X POST "https://wtsaibot.com/partner/v1/tenants" \
  -H "X-Partner-Key: <PARTNER_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Demo Cha Chaan Teng",
    "phone": "85291234567",
    "plan": "pro499",
    "notes": "Hong Kong style cafe, lunch-set takeaway focused"
  }'
```

### Response `201`

```json
{
  "tenantId": "yourbrand_a1b2c3",
  "webhookToken": "1234567890",
  "webhookUrl": "https://wtsaibot.com/webhook/1234567890",
  "portalUrl": "https://wtsaibot.com/merchant"
}
```

| Field | Description |
|---|---|
| `tenantId` | Unique tenant ID (`partnerid_6random` format; cannot be chosen) |
| `webhookUrl` | Inbound WhatsApp webhook — **fill this into the RPMSMS/WhatsApp gateway's Webhook field** (AIBot guides the customer through device binding) |
| `portalUrl` | Merchant portal login entry (customer self-service; credentials delivered by AIBot) |

New tenants instantly receive the **feature whitelist** (default: core AI chat + multi-turn memory + smart triage + human handoff; other features such as PDF quotations are off by default — contact AIBot to enable extras).

---

## 5. `GET /partner/v1/tenants` — List your tenants

### curl example

```bash
curl "https://wtsaibot.com/partner/v1/tenants" \
  -H "X-Partner-Key: <PARTNER_API_KEY>"
```

### Response `200`

```json
{
  "partner": "yourbrand",
  "tenants": [
    {
      "tenantId": "yourbrand_a1b2c3",
      "name": "Demo Cha Chaan Teng",
      "status": "trial",
      "planTier": "pro499",
      "createdAt": 1747267200000
    }
  ]
}
```

`status`: `trial` / `paid` / `suspended`. `createdAt` is a Unix timestamp in milliseconds.

---

## 6. `GET /partner/v1/usage` — Usage report

Query aggregated conversation usage for all your tenants in a given month (the basis of wholesale settlement). Months are bounded by Hong Kong time (HKT).

### Parameters

| Parameter | Required | Description |
|---|---|---|
| `month` | ❌ | `YYYY-MM`; defaults to the current month (HKT) |

### curl example

```bash
curl "https://wtsaibot.com/partner/v1/usage?month=2026-09" \
  -H "X-Partner-Key: <PARTNER_API_KEY>"
```

### Response `200`

```json
{
  "partner": "yourbrand",
  "month": "2026-09",
  "tenants": [
    {
      "tenantId": "yourbrand_a1b2c3",
      "name": "Demo Cha Chaan Teng",
      "conversations": 42,
      "messages": 318
    }
  ],
  "totals": {
    "conversations": 42,
    "messages": 318
  }
}
```

- `conversations` = count of independent customer conversation segments (by session); `messages` = total messages (customer + AI replies).
- Querying the current month returns in-progress figures (month not yet complete).

---

## 7. `GET /partner/v1/team` — Channel team (agent funnel + orders)

Fetch the performance funnel of every referral agent under your partner account (clicks / leads / conversions / total commission) and the latest closed orders (last 100).

### curl example

```bash
curl "https://wtsaibot.com/partner/v1/team" \
  -H "X-Partner-Key: <PARTNER_API_KEY>"
```

### Response `200`

```json
{
  "partner": "yourbrand",
  "agents": [
    {
      "id": 12,
      "name": "Chan Tai Man",
      "code": "A1B2C3",
      "status": "active",
      "activatedAt": 1747267200000,
      "clicks": 150,
      "leads": 32,
      "converted": 5,
      "rewardsTotal": 10000
    }
  ],
  "orders": [
    {
      "orderId": "ORD-20261001-001",
      "customerName": "Demo Cha Chaan Teng",
      "plan": "pro499",
      "amount": 5490,
      "status": "paid",
      "refCode": "A1B2C3",
      "createdAt": 1791072000000
    }
  ]
}
```

- `status`: `pending` / `active`. `rewardsTotal` is the agent's cumulative commission (HK$).
- `orders` returns the latest 100 only; `amount` is the contract total (HK$); order `status`: `pending` / `paid` / `cancelled`.

---

## 8. Error codes

| HTTP | `code` | Scenario | How to fix |
|---|---|---|---|
| `400` | `MISSING_NAME` | `name` missing when creating a tenant | Check the request body |
| `400` | `INVALID_PHONE` | `phone` is not 6-15 digits | Convert to E.164 digits only (strip `+`) |
| `400` | `INVALID_PLAN` | `plan` is not `lite199`/`pro499` | — |
| `401` | `INVALID_PARTNER_KEY` | Key missing or wrong | Check the header is `X-Partner-Key`; regenerating a key invalidates the old one instantly |
| `404` | `NOT_FOUND` | Wrong path or method | Compare against the endpoint table |
| `429` | `RATE_LIMITED` | Over 120 req/min | Retry after the `Retry-After` seconds (exponential backoff recommended) |
| `503` | `ID_COLLISION` | Random tenant_id collision (very rare) | Simply retry once |

Error responses are always JSON: `{"error": "...", "code": "..."}`.

## 9. Webhook push (optional add-on)

Beyond polling, partners can enable **Webhook push** — when configured events occur, AIBot pushes data to your system proactively: no polling, near real-time. Ideal for partners with their own CRM/settlement systems who want orders and conversions auto-synced.

### Enablement

Contact AIBot with your **HTTPS callback endpoint URL** (public HTTPS required). Once enabled, AIBot delivers a **Webhook Secret** for signature verification. Configuration is handled by AIBot — no self-service setup needed.

### Event types (phase one)

| Event | Trigger |
|---|---|
| `order.created` | A new order is placed under one of your tenants |
| `order.paid` | Order payment confirmed |

### Payload (JSON)

```json
{
  "event": "order.paid",
  "partner": "yourbrand",
  "timestamp": 1791072000000,
  "data": {
    "orderId": "ORD-20261001-001",
    "tenantId": "yourbrand_a1b2c3",
    "customerName": "Demo Cha Chaan Teng",
    "plan": "pro499",
    "amount": 5490,
    "refCode": "A1B2C3"
  }
}
```

### Signature verification

Each request carries headers:

- `X-AIBot-Event`: event type
- `X-AIBot-Signature`: hex of `HMAC-SHA256(Webhook Secret, raw request body)`

Your server should recompute and compare using the same secret (constant-time comparison recommended) before processing.

### Retry policy

Non-`2xx` responses or timeouts (10 s) count as failures, retried at **1 min → 5 min → 30 min → 2 h** (4 attempts total); afterwards re-sync via `GET /team` (orders) — no order is ever lost.

### Without Webhook

Partners without Webhook enabled simply poll `GET /team` and `GET /usage` — both methods coexist without conflict.

## 10. Integration notes

- All requests and responses are UTF-8 JSON.
- Before integrating, call `GET /partner/v1/tenants` to verify authentication.
- **KB / prompt / feature activation** are served manually by AIBot: the partner prepares the customer's materials (menu, FAQs, pricing, persona requirements) and hands them to AIBot; delivery timelines are agreed separately.
- **Testing**: AIBot provides every partner a **test key** (bound to a test partner account) for integration validation; production keys receive production traffic only.
