Base URL
https://api.sbl.so
/auth/tokenAuthenticates a user with email/password and returns a bearer token valid for 30 days. If a 401 Unauthorized is returned on any other endpoint, regenerate the token and retry.
Request Body Fields
| Name | Type | Required | Description |
|---|---|---|---|
| string | Yes | Your account email address | |
| password | string | Yes | Your account password |
Request Body Example
{
"email": "user@example.com",
"password": "your_password"
}Response (200 OK)
{
"token": "eyJhbGciOiJIUzI1NiIsInR5..."
}Error Responses
| Status | Description |
|---|---|
| 400 | Missing or invalid parameters |
| 401 | Invalid email or password |
| 429 | Too many requests — check Retry-After header and retry |
/campaignsReturns a list of campaigns for a company.
Authentication
Authorization: Bearer <token>
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| companyId | string | Yes | The ID of the company |
| statuses | string | string[] | No | Filter by campaign status(es) |
| types | string | string[] | No | Filter by campaign type(s) |
| isArchived | boolean | No | Filter archived campaigns (default: false) |
| searchQuery | string | No | Search campaigns by name |
| lastCampaignId | string | No | Pagination cursor — ID of the last campaign from previous page |
Response (200 OK)
[
{
"id": "123",
"name": "My Campaign",
"status": "running",
"type": "outbound",
"communicationChannelToUse": 1,
"statistics": {},
"createdAt": "2024-01-01T00:00:00.000Z"
}
]Error Responses
| Status | Description |
|---|---|
| 401 | Token expired or invalid |
| 403 | Company does not belong to the logged-in user |
| 429 | Too many requests — check Retry-After header and retry |
/campaigns/:campaignIdReturns full details for a single campaign.
Authentication
Authorization: Bearer <token>
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| campaignId | string | Yes | The ID of the campaign |
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| companyId | string | Yes | The ID of the company |
Response (200 OK)
{
"id": "123",
"name": "My Campaign",
"status": "running",
"type": "outbound",
"objective": "...",
"initialMessage": "Hello!",
"communicationChannelToUse": 1,
"statistics": {},
"analytics": {},
"batches": [],
"createdAt": "2024-01-01T00:00:00.000Z"
}Error Responses
| Status | Description |
|---|---|
| 401 | Token expired or invalid |
| 403 | Company does not belong to the logged-in user |
| 429 | Too many requests — check Retry-After header and retry |
/campaigns/:campaignId/usersReturns a paginated list of users in a campaign.
Authentication
Authorization: Bearer <token>
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| campaignId | string | Yes | The ID of the campaign |
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| companyId | string | Yes | The ID of the company |
| userChatStatus | number | No | Filter by user chat status |
| searchQuery | string | No | Search users by name |
| lastUserId | string | No | Pagination cursor — ID of the last user from previous page |
Response (200 OK)
[
{
"id": "456",
"name": "John Doe",
"phoneNumber": "+1234567890",
"email": null,
"linkedinChannelDetails": null,
"tags": [],
"aiChatOff": false,
"status": 1,
"lastMessageCreatedAt": "2024-01-01T00:00:00.000Z",
"createdAt": "2024-01-01T00:00:00.000Z"
}
]Error Responses
| Status | Description |
|---|---|
| 401 | Token expired or invalid |
| 403 | Company does not belong to the logged-in user |
| 429 | Too many requests — check Retry-After header and retry |
/campaigns/:campaignId/users/:userId/messagesReturns messages in a user's conversation within a campaign, ordered oldest first.
Authentication
Authorization: Bearer <token>
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| campaignId | string | Yes | The ID of the campaign |
| userId | string | Yes | The ID of the company user |
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| companyId | string | Yes | The ID of the company |
| lastMessageId | string | No | Pagination cursor — ID of the last message from previous page |
Response (200 OK)
[
{
"id": "789",
"senderType": "bot",
"content": "Hello, welcome!",
"type": "text",
"status": 2,
"communicationChannelUsed": 1,
"trigger": "initial",
"scheduledFor": null,
"createdAt": "2024-01-01T00:00:00.000Z"
}
]Error Responses
| Status | Description |
|---|---|
| 401 | Token expired or invalid |
| 403 | Company does not belong to the logged-in user |
| 429 | Too many requests — check Retry-After header and retry |
/campaigns/:campaignId/human-interventionReturns users in the campaign that require human intervention.
Authentication
Authorization: Bearer <token>
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| campaignId | string | Yes | The ID of the campaign |
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| companyId | string | Yes | The ID of the company |
| lastUserId | string | No | Pagination cursor — ID of the last user from previous page |
Response (200 OK)
[
{
"id": "456",
"name": "John Doe",
"phoneNumber": "+1234567890",
"email": null,
"linkedinChannelDetails": null,
"tags": [],
"aiChatOff": false,
"status": 1,
"lastMessageCreatedAt": "2024-01-01T00:00:00.000Z",
"createdAt": "2024-01-01T00:00:00.000Z"
}
]Error Responses
| Status | Description |
|---|---|
| 401 | Token expired or invalid |
| 403 | Company does not belong to the logged-in user |
| 429 | Too many requests — check Retry-After header and retry |
/campaigns/generateAI-generates a new campaign based on a natural language description.
Authentication
Authorization: Bearer <token>
Request Body Fields
| Name | Type | Required | Description |
|---|---|---|---|
| companyId | string | Yes | The ID of the company |
| description | string | Yes | Natural language description of the campaign goal |
| communicationChannel | number | Yes | 1 = WhatsApp, 3 = LinkedIn |
Request Body Example
{
"companyId": "123",
"description": "Reach out to CTOs at fintech companies about our new product",
"communicationChannel": 1
}Response (200 OK)
{
"id": "456",
"pendingCommentToDM": false,
"pendingMetaAdId": false,
"pendingProductLinks": []
}Error Responses
| Status | Description |
|---|---|
| 400 | Missing or invalid parameters |
| 401 | Token expired or invalid |
| 403 | Company does not belong to the logged-in user |
| 429 | Too many requests — check Retry-After header and retry |
/campaigns/:campaignId/send-messageSends a message to a specific user in a campaign.
Authentication
Authorization: Bearer <token>
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| campaignId | string | Yes | The ID of the campaign |
Request Body Fields
| Name | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes | The ID of the company user |
| message | string | Yes | The message text to send |
Request Body Example
{
"userId": "789",
"message": "Hello, following up on our conversation!"
}Response (200 OK)
{
"messageId": "xxxx"
}Error Responses
| Status | Description |
|---|---|
| 400 | User not in campaign, campaign not running, channel not connected, or user in invalid chat state |
| 401 | Token expired or invalid — regenerate using /auth/token |
| 403 | Campaign does not belong to the logged-in user |
| 404 | Campaign not found |
| 429 | Too many requests — check Retry-After header and retry |
/campaigns/:campaignId/add-userAdds a new user to a campaign. WhatsApp campaigns require phoneNumber; LinkedIn campaigns require linkedinProfileUrl. LinkedIn campaigns can also include customMessage for templates that use [custom message].
Authentication
Authorization: Bearer <token>
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| campaignId | string | Yes | The ID of the campaign |
Request Body Fields
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Full name of the user |
| phoneNumber | string | No | Required for WhatsApp campaigns |
| linkedinProfileUrl | string | No | Required for LinkedIn campaigns |
| customVariables | object | No | Key-value pairs of custom data to attach to the user. Keys and values must be non-empty strings. |
| customMessage | string | No | LinkedIn-only custom text used to replace [custom message] in campaign messages. |
Request Body Example
{
"name": "John Doe",
"linkedinProfileUrl": "https://www.linkedin.com/in/johndoe",
"customVariables": {
"company": "Acme Inc",
"role": "CTO"
},
"customMessage": "I noticed Acme recently expanded its engineering team."
}Response (200 OK)
This endpoint returns an empty response body (HTTP 200).
Error Responses
| Status | Description |
|---|---|
| 400 | Campaign not in a valid state, contact field does not match campaign channel, or customMessage is used outside a LinkedIn campaign |
| 401 | Token expired or invalid — regenerate using /auth/token |
| 403 | Campaign does not belong to the logged-in user |
| 404 | Campaign not found |
| 409 | User is already part of this campaign |
| 429 | Too many requests — check Retry-After header and retry |