# AI Smart Scheduling API Documentation

## Overview

The AI Smart Scheduling API enables automated employee shift assignment using OpenAI's GPT models. It analyzes employee availability, qualifications, hours preferences, and store priorities to generate optimized schedule suggestions.

**Specification**: See `docs/specs/026-ai-smart-scheduling/` for full PRD and SDD.

## Authentication

All endpoints require:
1. Valid user session (authentication)
2. Store group membership (`checkStoreGroup`)
3. Permission: `uri_schedule_ai` for viewing/generating, `uri_schedule_ai_apply` for applying

## Base URL

```
/:typeNum/api/schedule/ai/
```

Where `typeNum` is the store identifier (e.g., `ou00`).

---

## Endpoints

### Generate AI Schedule

**POST** `/:typeNum/api/schedule/ai/generate`

Initiates AI-powered schedule generation for a specified week.

#### Request Body

```json
{
  "weekStart": "2026-01-12",
  "priorities": ["labor_cost", "hours_fairness", "position_coverage"],
  "customInstructions": "Prefer experienced staff for opening shifts",
  "forceRegenerate": false,
  "notifyByEmail": true
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `weekStart` | string | Yes | Week start date (ISO format YYYY-MM-DD) |
| `priorities` | array | No | Optimization priorities. Default: `["labor_cost", "hours_fairness"]` |
| `customInstructions` | string | No | Free-text instructions for AI (max 500 chars) |
| `forceRegenerate` | boolean | No | Replace existing pending suggestion. Default: false |
| `notifyByEmail` | boolean | No | Send email on completion. Default: false |

**Available Priorities:**
- `labor_cost` - Minimize total labor cost
- `hours_fairness` - Distribute hours equitably
- `position_coverage` - Ensure all positions staffed
- `seniority` - Prefer senior employees
- `minimize_overtime` - Avoid overtime when possible

#### Success Response (202 Accepted)

```json
{
  "success": true,
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "channel": "ai-schedule-ou00-550e8400-e29b-41d4-a716-446655440000",
  "message": "AI schedule generation started"
}
```

#### Error Responses

**429 Too Many Requests** - Rate limit exceeded
```json
{
  "error": true,
  "code": "ERROR_RATE_LIMITED",
  "message": "Rate limit exceeded. 5/5 runs used this pay week."
}
```

**400 Bad Request** - Invalid parameters
```json
{
  "error": true,
  "code": "ERROR_VALIDATION",
  "message": "weekStart is required"
}
```

---

### Get Job Status

**GET** `/:typeNum/api/schedule/ai/job/:jobId`

Check the status of an AI generation job.

#### Path Parameters

| Parameter | Description |
|-----------|-------------|
| `jobId` | UUID of the AI job |

#### Response

```json
{
  "success": true,
  "job": {
    "jobId": "550e8400-e29b-41d4-a716-446655440000",
    "status": "completed",
    "weekStart": "2026-01-12",
    "suggestionId": 123,
    "createdAt": "2026-01-10T14:30:00Z",
    "completedAt": "2026-01-10T14:30:25Z"
  }
}
```

**Job Statuses:**
- `pending` - Queued for processing
- `processing` - AI generation in progress
- `completed` - Suggestions ready
- `failed` - Generation failed (check `errorMessage`)

---

### Get Suggestions for Week

**GET** `/:typeNum/api/schedule/ai/suggestions/:weekStart`

Get AI-generated suggestions for a specific week.

#### Path Parameters

| Parameter | Description |
|-----------|-------------|
| `weekStart` | Week start date (YYYY-MM-DD) |

#### Response

```json
{
  "success": true,
  "suggestion": {
    "id": 123,
    "jobId": "550e8400-e29b-41d4-a716-446655440000",
    "status": "pending",
    "weekStart": "2026-01-12",
    "weekEnd": "2026-01-18",
    "generatedAt": "2026-01-10T14:30:25Z",
    "generatedByUserId": 100,
    "assignments": [
      {
        "shiftId": 1001,
        "employeeId": 500,
        "employeeName": "John Smith",
        "shiftStart": "2026-01-13T09:00:00Z",
        "shiftEnd": "2026-01-13T17:00:00Z",
        "position": "Cashier",
        "reasoning": "Best availability match with lowest labor cost",
        "confidenceScore": 0.92,
        "laborCost": 120.00,
        "hoursAfterAssignment": 24.0,
        "isOvertime": false,
        "isStale": false
      }
    ],
    "summary": {
      "totalShifts": 10,
      "filledCount": 8,
      "unfilledCount": 2,
      "totalLaborCost": 960.00
    }
  }
}
```

---

### Get Suggestion Details

**GET** `/:typeNum/api/schedule/ai/suggestions/detail/:suggestionId`

Get detailed information about a specific suggestion.

#### Path Parameters

| Parameter | Description |
|-----------|-------------|
| `suggestionId` | Numeric suggestion ID |

---

### Apply Suggestions

**POST** `/:typeNum/api/schedule/ai/apply`

Apply selected AI suggestions to the actual schedule.

**Required Permission:** `uri_schedule_ai_apply`

#### Request Body

```json
{
  "suggestionId": 123,
  "shiftIds": [1001, 1002, 1003],
  "applyAll": false
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `suggestionId` | integer | Yes | ID of the suggestion to apply |
| `shiftIds` | array | No | Specific shift IDs to apply (if not applyAll) |
| `applyAll` | boolean | No | Apply all suggestions. Default: false |

#### Success Response

```json
{
  "success": true,
  "applied": 3,
  "message": "Successfully applied 3 AI suggestions"
}
```

#### Error Responses

**410 Gone** - Week has passed
```json
{
  "error": true,
  "code": "ERROR_WEEK_EXPIRED",
  "message": "Cannot apply suggestions for past weeks"
}
```

---

### Dismiss Suggestions

**POST** `/:typeNum/api/schedule/ai/dismiss`

Dismiss AI suggestions without applying.

#### Request Body

```json
{
  "suggestionId": 123
}
```

---

### Get Usage Statistics

**GET** `/:typeNum/api/schedule/ai/usage`

Get AI scheduling usage for the current pay period.

#### Response

```json
{
  "success": true,
  "usage": {
    "runsUsed": 2,
    "runsAllowed": 5,
    "runsRemaining": 3,
    "usagePercentage": 40.0,
    "resetDate": "2026-01-19"
  }
}
```

---

### Get/Update Owner Preferences

**GET** `/:typeNum/api/schedule/ai/owner-prefs`

Get owner-specific scheduling preferences (which owners to include).

**POST** `/:typeNum/api/schedule/ai/owner-prefs`

Update owner inclusion preferences.

#### Request Body

```json
{
  "ownerToggles": {
    "100": true,
    "101": false
  }
}
```

---

### Get Default Preferences

**GET** `/:typeNum/api/schedule/ai/default-prefs`

Get store-wide default priorities and settings.

---

### Get Session Logs

**GET** `/:typeNum/api/schedule/ai/logs`

Get AI scheduling session logs for auditing.

#### Query Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `limit` | integer | Max results (default: 20, max: 100) |
| `offset` | integer | Pagination offset |

---

## Real-Time Notifications

The API uses Ably for real-time notifications during AI generation.

### Channel Format

```
ai-schedule-{typeNum}-{jobId}
```

Example: `ai-schedule-ou00-550e8400-e29b-41d4-a716-446655440000`

### Events

**job-complete** - Generation finished
```json
{
  "event": "job-complete",
  "data": {
    "status": "completed",
    "jobId": "550e8400-e29b-41d4-a716-446655440000",
    "suggestionId": 123,
    "summary": {
      "filled": 8,
      "unfilled": 2,
      "laborCost": 960.00
    }
  }
}
```

**ai-schedule-applied** - Suggestions applied
```json
{
  "event": "ai-schedule-applied",
  "data": {
    "suggestionId": 123,
    "appliedCount": 5,
    "shiftIds": [1001, 1002, 1003, 1004, 1005]
  }
}
```

---

## Rate Limiting

- **5 runs per pay week** per store
- `forceRegenerate=true` does NOT count against limit (replaces existing)
- Resets at pay period boundary
- Tracked per store, not per user

---

## Error Codes

| Code | HTTP Status | Description |
|------|-------------|-------------|
| `ERROR_VALIDATION` | 400 | Invalid request parameters |
| `ERROR_NOT_FOUND` | 404 | Resource not found |
| `ERROR_RATE_LIMITED` | 429 | Usage limit exceeded |
| `ERROR_WEEK_EXPIRED` | 410 | Week has passed |
| `ERROR_INTERNAL` | 500 | Server error |

---

## Related Documentation

- **PRD**: `docs/specs/026-ai-smart-scheduling/product-requirements.md`
- **SDD**: `docs/specs/026-ai-smart-scheduling/solution-design.md`
- **Implementation Plan**: `docs/specs/026-ai-smart-scheduling/implementation-plan.md`
