Version: 1.0 Date: 2025-10-23 Purpose: REST API extension for Mixpost to enable n8n integration
This specification defines a REST API add-on for Mixpost that enables external workflow automation tools (like n8n) to interact with Mixpost programmatically. The API follows RESTful principles and Laravel best practices.
- ✅ Create, schedule, and publish social media posts
- ✅ Upload and manage media files
- ✅ Manage social media accounts
- ✅ Retrieve analytics and reports
- ✅ Manage tags and metadata
- ✅ Token-based authentication (Laravel Sanctum)
- ✅ Comprehensive error handling
- ✅ Full CRUD operations on all resources
Token Generation:
POST /api/mixpost/auth/tokens
Content-Type: application/json
{
"email": "[email protected]",
"password": "secret",
"token_name": "n8n-integration",
"abilities": ["*"]
}Response:
{
"token": "1|abc123def456...",
"token_type": "Bearer",
"expires_at": null
}Usage:
Authorization: Bearer 1|abc123def456...Token Revocation:
DELETE /api/mixpost/auth/tokens/{token_id}
Authorization: Bearer 1|abc123def456...Base URL: /api/mixpost
GET /api/mixpost/posts
Authorization: Bearer {token}Query Parameters:
page(int): Page number (default: 1)per_page(int): Items per page (default: 20, max: 100)status(string): Filter by status (draft, scheduled, published, failed)accounts[](array): Filter by account IDstags[](array): Filter by tag IDskeyword(string): Search in post contentfrom_date(date): Filter from date (Y-m-d)to_date(date): Filter to date (Y-m-d)
Response (200 OK):
{
"data": [
{
"id": 1,
"uuid": "9b8c1234-5678-90ab-cdef-1234567890ab",
"status": "scheduled",
"schedule_status": "pending",
"scheduled_at": "2025-10-24T10:00:00.000000Z",
"published_at": null,
"accounts": [
{
"id": 1,
"uuid": "account-uuid",
"name": "Twitter Account",
"username": "@mycompany",
"provider": "twitter",
"errors": null,
"provider_post_id": null
}
],
"versions": [
{
"id": 1,
"account_id": null,
"is_original": true,
"content": [
{
"body": "Check out our latest update!",
"media": [1, 2]
}
]
}
],
"tags": [
{
"id": 1,
"name": "marketing"
}
],
"created_at": "2025-10-23T15:30:00.000000Z",
"updated_at": "2025-10-23T15:30:00.000000Z"
}
],
"links": {
"first": "http://example.com/api/mixpost/posts?page=1",
"last": "http://example.com/api/mixpost/posts?page=5",
"prev": null,
"next": "http://example.com/api/mixpost/posts?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"per_page": 20,
"to": 20,
"total": 95
}
}GET /api/mixpost/posts/{uuid}
Authorization: Bearer {token}Response (200 OK):
{
"data": {
"id": 1,
"uuid": "9b8c1234-5678-90ab-cdef-1234567890ab",
"status": "scheduled",
"schedule_status": "pending",
"scheduled_at": "2025-10-24T10:00:00.000000Z",
"published_at": null,
"accounts": [...],
"versions": [...],
"tags": [...],
"created_at": "2025-10-23T15:30:00.000000Z",
"updated_at": "2025-10-23T15:30:00.000000Z"
}
}POST /api/mixpost/posts
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body:
{
"accounts": [1, 2, 3],
"tags": [1, 2],
"date": "2025-10-24",
"time": "10:00",
"versions": [
{
"is_original": true,
"account_id": null,
"content": [
{
"body": "Check out our latest blog post! #marketing #content",
"media": [1, 2]
}
]
},
{
"is_original": false,
"account_id": 2,
"content": [
{
"body": "Custom version for Twitter with mentions @partner",
"media": [1]
}
]
}
]
}Field Descriptions:
accounts(array, required): Array of account IDs to post totags(array, optional): Array of tag IDsdate(string, optional): Schedule date (Y-m-d format)time(string, optional): Schedule time (H:i format)versions(array, required): Array of post versionsis_original(boolean, required): Is this the default version?account_id(int, nullable): Specific account for custom versioncontent(array, required): Array of content blocksbody(string, nullable): Post text (max 5000 chars)media(array, optional): Array of media IDs
Response (201 Created):
{
"data": {
"id": 1,
"uuid": "9b8c1234-5678-90ab-cdef-1234567890ab",
"status": "draft",
"schedule_status": "pending",
"scheduled_at": "2025-10-24T10:00:00.000000Z",
"published_at": null,
"accounts": [...],
"versions": [...],
"tags": [...],
"created_at": "2025-10-23T15:30:00.000000Z",
"updated_at": "2025-10-23T15:30:00.000000Z"
},
"message": "Post created successfully"
}Error Response (422 Unprocessable Entity):
{
"message": "The given data was invalid.",
"errors": {
"accounts": ["The accounts field is required."],
"versions": ["The versions field must have at least 1 items."],
"versions.0.content.0.body": ["The body may not be greater than 5000 characters."]
}
}PUT /api/mixpost/posts/{uuid}
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body: Same as Create Post
Response (200 OK):
{
"data": {...},
"message": "Post updated successfully"
}DELETE /api/mixpost/posts/{uuid}
Authorization: Bearer {token}Response (200 OK):
{
"message": "Post deleted successfully"
}POST /api/mixpost/posts/{uuid}/schedule
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body:
{
"date": "2025-10-24",
"time": "10:00"
}Response (200 OK):
{
"data": {
"id": 1,
"uuid": "9b8c1234-5678-90ab-cdef-1234567890ab",
"status": "scheduled",
"scheduled_at": "2025-10-24T10:00:00.000000Z",
...
},
"message": "Post scheduled successfully"
}POST /api/mixpost/posts/{uuid}/publish
Authorization: Bearer {token}Response (200 OK):
{
"data": {
"id": 1,
"uuid": "9b8c1234-5678-90ab-cdef-1234567890ab",
"status": "scheduled",
"scheduled_at": "2025-10-23T15:35:00.000000Z",
...
},
"message": "Post queued for immediate publishing"
}POST /api/mixpost/posts/{uuid}/duplicate
Authorization: Bearer {token}Response (201 Created):
{
"data": {
"id": 2,
"uuid": "new-uuid",
"status": "draft",
...
},
"message": "Post duplicated successfully"
}DELETE /api/mixpost/posts
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body:
{
"posts": ["uuid1", "uuid2", "uuid3"]
}Response (200 OK):
{
"message": "3 posts deleted successfully"
}GET /api/mixpost/media
Authorization: Bearer {token}Query Parameters:
page(int): Page numberper_page(int): Items per page (default: 20, max: 100)search(string): Search by filename
Response (200 OK):
{
"data": [
{
"id": 1,
"uuid": "media-uuid",
"name": "image.jpg",
"mime_type": "image/jpeg",
"size": 1024000,
"size_total": 1024000,
"disk": "public",
"path": "mixpost/media/2025/10/image.jpg",
"url": "http://example.com/storage/mixpost/media/2025/10/image.jpg",
"conversions": {
"thumb": "mixpost/media/2025/10/image-thumb.jpg",
"medium": "mixpost/media/2025/10/image-medium.jpg"
},
"created_at": "2025-10-23T15:30:00.000000Z"
}
],
"meta": {...}
}GET /api/mixpost/media/{uuid}
Authorization: Bearer {token}Response (200 OK):
{
"data": {
"id": 1,
"uuid": "media-uuid",
"name": "image.jpg",
...
}
}POST /api/mixpost/media
Authorization: Bearer {token}
Content-Type: multipart/form-dataRequest Body:
file: [binary file data]
Supported Formats:
- Images: jpg, jpeg, png, gif, webp
- Videos: mp4, mov, avi
- Max file size: Configured in Mixpost settings
Response (201 Created):
{
"data": {
"id": 1,
"uuid": "media-uuid",
"name": "image.jpg",
"mime_type": "image/jpeg",
"size": 1024000,
"url": "http://example.com/storage/mixpost/media/2025/10/image.jpg",
...
},
"message": "Media uploaded successfully"
}POST /api/mixpost/media/download
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body:
{
"url": "https://example.com/image.jpg"
}Response (201 Created):
{
"data": {...},
"message": "Media downloaded successfully"
}DELETE /api/mixpost/media/{uuid}
Authorization: Bearer {token}Response (200 OK):
{
"message": "Media deleted successfully"
}DELETE /api/mixpost/media
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body:
{
"media": ["uuid1", "uuid2", "uuid3"]
}Response (200 OK):
{
"message": "3 media files deleted successfully"
}GET /api/mixpost/accounts
Authorization: Bearer {token}Response (200 OK):
{
"data": [
{
"id": 1,
"uuid": "account-uuid",
"name": "My Twitter Account",
"username": "@mycompany",
"provider": "twitter",
"provider_id": "123456789",
"authorized": true,
"image": "https://pbs.twimg.com/profile_images/.../avatar.jpg",
"data": {
"followers_count": 1000,
"following_count": 500
},
"created_at": "2025-01-15T10:00:00.000000Z",
"updated_at": "2025-10-23T12:00:00.000000Z"
}
]
}GET /api/mixpost/accounts/{uuid}
Authorization: Bearer {token}Response (200 OK):
{
"data": {
"id": 1,
"uuid": "account-uuid",
...
}
}PUT /api/mixpost/accounts/{uuid}
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body:
{
"name": "Updated Account Name"
}Response (200 OK):
{
"data": {...},
"message": "Account updated successfully"
}DELETE /api/mixpost/accounts/{uuid}
Authorization: Bearer {token}Response (200 OK):
{
"message": "Account deleted successfully"
}GET /api/mixpost/tags
Authorization: Bearer {token}Response (200 OK):
{
"data": [
{
"id": 1,
"name": "marketing",
"created_at": "2025-10-23T15:30:00.000000Z",
"updated_at": "2025-10-23T15:30:00.000000Z"
}
]
}POST /api/mixpost/tags
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body:
{
"name": "product-launch"
}Response (201 Created):
{
"data": {
"id": 2,
"name": "product-launch",
"created_at": "2025-10-23T15:30:00.000000Z",
"updated_at": "2025-10-23T15:30:00.000000Z"
},
"message": "Tag created successfully"
}PUT /api/mixpost/tags/{id}
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body:
{
"name": "updated-tag-name"
}Response (200 OK):
{
"data": {...},
"message": "Tag updated successfully"
}DELETE /api/mixpost/tags/{id}
Authorization: Bearer {token}Response (200 OK):
{
"message": "Tag deleted successfully"
}GET /api/mixpost/reports/accounts/{account_uuid}
Authorization: Bearer {token}Query Parameters:
from_date(date): Start date (Y-m-d)to_date(date): End date (Y-m-d)metrics[](array): Specific metrics (followers, engagement, impressions)
Response (200 OK):
{
"data": {
"account": {
"id": 1,
"uuid": "account-uuid",
"name": "Twitter Account",
"provider": "twitter"
},
"period": {
"from": "2025-10-01",
"to": "2025-10-23"
},
"metrics": {
"followers": {
"current": 1000,
"change": 50,
"change_percentage": 5.0
},
"posts": {
"total": 25,
"published": 23,
"failed": 2
},
"engagement": {
"total": 500,
"likes": 300,
"comments": 100,
"shares": 100
}
}
}
}GET /api/mixpost/reports/posts/{post_uuid}
Authorization: Bearer {token}Response (200 OK):
{
"data": {
"post": {
"id": 1,
"uuid": "post-uuid",
"status": "published"
},
"accounts": [
{
"account_id": 1,
"provider": "twitter",
"provider_post_id": "123456789",
"metrics": {
"impressions": 1000,
"likes": 50,
"comments": 10,
"shares": 5
}
}
]
}
}GET /api/mixpost/reports/dashboard
Authorization: Bearer {token}Query Parameters:
from_date(date): Start date (Y-m-d)to_date(date): End date (Y-m-d)
Response (200 OK):
{
"data": {
"period": {
"from": "2025-10-01",
"to": "2025-10-23"
},
"accounts": {
"total": 5,
"authorized": 5,
"unauthorized": 0
},
"posts": {
"total": 100,
"draft": 10,
"scheduled": 20,
"published": 65,
"failed": 5
},
"media": {
"total": 150,
"total_size": 524288000
},
"engagement": {
"total": 5000,
"likes": 3000,
"comments": 1000,
"shares": 1000
}
}
}GET /api/mixpost/calendar
Authorization: Bearer {token}Query Parameters:
date(string, required): Date in Y-m-d formattype(string, required): View type (month, week)
Response (200 OK):
{
"data": {
"date": "2025-10-23",
"type": "month",
"posts": [
{
"id": 1,
"uuid": "post-uuid",
"status": "scheduled",
"scheduled_at": "2025-10-24T10:00:00.000000Z",
"versions": [...],
"accounts": [...]
}
]
}
}GET /api/mixpost/system/status
Authorization: Bearer {token}Response (200 OK):
{
"data": {
"version": "1.0.0",
"environment": "production",
"queue": {
"connection": "redis",
"status": "running",
"jobs_pending": 5,
"jobs_failed": 0
},
"services": {
"configured": ["twitter", "facebook", "instagram"],
"active": ["twitter", "facebook"]
},
"storage": {
"disk": "public",
"total_media": 150,
"total_size": 524288000
}
}
}{
"data": {...},
"message": "Operation successful"
}{
"message": "Invalid request parameters",
"errors": {
"field": ["Error description"]
}
}{
"message": "Unauthenticated"
}{
"message": "This action is unauthorized"
}{
"message": "Resource not found"
}{
"message": "The given data was invalid.",
"errors": {
"field": ["Validation error description"]
}
}{
"message": "An error occurred while processing your request",
"error": "Error details (only in debug mode)"
}Default Limits:
- 60 requests per minute per token
- Configurable via Mixpost settings
Response Headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1729785600
Rate Limit Exceeded (429 Too Many Requests):
{
"message": "Too many requests. Please try again later.",
"retry_after": 30
}All list endpoints support pagination:
Request:
GET /api/mixpost/posts?page=2&per_page=50Response Structure:
{
"data": [...],
"links": {
"first": "http://example.com/api/mixpost/posts?page=1",
"last": "http://example.com/api/mixpost/posts?page=5",
"prev": "http://example.com/api/mixpost/posts?page=1",
"next": "http://example.com/api/mixpost/posts?page=3"
},
"meta": {
"current_page": 2,
"from": 51,
"last_page": 5,
"per_page": 50,
"to": 100,
"total": 235
}
}{
"workflow": "When new blog post published",
"action": "POST /api/mixpost/posts",
"body": {
"accounts": [1, 2, 3],
"tags": [1],
"date": "{{$now.plus(1, 'hour').format('YYYY-MM-DD')}}",
"time": "{{$now.plus(1, 'hour').format('HH:mm')}}",
"versions": [
{
"is_original": true,
"account_id": null,
"content": [
{
"body": "New blog post: {{$node.BlogPost.json.title}} - {{$node.BlogPost.json.url}}",
"media": []
}
]
}
]
}
}{
"workflow": "Generate image → Upload → Create post",
"steps": [
{
"step": 1,
"action": "POST /api/mixpost/media/download",
"body": {
"url": "{{$node.GenerateImage.json.image_url}}"
}
},
{
"step": 2,
"action": "POST /api/mixpost/posts",
"body": {
"accounts": [1, 2],
"versions": [
{
"is_original": true,
"content": [
{
"body": "Check out our latest visual!",
"media": ["{{$node.UploadMedia.json.data.id}}"]
}
]
}
]
}
}
]
}{
"workflow": "Emergency announcement",
"action": "POST /api/mixpost/posts/{uuid}/publish"
}{
"workflow": "Check post published successfully",
"action": "GET /api/mixpost/posts/{uuid}",
"condition": "{{$json.data.status}} === 'published'"
}- HTTPS Only: All API requests must use HTTPS in production
- Token Security: Store tokens securely, never commit to repositories
- Token Rotation: Implement periodic token rotation
- IP Whitelisting: Optional IP restriction for API access
- CORS: Configure appropriate CORS policies
- Input Validation: All inputs validated on server side
- Rate Limiting: Prevent abuse with request throttling
- ✅ Authentication (Sanctum tokens)
- ✅ Posts CRUD
- ✅ Media upload & management
- ✅ Basic error handling
- ✅ Accounts management
- ✅ Tags management
- ✅ Analytics & reports
- ✅ Calendar endpoints
- ✅ Webhooks for post status changes
- ✅ Bulk operations optimization
- ✅ Advanced filtering & search
- ✅ Rate limiting customization
- Review this specification
- Confirm requirements alignment
- Implement Laravel API routes & controllers
- Create API documentation (OpenAPI/Swagger)
- Build n8n integration examples
- Test with n8n workflows
- Deploy as Mixpost add-on package
Document Version: 1.0 Last Updated: 2025-10-23 Maintained By: Mixpost REST API Add-on Team