Complete reference for the BulkAPIs REST API. All endpoints use JSON request/response bodies and require API key authentication.
Base URL: https://bulkapis.com/api/v1
All API requests require a Bearer token in the Authorization header:
Authorization: Bearer bulk_ak_your_api_key_hereCreate API keys in the dashboard. Keys are shown once on creation โ store them securely. All keys are prefixed with bulk_ak_ and are SHA-256 hashed before storage.
All responses follow a consistent envelope:
Success
{
"success": true,
"data": { ... }
}Error
{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "...",
"retryAfter": "2026-..."
}
}BulkAPIs uses an annual membership model. Each plan includes a yearly API call quota. Social features (DMs, posts, account management) require a Social Accounts add-on ($50/mo per 50 accounts).
| Plan | Annual API Calls | Social Features |
|---|---|---|
| Base ($100/yr) | 3,000 | Requires add-on |
| Growth ($1,000/yr) | 30,000 | Requires add-on |
| Scale ($5,000/yr) | 250,000 | Requires add-on |
When you exceed your plan limit, API calls return a 403 with code API_CALLS_EXCEEDED. Upgrade your membership to increase your quota.
Step 1: Sign up and subscribe to a membership plan
Step 2: Add a Social Accounts pack and connect your X account via OAuth
Step 3: Create an API key in the dashboard
Step 4: Send your first API call
curl -X POST https://bulkapis.com/api/v1/dm/send \
-H "Authorization: Bearer bulk_ak_your_key" \
-H "Content-Type: application/json" \
-d '{
"accountId": "your_account_id",
"recipientUserId": "target_x_user_id",
"text": "Hello from BulkAPIs!"
}'| GET | /api/v1/accounts |
| GET | /api/v1/accounts/:accountId |
| DELETE | /api/v1/accounts/:accountId |
| GET | /api/v1/accounts/:accountId/health |
| POST | /api/v1/dm/send |
| GET | /api/v1/conversations?accountId= |
| GET | /api/v1/conversations/:conversationId?accountId= |
| GET | /api/v1/conversations/:conversationId/messages?accountId= |
| POST | /api/v1/conversations/:conversationId/messages |
| GET | /api/v1/posts?accountId= |
| POST | /api/v1/posts |
| GET | /api/v1/posts/:postId?accountId= |
| DELETE | /api/v1/posts/:postId?accountId= |
| GET | /api/v1/comments?accountId=&postId= |
| GET | /api/v1/comments/:postId?accountId= |
| POST | /api/v1/comments/:postId |
| GET | /api/v1/webhooks |
| POST | /api/v1/webhooks |
| GET | /api/v1/webhooks/:webhookId |
| PUT | /api/v1/webhooks/:webhookId |
| DELETE | /api/v1/webhooks/:webhookId |
| GET | /api/v1/api-keys |
| POST | /api/v1/api-keys |
| DELETE | /api/v1/api-keys?id= |
| GET | /api/v1/usage?from=&to= |
Send a DM to any X/Twitter user. This is the core feature โ most providers cannot initiate new DM conversations. Requires Social Accounts add-on.
{
"accountId": "string", // Your connected account ID
"recipientUserId": "string", // X user ID of the recipient
"text": "string" // Message content (max 10,000 chars)
}{
"success": true,
"data": {
"jobId": "abc123",
"status": "queued",
"message": "DM queued for delivery"
}
}DMs are processed asynchronously via a job queue. Set up a webhook for dm.sent and dm.failed events to track delivery status.
Create a new post (tweet) on X/Twitter via a connected account. Requires Social Accounts add-on.
{
"accountId": "string", // Your connected account ID
"text": "string" // Post content (max 280 chars for tweets)
}{
"success": true,
"data": {
"jobId": "def456",
"status": "queued",
"message": "Post queued for publishing"
}
}curl -X POST https://bulkapis.com/api/v1/posts \
-H "Authorization: Bearer bulk_ak_your_key" \
-H "Content-Type: application/json" \
-d '{
"accountId": "acc_xxx",
"text": "Hello world from BulkAPIs! ๐"
}'List all connected social media accounts for the authenticated user.
{
"success": true,
"data": [
{
"id": "acc_xxx",
"platform": "x",
"platformUserId": "1234567890",
"username": "johndoe",
"displayName": "John Doe",
"isActive": true,
"needsReauth": false,
"createdAt": "2026-01-15T10:30:00Z"
}
]
}curl https://bulkapis.com/api/v1/accounts \
-H "Authorization: Bearer bulk_ak_your_key"Create a new webhook endpoint to receive real-time event notifications.
{
"name": "string", // Descriptive name
"url": "string", // HTTPS endpoint URL
"secret": "string", // (optional) HMAC-SHA256 signing secret
"events": ["string"], // Array of event types to subscribe to
"isActive": true // (optional) defaults to true
}{
"success": true,
"data": {
"id": "wh_xxx",
"name": "Production Webhook",
"url": "https://example.com/webhooks",
"events": ["dm.received", "dm.sent"],
"isActive": true,
"createdAt": "2026-01-15T10:30:00Z"
}
}curl -X POST https://bulkapis.com/api/v1/webhooks \
-H "Authorization: Bearer bulk_ak_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Webhook",
"url": "https://example.com/webhooks",
"secret": "whsec_my_secret",
"events": ["dm.received", "dm.sent", "dm.failed"]
}'Configure webhooks to receive real-time event notifications. All payloads are signed with HMAC-SHA256 using your webhook secret.
// Verify the X-BulkAPIs-Signature header
const crypto = require('crypto');
const signature = crypto
.createHmac('sha256', webhookSecret)
.update(rawBody)
.digest('hex');
const isValid = signature === request.headers['x-bulkapis-signature'];Webhooks are delivered with automatic retries (up to 5 attempts) using exponential backoff. Failed deliveries after all retries are moved to a dead letter queue. Expect delivery within seconds of the event.
| Event | Description |
|---|---|
| dm.received | A DM was received on a connected account |
| dm.sent | A DM was successfully sent |
| dm.failed | A DM failed to send after retries |
| post.published | A post was successfully published |
| post.deleted | A post was deleted |
| comment.received | A comment/reply was received on a post |
{
"event": "dm.received",
"timestamp": "2026-02-22T01:00:00Z",
"data": {
"accountId": "acc_xxx",
"conversationId": "1234-5678",
"messageId": "msg_xxx",
"senderId": "9876543210",
"senderUsername": "johndoe",
"text": "Hey, I commented on your post!",
"createdAt": "2026-02-22T01:00:00Z"
}
}Content-Type: application/json
X-BulkAPIs-Signature: <hmac-sha256-hex>
X-BulkAPIs-Event: dm.received
X-BulkAPIs-Delivery-Id: <uuid>
X-BulkAPIs-Timestamp: <iso-8601>Rate limits are applied per connected account for platform-specific actions and per API key for general requests. Rate-limited responses include a Retry-After header.
| Endpoint | Limit |
|---|---|
| DM Send | 180 / 15 min per account |
| DM Read | 100 / 15 min per account |
| DM Events | 15 / 15 min per account |
| Post Create | 200 / 15 min per account |
| API Requests | 60 / min per API key |
| Code | Status | Description |
|---|---|---|
| UNAUTHORIZED | 401 | Missing or invalid API key |
| FORBIDDEN | 403 | API key does not have access, or plan limit exceeded |
| NOT_FOUND | 404 | Resource not found |
| VALIDATION_ERROR | 400 | Request body failed validation |
| RATE_LIMITED | 429 | Too many requests โ check Retry-After header |
| ACCOUNT_NEEDS_REAUTH | 400 | Connected account needs re-authorization |
| PLAN_LIMIT | 403 | Membership plan limit reached (upgrade required) |
| NO_SOCIAL_PACK | 403 | Social features require a Social Accounts add-on |
| API_CALLS_EXCEEDED | 403 | Annual API call quota exhausted |
| SOCIAL_ACCOUNTS_EXCEEDED | 403 | Connected account limit reached (add another pack) |
| PLATFORM_ERROR | 502 | Upstream platform API error |
| INTERNAL_ERROR | 500 | Unexpected server error |