# Broadcast & Survey API Reference

> **Base URL**: `https://api.bytelyst.io/v1`  
> **Authentication**: Bearer token (JWT) required for all endpoints except public ones  
> **Product ID**: All requests must include `X-Product-ID` header

---

## Authentication

```http
Authorization: Bearer <jwt_token>
X-Product-ID: <product_id>
```

---

## Broadcasts

### Admin Endpoints

#### List Broadcasts
```http
GET /admin/broadcasts
```

**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `status` | string | Filter by status: `draft`, `scheduled`, `sending`, `paused`, `completed` |
| `channel` | string | Filter by channel: `push`, `in_app`, `email`, `sms` |
| `limit` | integer | Max items (default: 20, max: 100) |
| `offset` | integer | Pagination offset |

**Response:**
```json
{
  "broadcasts": [
    {
      "id": "bc_123456789",
      "productId": "lysnrai",
      "title": "New Feature Announcement",
      "body": "Check out our latest update!",
      "channel": "push",
      "priority": "high",
      "status": "completed",
      "target": {
        "platforms": ["ios", "android"],
        "userSegments": ["pro"],
        "percentageRollout": 100
      },
      "metrics": {
        "targetedCount": 1500,
        "sentCount": 1500,
        "deliveredCount": 1420,
        "openedCount": 890,
        "clickedCount": 340,
        "dismissedCount": 45
      },
      "createdAt": "2024-01-15T10:30:00Z",
      "updatedAt": "2024-01-15T10:35:00Z"
    }
  ],
  "total": 47,
  "limit": 20,
  "offset": 0
}
```

---

#### Get Broadcast
```http
GET /admin/broadcasts/:id
```

**Response:** Single broadcast object (same as list item)

---

#### Create Broadcast
```http
POST /admin/broadcasts
```

**Request Body:**
```json
{
  "title": "New Feature Announcement",
  "body": "Check out our latest update with voice commands!",
  "channel": "push",
  "priority": "high",
  "style": "banner",
  "ctaText": "Try it now",
  "ctaUrl": "https://app.bytelyst.io/voice",
  "imageUrl": "https://cdn.bytelyst.io/banner/voice.jpg",
  "target": {
    "platforms": ["ios", "android"],
    "userSegments": ["pro"],
    "appVersionMin": "2.0.0",
    "appVersionMax": null,
    "countryCodes": ["US", "CA"],
    "percentageRollout": 100,
    "specificUserIds": null
  },
  "scheduledAt": "2024-01-20T09:00:00Z",
  "expiresAt": "2024-02-20T09:00:00Z",
  "deepLink": {
    "screen": "voice_settings",
    "params": { "tab": "commands" }
  }
}
```

**Response:** Created broadcast object with `id`

---

#### Update Broadcast
```http
PUT /admin/broadcasts/:id
```

**Request Body:** Partial broadcast object (same as create)

**Response:** Updated broadcast object

---

#### Delete Broadcast
```http
DELETE /admin/broadcasts/:id
```

**Response:** `204 No Content`

---

#### Send Broadcast
```http
POST /admin/broadcasts/:id/send
```

Triggers immediate send (or schedules if `scheduledAt` is set).

**Response:**
```json
{
  "success": true,
  "message": "Broadcast queued for sending",
  "estimatedReach": 1500
}
```

---

#### Pause Broadcast
```http
POST /admin/broadcasts/:id/pause
```

Pauses a sending broadcast.

**Response:**
```json
{
  "success": true,
  "message": "Broadcast paused"
}
```

---

#### Get Broadcast Metrics
```http
GET /admin/broadcasts/:id/metrics
```

**Response:**
```json
{
  "targetedCount": 1500,
  "sentCount": 1500,
  "deliveredCount": 1420,
  "openedCount": 890,
  "clickedCount": 340,
  "dismissedCount": 45,
  "convertedCount": 120,
  "deliveryRate": 94.7,
  "openRate": 59.3,
  "clickRate": 22.7,
  "conversionRate": 8.0
}
```

---

#### Clone Broadcast
```http
POST /admin/broadcasts/:id/clone
```

Creates a copy of the broadcast as a draft.

**Response:** New broadcast object with `id`

---

### Public Endpoints (Authenticated)

#### List In-App Messages
```http
GET /public/messages/in-app
```

Returns active in-app messages for the authenticated user.

**Response:**
```json
{
  "messages": [
    {
      "id": "msg_987654321",
      "broadcastId": "bc_123456789",
      "title": "New Feature Announcement",
      "body": "Check out our latest update!",
      "style": "banner",
      "priority": "high",
      "ctaText": "Try it now",
      "ctaUrl": "https://app.bytelyst.io/voice",
      "imageUrl": "https://cdn.bytelyst.io/banner/voice.jpg",
      "deepLink": {
        "screen": "voice_settings",
        "params": { "tab": "commands" }
      },
      "status": "unread",
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ]
}
```

