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:
parent
c4c84ddf16
commit
3842f65c81
750
docs/BROADCAST_SURVEY_API_REFERENCE.md
Normal file
750
docs/BROADCAST_SURVEY_API_REFERENCE.md
Normal 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"
|
||||
}
|
||||
}
|
||||
```
|
||||
Loading…
Reference in New Issue
Block a user