docs(broadcasts,surveys): Complete API reference documentation

- OpenAPI-style reference for all admin and public endpoints
- Request/response examples for broadcasts and surveys
- Types reference, error codes, rate limits, webhooks
This commit is contained in:
saravanakumardb1 2026-03-03 08:28:15 -08:00
parent c4c84ddf16
commit 3842f65c81

View File

@ -0,0 +1,750 @@
# 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"
}
}
```