- OpenAPI-style reference for all admin and public endpoints - Request/response examples for broadcasts and surveys - Types reference, error codes, rate limits, webhooks
13 KiB
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 includeX-Product-IDheader
Authentication
Authorization: Bearer <jwt_token>
X-Product-ID: <product_id>
Broadcasts
Admin Endpoints
List Broadcasts
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:
{
"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
GET /admin/broadcasts/:id
Response: Single broadcast object (same as list item)
Create Broadcast
POST /admin/broadcasts
Request Body:
{
"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
PUT /admin/broadcasts/:id
Request Body: Partial broadcast object (same as create)
Response: Updated broadcast object
Delete Broadcast
DELETE /admin/broadcasts/:id
Response: 204 No Content
Send Broadcast
POST /admin/broadcasts/:id/send
Triggers immediate send (or schedules if scheduledAt is set).
Response:
{
"success": true,
"message": "Broadcast queued for sending",
"estimatedReach": 1500
}
Pause Broadcast
POST /admin/broadcasts/:id/pause
Pauses a sending broadcast.
Response:
{
"success": true,
"message": "Broadcast paused"
}
Get Broadcast Metrics
GET /admin/broadcasts/:id/metrics
Response:
{
"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
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
GET /public/messages/in-app
Returns active in-app messages for the authenticated user.
Response:
{
"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
POST /public/messages/:id/read
Response:
{
"success": true,
"message": "Marked as read"
}
Dismiss Message
POST /public/messages/:id/dismiss
Response:
{
"success": true,
"message": "Message dismissed"
}
Track Message Click
POST /public/messages/:id/click
Response:
{
"success": true,
"message": "Click tracked"
}
Surveys
Admin Endpoints
List Surveys
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:
{
"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
GET /admin/surveys/:id
Response: Full survey with questions
{
"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
POST /admin/surveys
Request Body:
{
"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
PUT /admin/surveys/:id
Request Body: Partial survey object
Response: Updated survey object
Delete Survey
DELETE /admin/surveys/:id
Response: 204 No Content
Get Survey Metrics
GET /admin/surveys/:id/metrics
Response:
{
"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
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:
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
GET /public/surveys/active
Returns the active survey for the authenticated user, if any.
Response:
{
"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
POST /public/surveys/:id/start
Response:
{
"success": true,
"surveyStateId": "ss_987654321",
"currentQuestionIndex": 0
}
Submit Answer
POST /public/surveys/:id/answers
Request Body:
{
"questionId": "q1",
"answer": {
"type": "rating",
"value": { "value": 8 }
}
}
Response:
{
"success": true,
"currentQuestionIndex": 1,
"nextQuestionId": "q2",
"isComplete": false
}
Complete Survey
POST /public/surveys/:id/complete
Response:
{
"success": true,
"incentiveClaimed": true,
"incentiveType": "pro_days",
"incentiveAmount": 7
}
Dismiss Survey
POST /public/surveys/:id/dismiss
Response:
{
"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:
{
"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.createdbroadcast.sentbroadcast.completedbroadcast.readbroadcast.clicked
Survey Events
survey.createdsurvey.startedsurvey.completedsurvey.response_submitted
Webhook Payload:
{
"event": "broadcast.clicked",
"timestamp": "2024-01-15T10:32:15Z",
"data": {
"broadcastId": "bc_123456789",
"userId": "user_xyz",
"messageId": "msg_987654321"
}
}