---

#### Mark Message Read
```http
POST /public/messages/:id/read
```

**Response:**
```json
{
  "success": true,
  "message": "Marked as read"
}
```

---

#### Dismiss Message
```http
POST /public/messages/:id/dismiss
```

**Response:**
```json
{
  "success": true,
  "message": "Message dismissed"
}
```

---

#### Track Message Click
```http
POST /public/messages/:id/click
```

**Response:**
```json
{
  "success": true,
  "message": "Click tracked"
}
```

---

## Surveys

### Admin Endpoints

#### List Surveys
```http
GET /admin/surveys
```

**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `status` | string | Filter by status: `draft`, `active`, `paused`, `completed` |
| `limit` | integer | Max items (default: 20, max: 100) |
| `offset` | integer | Pagination offset |

**Response:**
```json
{
  "surveys": [
    {
      "id": "srv_123456789",
      "productId": "lysnrai",
      "title": "Product Feedback Survey",
      "description": "Help us improve your experience",
      "status": "active",
      "questionCount": 5,
      "responseCount": 892,
      "incentive": {
        "type": "pro_days",
        "amount": 7
      },
      "createdAt": "2024-01-10T08:00:00Z",
      "updatedAt": "2024-01-15T14:30:00Z"
    }
  ],
  "total": 12,
  "limit": 20,
  "offset": 0
}
```

---

#### Get Survey
```http
GET /admin/surveys/:id
```

**Response:** Full survey with questions
```json
{
  "id": "srv_123456789",
  "productId": "lysnrai",
  "title": "Product Feedback Survey",
  "description": "Help us improve your experience",
  "status": "active",
  "questions": [
    {
      "id": "q1",
      "type": "nps",
      "text": "How likely are you to recommend us?",
      "required": true,
      "minValue": 0,
      "maxValue": 10
    },
    {
      "id": "q2",
      "type": "single_choice",
      "text": "What feature do you use most?",
      "required": true,
      "options": [
        { "id": "voice", "text": "Voice dictation", "emoji": "🎙️" },
        { "id": "keyboard", "text": "Keyboard", "emoji": "⌨️" },
        { "id": "desktop", "text": "Desktop app", "emoji": "💻" }
      ]
    }
  ],
  "target": {
    "platforms": ["ios", "android"],
    "userSegments": ["active"]
  },
  "displayTrigger": {
    "type": "delay_seconds",
    "seconds": 30
  },
  "incentive": {
    "type": "pro_days",
    "amount": 7
  },
  "metrics": {
    "startedCount": 1200,
    "completedCount": 892,
    "completionRate": 74.3
  },
  "createdAt": "2024-01-10T08:00:00Z",
  "updatedAt": "2024-01-15T14:30:00Z"
}
```

---

#### Create Survey
```http
POST /admin/surveys
```

**Request Body:**
```json
{
  "title": "Product Feedback Survey",
  "description": "Help us improve your experience",
  "questions": [
    {
      "id": "q1",
      "type": "nps",
      "text": "How likely are you to recommend us?",
      "required": true,
      "minValue": 0,
      "maxValue": 10
    },
    {
      "id": "q2",
      "type": "single_choice",
      "text": "What feature do you use most?",
      "description": "Select your primary use case",
      "required": true,
      "options": [
        { "id": "voice", "text": "Voice dictation", "emoji": "🎙️" },
        { "id": "keyboard", "text": "Keyboard", "emoji": "⌨️" }
      ]
    },
    {
      "id": "q3",
      "type": "text_long",
      "text": "What could we improve?",
      "required": false,
      "maxLength": 500,
      "showIf": {
        "questionId": "q1",
        "operator": "not_equals",
        "value": ["9", "10"]
      }
    }
  ],
  "target": {
    "platforms": ["ios", "android"],
    "userSegments": ["active"],
    "percentageRollout": 100
  },
  "displayTrigger": {
    "type": "delay_seconds",
    "seconds": 30
  },
  "incentive": {
    "type": "pro_days",
    "amount": 7
  }
}
```

**Response:** Created survey object with `id`

---

#### Update Survey
```http
PUT /admin/surveys/:id
```

**Request Body:** Partial survey object

**Response:** Updated survey object

---

#### Delete Survey
```http
DELETE /admin/surveys/:id
```

**Response:** `204 No Content`

---

#### Get Survey Metrics
```http
GET /admin/surveys/:id/metrics
```

**Response:**
```json
{
  "questionStats": [
    {
      "questionId": "q1",
      "questionType": "nps",
      "responseCount": 892,
      "distribution": {
        "0": 12,
        "1": 8,
        "2": 15,
        "7": 120,
        "8": 200,
        "9": 180,
        "10": 357
      },
      "average": 8.2,
      "npsScore": 68
    }
  ],
  "startedCount": 1200,
  "completedCount": 892,
  "completionRate": 74.3,
  "averageTimeSeconds": 145
}
```

