API Reference #
Complete REST API documentation for the Message plugin.
🔑 Authentication #
All API requests require authentication using Bearer tokens.
Generating API Tokens #
- Navigate to Settings → API Settings
- Click "Generate New Token"
- Configure token settings:
- Name: Descriptive identifier
- IP Restrictions: Optional whitelist
- Permissions: Specific endpoints
Using Tokens #
Include token in Authorization header:
curl -H "Authorization: Bearer your-api-token-here" \
-H "Content-Type: application/json" \
https://your-domain.com/api/campaign/subscribers
Token Format #
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
🌐 Base URL #
All API endpoints are prefixed with:
https://your-domain.com/api/campaign
🔄 Recent API Updates #
MessageSchedule Endpoints - Manage recurring campaign schedules SenderProfile Endpoints - Manage sender identities Enhanced Message Endpoints - New send timing and recurring options
📋 Response Format #
All responses follow a consistent JSON structure:
Success Response #
{
"success": true,
"data": {
// Response data
},
"meta": {
"timestamp": "2024-01-15T10:30:00Z",
"version": "1.0"
}
}
Error Response #
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "The email field is required",
"details": {
"field": "email",
"rule": "required"
}
}
}
Pagination Response #
{
"success": true,
"data": [...],
"pagination": {
"total": 150,
"per_page": 20,
"current_page": 1,
"last_page": 8,
"next_page_url": "/api/campaign/subscribers?page=2",
"prev_page_url": null
}
}
👥 Subscribers API #
List Subscribers #
GET /api/campaign/subscribers
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
| page | integer | Page number | 1 |
| per_page | integer | Items per page (max 100) | 20 |
| list_id | integer | Filter by list | null |
| status | string | active, unsubscribed, unconfirmed | active |
| search | string | Search email/name | null |
Example Request:
curl -H "Authorization: Bearer token" \
"https://your-domain.com/api/campaign/subscribers?page=1&per_page=50&status=active"
Example Response:
{
"success": true,
"data": [
{
"id": 1,
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe",
"company_name": "Acme Corporation",
"phone": "(555) 123-4567",
"job_title": "Marketing Director",
"status": "active",
"lists": [1, 2],
"created_at": "2024-01-15T10:00:00Z",
"meta_data": {
"source": "website",
"preferences": ["newsletters", "promotions"]
}
}
],
"pagination": {
"total": 500,
"per_page": 50,
"current_page": 1
}
}
Get Subscriber #
GET /api/campaign/subscribers/{id}
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
| id | integer | Subscriber ID |
Example Response:
{
"success": true,
"data": {
"id": 1,
"email": "john@example.com",
"first_name": "John",
"last_name": "Doe",
"company_name": "Acme Corporation",
"phone": "(555) 123-4567",
"job_title": "Marketing Director",
"status": "active",
"lists": [
{
"id": 1,
"name": "Newsletter",
"code": "newsletter"
}
],
"confirmed_at": "2024-01-15T10:00:00Z",
"unsubscribed_at": null,
"messages_received": 15,
"messages_opened": 12,
"messages_clicked": 5
}
}
Create Subscriber #
POST /api/campaign/subscribers
Request Body:
{
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Smith",
"company_name": "Acme Corporation",
"phone": "(555) 123-4567",
"job_title": "Marketing Director",
"lists": [1, 2],
"confirmed": true,
"meta_data": {
"source": "api",
"referrer": "partner-site"
}
}
Response:
{
"success": true,
"data": {
"id": 123,
"email": "jane@example.com",
"status": "active",
"confirmation_sent": false
}
}
Update Subscriber #
PUT /api/campaign/subscribers/{id}
Request Body:
{
"first_name": "Jane",
"last_name": "Johnson",
"company_name": "New Company Inc",
"phone": "(555) 987-6543",
"job_title": "VP of Marketing",
"lists": [1, 3],
"meta_data": {
"preferences": ["weekly-digest"]
}
}
Delete Subscriber #
DELETE /api/campaign/subscribers/{id}
Response:
{
"success": true,
"message": "Subscriber deleted successfully"
}
Unsubscribe #
POST /api/campaign/subscribers/{id}/unsubscribe
Request Body (optional):
{
"reason": "Too many emails",
"feedback": "Would prefer monthly updates"
}
📋 Lists API #
Get All Lists #
GET /api/campaign/lists
Example Response:
{
"success": true,
"data": [
{
"id": 1,
"name": "Newsletter Subscribers",
"code": "newsletter",
"description": "Main newsletter list",
"subscriber_count": 1500,
"active_count": 1450,
"created_at": "2024-01-01T00:00:00Z"
}
]
}
Get List #
GET /api/campaign/lists/{id}
Create List #
POST /api/campaign/lists
Request Body:
{
"name": "VIP Customers",
"code": "vip",
"description": "Premium customer segment"
}
Update List #
PUT /api/campaign/lists/{id}
Delete List #
DELETE /api/campaign/lists/{id}
Add Subscribers to List #
POST /api/campaign/lists/{id}/subscribers
Request Body:
{
"subscriber_ids": [1, 2, 3, 4, 5]
}
Remove Subscribers from List #
DELETE /api/campaign/lists/{id}/subscribers
Request Body:
{
"subscriber_ids": [1, 2]
}
✉️ Messages API #
List Messages #
GET /api/campaign/messages
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| status | string | draft, pending, active, sent, cancelled |
| from_date | string | ISO 8601 date |
| to_date | string | ISO 8601 date |
Get Message #
GET /api/campaign/messages/{id}
Example Response:
{
"success": true,
"data": {
"id": 1,
"name": "January Newsletter",
"subject": "Happy New Year!",
"status": "sent",
"sent_at": "2024-01-15T10:00:00Z",
"stats": {
"sent": 1500,
"opened": 750,
"clicked": 225,
"unsubscribed": 5
},
"open_rate": 50.0,
"click_rate": 15.0
}
}
Create Message #
POST /api/campaign/messages
Request Body:
{
"name": "February Newsletter",
"subject": "Valentine's Day Special",
"preheader": "Exclusive offers inside",
"content_html": "<html>...</html>",
"content_text": "Plain text version...",
"from_name": "Your Company",
"from_email": "news@company.com"
}
Update Message #
PUT /api/campaign/messages/{id}
Note: Can only update messages in 'draft' status.
Send Message #
POST /api/campaign/messages/{id}/send
Request Body:
{
"list_ids": [1, 2],
"scheduled_at": "2024-02-01T10:00:00Z",
"test_mode": false
}
Send Test Message #
POST /api/campaign/messages/{id}/test
Request Body:
{
"email": "test@example.com"
}
Cancel Message #
POST /api/campaign/messages/{id}/cancel
Get Message Statistics #
GET /api/campaign/messages/{id}/stats
Example Response:
{
"success": true,
"data": {
"summary": {
"sent": 1500,
"delivered": 1485,
"opened": 750,
"clicked": 225,
"unsubscribed": 5,
"bounced": 15,
"complained": 2
},
"rates": {
"delivery_rate": 99.0,
"open_rate": 50.5,
"click_rate": 15.2,
"unsubscribe_rate": 0.34,
"bounce_rate": 1.0,
"complaint_rate": 0.13
},
"timeline": {
"hourly": [...],
"daily": [...]
}
}
}
📅 Message Schedules API #
List Schedules #
GET /api/campaign/schedules
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
| message_id | integer | Filter by message | null |
| is_active | boolean | Active schedules only | null |
Example Response:
{
"success": true,
"data": [
{
"id": 1,
"message_id": 5,
"frequency": "weekly",
"send_time": "09:00",
"timezone": "America/New_York",
"day_of_week": 1,
"is_active": true,
"run_count": 15,
"next_run_at": "2024-02-12T09:00:00Z"
}
]
}
Get Schedule #
GET /api/campaign/schedules/{id}
Create Schedule #
POST /api/campaign/schedules
Request Body:
{
"message_id": 5,
"frequency": "weekly",
"send_time": "09:00",
"timezone": "America/New_York",
"day_of_week": 1,
"max_runs": 52
}
Update Schedule #
PUT /api/campaign/schedules/{id}
Pause Schedule #
POST /api/campaign/schedules/{id}/pause
Resume Schedule #
POST /api/campaign/schedules/{id}/resume
Delete Schedule #
DELETE /api/campaign/schedules/{id}
👤 Sender Profiles API #
List Sender Profiles #
GET /api/campaign/sender-profiles
Example Response:
{
"success": true,
"data": [
{
"id": 1,
"name": "Marketing Team",
"from_name": "Acme Marketing",
"from_email": "marketing@acme.com",
"reply_to_email": "support@acme.com",
"is_default": true
}
]
}
Get Sender Profile #
GET /api/campaign/sender-profiles/{id}
Create Sender Profile #
POST /api/campaign/sender-profiles
Request Body:
{
"name": "Newsletter Team",
"from_name": "Acme Weekly",
"from_email": "newsletter@acme.com",
"reply_to_email": "support@acme.com",
"is_default": false
}
Update Sender Profile #
PUT /api/campaign/sender-profiles/{id}
Delete Sender Profile #
DELETE /api/campaign/sender-profiles/{id}
📊 Analytics API #
Get Dashboard Stats #
GET /api/campaign/analytics/dashboard
Query Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
| period | string | 7d, 30d, 90d, 1y | 30d |
Get Subscriber Growth #
GET /api/campaign/analytics/growth
Example Response:
{
"success": true,
"data": {
"current_period": {
"new_subscribers": 150,
"unsubscribes": 10,
"net_growth": 140,
"growth_rate": 9.3
},
"previous_period": {
"new_subscribers": 120,
"unsubscribes": 15,
"net_growth": 105,
"growth_rate": 7.0
},
"chart_data": [
{
"date": "2024-01-01",
"subscribers": 1500,
"new": 10,
"unsubscribed": 1
}
]
}
}
Get Message Performance #
GET /api/campaign/analytics/performance
Get Engagement Metrics #
GET /api/campaign/analytics/engagement
🔄 Webhooks API #
List Webhooks #
GET /api/campaign/webhooks
Create Webhook #
POST /api/campaign/webhooks
Request Body:
{
"name": "Order System Webhook",
"url": "https://orders.example.com/webhook",
"events": ["sent", "opened", "clicked"],
"secret": "webhook-secret-key",
"active": true
}
Update Webhook #
PUT /api/campaign/webhooks/{id}
Delete Webhook #
DELETE /api/campaign/webhooks/{id}
Test Webhook #
POST /api/campaign/webhooks/{id}/test
🚦 Rate Limiting #
API requests are rate limited to prevent abuse:
Default Limits #
- Global: 1000 requests per hour
- Per Endpoint: Varies by endpoint
- GET requests: 500/hour
- POST requests: 100/hour
- DELETE requests: 50/hour
Rate Limit Headers #
Response includes rate limit information:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 1642248000
Handling Rate Limits #
When limit exceeded:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Too many requests",
"retry_after": 3600
}
}
🔍 Search & Filtering #
Search Operators #
Use search parameter with operators:
email:john@example.com // Exact email match
name:John // Name contains
list:newsletter // In specific list
status:active // Status filter
created:>2024-01-01 // Created after date
meta.source:api // Meta data search
Complex Queries #
Combine operators:
GET /api/campaign/subscribers?search=status:active list:vip created:>2024-01-01
📦 Batch Operations #
Batch Create Subscribers #
POST /api/campaign/subscribers/batch
Request Body:
{
"subscribers": [
{
"email": "user1@example.com",
"first_name": "User",
"last_name": "One"
},
{
"email": "user2@example.com",
"first_name": "User",
"last_name": "Two"
}
],
"lists": [1, 2],
"skip_confirmation": false
}
Batch Update #
PUT /api/campaign/subscribers/batch
Batch Delete #
DELETE /api/campaign/subscribers/batch
🛠️ Error Codes #
HTTP Status Codes #
| Code | Description |
|---|---|
| 200 | Success |
| 201 | Created |
| 204 | No Content |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 422 | Validation Error |
| 429 | Rate Limit Exceeded |
| 500 | Server Error |
Application Error Codes #
| Code | Description |
|---|---|
| AUTH_INVALID_TOKEN | Invalid or expired token |
| AUTH_INSUFFICIENT_PERMISSIONS | Token lacks required permissions |
| VALIDATION_ERROR | Input validation failed |
| RESOURCE_NOT_FOUND | Requested resource doesn't exist |
| DUPLICATE_ENTRY | Resource already exists |
| QUOTA_EXCEEDED | Account limit reached |
🔧 SDK Examples #
PHP #
$client = new CampaignClient([
'base_url' => 'https://your-domain.com/api/campaign',
'token' => 'your-api-token'
]);
$subscribers = $client->subscribers()->list([
'page' => 1,
'per_page' => 50,
'status' => 'active'
]);
JavaScript #
const campaign = new CampaignAPI({
baseURL: 'https://your-domain.com/api/campaign',
token: 'your-api-token'
});
const subscribers = await campaign.subscribers.list({
page: 1,
perPage: 50,
status: 'active'
});
Python #
client = CampaignClient(
base_url='https://your-domain.com/api/campaign',
token='your-api-token'
)
subscribers = client.subscribers.list(
page=1,
per_page=50,
status='active'
)
📝 Changelog Webhooks #
Get notified of API changes:
POST /api/campaign/changelog/subscribe
{
"email": "dev@example.com",
"webhook_url": "https://example.com/api-changes"
}
Next: Troubleshooting Guide →