---

#### Export Survey Responses
```http
GET /admin/surveys/:id/export
```

**Query Parameters:**
| Parameter | Type | Description |
|-----------|------|-------------|
| `format` | string | `csv` or `json` (default: `csv`) |

**Response:** File download (CSV or JSON)

CSV format:
```csv
response_id,user_id,started_at,completed_at,q1,q2,q3
resp_abc123,user_xyz,2024-01-15T10:30:00Z,2024-01-15T10:32:45Z,8,voice,Make it faster
```

---

### Public Endpoints (Authenticated)

#### Get Active Survey
```http
GET /public/surveys/active
```

Returns the active survey for the authenticated user, if any.

**Response:**
```json
{
  "id": "srv_123456789",
  "title": "Product Feedback Survey",
  "description": "Help us improve your experience",
  "questions": [
    {
      "id": "q1",
      "type": "nps",
      "text": "How likely are you to recommend us?",
      "required": true,
      "minValue": 0,
      "maxValue": 10
    }
  ],
  "currentQuestionIndex": 0,
  "incentive": {
    "type": "pro_days",
    "amount": 7
  }
}
```

Or `204 No Content` if no active survey.

---

#### Start Survey
```http
POST /public/surveys/:id/start
```

**Response:**
```json
{
  "success": true,
  "surveyStateId": "ss_987654321",
  "currentQuestionIndex": 0
}
```

---

#### Submit Answer
```http
POST /public/surveys/:id/answers
```

**Request Body:**
```json
{
  "questionId": "q1",
  "answer": {
    "type": "rating",
    "value": { "value": 8 }
  }
}
```

**Response:**
```json
{
  "success": true,
  "currentQuestionIndex": 1,
  "nextQuestionId": "q2",
  "isComplete": false
}
```

---

#### Complete Survey
```http
POST /public/surveys/:id/complete
```

**Response:**
```json
{
  "success": true,
  "incentiveClaimed": true,
  "incentiveType": "pro_days",
  "incentiveAmount": 7
}
```

---

#### Dismiss Survey
```http
POST /public/surveys/:id/dismiss
```

**Response:**
```json
{
  "success": true,
  "message": "Survey dismissed"
}
```

---

## Types Reference

### Broadcast Status
| Status | Description |
|--------|-------------|
| `draft` | Created but not yet sent |
| `scheduled` | Scheduled for future send |
| `sending` | Currently being sent |
| `paused` | Send paused by admin |
| `completed` | Fully sent and finished |

### Message Priority
| Priority | Description |
|----------|-------------|
| `low` | Silent delivery, no badge |
| `normal` | Standard notification |
| `high` | Prominent with sound |
| `urgent` | Critical, persistent alert |

### Message Style
| Style | Description |
|-------|-------------|
| `banner` | Top/bottom banner |
| `modal` | Center dialog |
| `fullscreen` | Full-screen takeover |
| `toast` | Brief ephemeral message |

### Survey Question Types
| Type | Description |
|------|-------------|
| `single_choice` | Radio button selection |
| `multiple_choice` | Checkbox multi-select |
| `rating` | Star rating (1-5) |
| `scale` | Numeric scale |
| `nps` | Net Promoter Score (0-10) |
| `text_short` | Single line text |
| `text_long` | Multi-line textarea |
| `ranking` | Drag-to-order items |
| `dropdown` | Single select dropdown |

---

## Error Responses

All errors follow this format:

```json
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Broadcast not found",
    "requestId": "req_abc123"
  }
}
```

### Error Codes
| Code | HTTP Status | Description |
|------|-------------|-------------|
| `BAD_REQUEST` | 400 | Invalid request data |
| `UNAUTHORIZED` | 401 | Missing or invalid token |
| `FORBIDDEN` | 403 | Insufficient permissions |
| `NOT_FOUND` | 404 | Resource not found |
| `CONFLICT` | 409 | Resource already exists |
| `RATE_LIMITED` | 429 | Too many requests |
| `INTERNAL_ERROR` | 500 | Server error |

---

## Rate Limits

| Endpoint Group | Limit |
|----------------|-------|
| Admin endpoints | 100 req/min per user |
| Public endpoints | 60 req/min per user |
| Message tracking | 1000 req/min per user |

---

## Webhooks

Events sent to configured webhook URLs:

### Broadcast Events
- `broadcast.created`
- `broadcast.sent`
- `broadcast.completed`
- `broadcast.read`
- `broadcast.clicked`

### Survey Events
- `survey.created`
- `survey.started`
- `survey.completed`
- `survey.response_submitted`

**Webhook Payload:**
```json
{
  "event": "broadcast.clicked",
  "timestamp": "2024-01-15T10:32:15Z",
  "data": {
    "broadcastId": "bc_123456789",
    "userId": "user_xyz",
    "messageId": "msg_987654321"
  }
}
```
