{"openapi":"3.1.0","info":{"title":"BulkAPIs","version":"1.0.0","description":"Social media automation API. Send DMs, schedule posts, manage automations, and track analytics — all via API. Built for SaaS integrations.","contact":{"url":"https://bulkapis.com"}},"servers":[{"url":"https://bulkapis.com","description":"Production"},{"url":"http://localhost:4000","description":"Local development"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key obtained from /api/v1/api-keys. Pass as `Authorization: Bearer bulk_ak_...`"}},"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"retryAfter":{"type":"string"}}}}},"Post":{"type":"object","properties":{"id":{"type":"string"},"accountId":{"type":"string"},"platform":{"type":"string","enum":["x"]},"content":{"type":"string"},"mediaUrls":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["draft","scheduled","queued","publishing","published","failed"]},"replyToPostId":{"type":"string","description":"Platform post ID to reply to (creates a reply tweet)"},"quotedPostId":{"type":"string","description":"Platform post ID to quote (creates a quote tweet)"},"idempotencyKey":{"type":"string","description":"Caller-provided dedup key. Duplicate requests return the original post."},"scheduledFor":{"type":"string","format":"date-time"},"publishedAt":{"type":"string","format":"date-time"},"platformPostId":{"type":"string"},"platformPostUrl":{"type":"string"}}},"AutomationRule":{"type":"object","properties":{"id":{"type":"string"},"accountId":{"type":"string"},"isActive":{"type":"boolean"},"triggerType":{"type":"string","enum":["keyword_comment","any_comment","mention"]},"triggerKeyword":{"type":"string"},"actionType":{"type":"string","enum":["send_dm"]},"actionTemplate":{"type":"string","description":"Supports {{username}} and {{comment}} placeholders"},"triggerCount":{"type":"integer"}}},"ConnectedAccount":{"type":"object","properties":{"id":{"type":"string"},"platform":{"type":"string"},"platformUserId":{"type":"string"},"username":{"type":"string"},"displayName":{"type":"string"},"isActive":{"type":"boolean"},"needsReauth":{"type":"boolean"}}}},"parameters":{"page":{"name":"page","in":"query","schema":{"type":"integer","default":1}},"limit":{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},"accountId":{"name":"accountId","in":"query","schema":{"type":"string"}}}},"paths":{"/api/v1/accounts":{"get":{"tags":["Accounts"],"summary":"List connected social accounts","operationId":"listAccounts","responses":{"200":{"description":"List of accounts"}}}},"/api/v1/accounts/{accountId}":{"get":{"tags":["Accounts"],"summary":"Get account details","operationId":"getAccount","parameters":[{"name":"accountId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Account details"}}},"delete":{"tags":["Accounts"],"summary":"Disconnect account","operationId":"disconnectAccount","parameters":[{"name":"accountId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Account disconnected"}}}},"/api/v1/accounts/{accountId}/health":{"get":{"tags":["Accounts"],"summary":"Check account health (token validity)","operationId":"checkAccountHealth","description":"Pings X API to verify the OAuth token is valid. Returns `healthy` (boolean) and `needsReauth` (boolean). If unhealthy, the account is flagged for re-authentication.","parameters":[{"name":"accountId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Health status with `accountId`, `healthy`, `needsReauth`, `checkedAt`"}}}},"/api/v1/dm/send":{"post":{"tags":["DMs"],"summary":"Send a DM (text, media, or both)","operationId":"sendDm","description":"Sends a direct message synchronously. Returns the X conversation ID for the DM thread that was created or used. Supports cold DMs (new conversations) and existing conversations. Can include text, a media attachment (image/GIF/video), or both. Media is fetched from the provided URL, uploaded to X with the correct DM media category, and attached to the message.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","recipientUserId"],"properties":{"accountId":{"type":"string","description":"Your connected account ID"},"recipientUserId":{"type":"string","description":"X user ID of the recipient"},"text":{"type":"string","maxLength":10000,"description":"Message text (required if no mediaUrl)"},"mediaUrl":{"type":"string","format":"uri","description":"Public URL of an image, GIF, or video to attach. Supported: JPEG, PNG, GIF, WEBP, MP4. Max 5MB for images, 15MB for GIFs, 512MB for video."},"idempotencyKey":{"type":"string","description":"Prevent duplicate sends"}}},"examples":{"textOnly":{"summary":"Text-only DM","value":{"accountId":"clxyz123","recipientUserId":"1234567890","text":"Hey! Thanks for the comment. Here's the link: https://example.com","idempotencyKey":"dm-user1234-campaign1"}},"withImage":{"summary":"DM with image","value":{"accountId":"clxyz123","recipientUserId":"1234567890","text":"Check out this product!","mediaUrl":"https://example.com/product.jpg"}},"mediaOnly":{"summary":"Media-only DM (no text)","value":{"accountId":"clxyz123","recipientUserId":"1234567890","mediaUrl":"https://example.com/promo.mp4"}}}}}},"responses":{"200":{"description":"DM sent successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"jobId":{"type":"string","description":"Unique reference ID for this send"},"status":{"type":"string","enum":["sent"],"description":"Always 'sent' on success"},"conversationId":{"type":"string","description":"X conversation ID for the DM thread"}}}}},"example":{"success":true,"data":{"jobId":"abc123","status":"sent","conversationId":"1234567890-9876543210"}}}}},"429":{"description":"Rate limited"}}}},"/api/v1/dm/send/bulk":{"post":{"tags":["DMs"],"summary":"Send DMs in bulk (text, media, or both)","operationId":"sendBulkDm","description":"Send up to 100 DMs in a single request. Each recipient can receive text, a media attachment, or both. Messages are staggered with configurable delay to avoid rate limits. Media URLs are fetched and uploaded to X per-message.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","recipients"],"properties":{"accountId":{"type":"string"},"recipients":{"type":"array","maxItems":100,"items":{"type":"object","required":["userId"],"properties":{"userId":{"type":"string"},"text":{"type":"string","description":"Message text (required if no mediaUrl)"},"mediaUrl":{"type":"string","format":"uri","description":"Public URL of media to attach (image, GIF, or video)"},"idempotencyKey":{"type":"string"}}}},"delayBetweenMs":{"type":"integer","default":2000,"description":"Delay between each DM (0-60000ms)"}}}}}},"responses":{"202":{"description":"Bulk DMs queued"}}}},"/api/v1/conversations":{"get":{"tags":["Inbox"],"summary":"List DM conversations","operationId":"listConversations","parameters":[{"name":"accountId","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["unread","read","archived"]}}],"responses":{"200":{"description":"List of conversations"}}}},"/api/v1/conversations/{conversationId}":{"get":{"tags":["Inbox"],"summary":"Get conversation details + messages","operationId":"getConversation","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Conversation with messages"}}},"patch":{"tags":["Inbox"],"summary":"Update conversation status (read/archive)","operationId":"updateConversation","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["read","archived"]}}}}}},"responses":{"200":{"description":"Updated"}}}},"/api/v1/conversations/{conversationId}/messages":{"get":{"tags":["Inbox"],"summary":"List messages in a conversation","operationId":"listMessages","description":"Returns messages with both canonical fields (`content`, `sentAt`) and aliases (`text`, `createdAt`) for backward compatibility.","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string"}},{"name":"accountId","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string","description":"Pagination cursor from previous response"}}],"responses":{"200":{"description":"Messages with `{ messages, pagination: { hasMore, nextCursor } }`"}}},"post":{"tags":["Inbox"],"summary":"Send a reply in an existing conversation (text, media, or both)","operationId":"sendConversationMessage","description":"Queues a DM reply for delivery to an existing conversation. Can include text, a media attachment, or both.","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId"],"properties":{"accountId":{"type":"string"},"text":{"type":"string","maxLength":10000,"description":"Message text (required if no mediaUrl)"},"mediaUrl":{"type":"string","format":"uri","description":"Public URL of media to attach (image, GIF, or video)"}}}}}},"responses":{"202":{"description":"Message queued for delivery"}}}},"/api/v1/posts":{"get":{"tags":["Posts"],"summary":"List posts","operationId":"listPosts","parameters":[{"name":"accountId","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["draft","scheduled","published","failed"]}},{"name":"page","in":"query","schema":{"type":"integer"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"List of posts"}}},"post":{"tags":["Posts"],"summary":"Create a post","operationId":"createPost","description":"Create a draft, schedule for later, or publish immediately. Supports replies (`replyToPostId`) and quote tweets (`quotedPostId`). Use `idempotencyKey` to prevent duplicate posts in retry scenarios. Media URLs are downloaded and uploaded to X automatically.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","content"],"properties":{"accountId":{"type":"string"},"content":{"type":"string","maxLength":25000},"mediaUrls":{"type":"array","items":{"type":"string"},"maxItems":4,"description":"Up to 4 media URLs. BulkAPIs downloads and uploads to X for you."},"status":{"type":"string","enum":["draft","scheduled","published"],"default":"published"},"scheduledFor":{"type":"string","format":"date-time"},"queue":{"type":"boolean","description":"Auto-schedule using next available slot"},"replyToPostId":{"type":"string","description":"Platform post ID to reply to (X: in_reply_to_tweet_id)"},"quotedPostId":{"type":"string","description":"Platform post ID to quote (X: quote_tweet_id)"},"idempotencyKey":{"type":"string","maxLength":255,"description":"Prevents duplicate posts. If a post with this key exists, returns the existing post."}}},"example":{"accountId":"clxyz123","content":"Just shipped our new API! Check it out at bulkapis.com","replyToPostId":"1234567890","idempotencyKey":"campaign-abc-post-1"}}}},"responses":{"200":{"description":"Deduplicated — existing post returned"},"201":{"description":"Post created"}}}},"/api/v1/posts/{postId}":{"get":{"tags":["Posts"],"summary":"Get post details + metrics","operationId":"getPost","parameters":[{"name":"postId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Post with latest metrics"}}},"put":{"tags":["Posts"],"summary":"Update post content or schedule","operationId":"updatePost","parameters":[{"name":"postId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Post updated"}}},"delete":{"tags":["Posts"],"summary":"Delete post (also deletes from platform if published)","operationId":"deletePost","parameters":[{"name":"postId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Post deleted"}}}},"/api/v1/posts/{postId}/retry":{"post":{"tags":["Posts"],"summary":"Retry a failed post","operationId":"retryPost","parameters":[{"name":"postId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"Post re-queued"}}}},"/api/v1/posts/{postId}/publish":{"post":{"tags":["Posts"],"summary":"Publish a draft/scheduled post immediately","operationId":"publishPost","parameters":[{"name":"postId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"Post queued for immediate publishing"}}}},"/api/v1/automations":{"get":{"tags":["Automations"],"summary":"List automation rules","operationId":"listAutomations","responses":{"200":{"description":"List of automation rules"}}},"post":{"tags":["Automations"],"summary":"Create an automation rule","operationId":"createAutomation","description":"Create a rule that triggers an action (e.g., send DM) when someone comments on your posts. Perfect for comment-to-DM lead magnet funnels.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","actionTemplate"],"properties":{"accountId":{"type":"string"},"triggerType":{"type":"string","enum":["keyword_comment","any_comment","mention"],"default":"keyword_comment"},"triggerKeyword":{"type":"string","description":"Comma-separated keywords to match"},"actionType":{"type":"string","enum":["send_dm"],"default":"send_dm"},"actionTemplate":{"type":"string","description":"DM template. Use {{username}} and {{comment}} placeholders."},"postId":{"type":"string","description":"Monitor a specific post (optional)"},"postUrl":{"type":"string"}}},"example":{"accountId":"clxyz123","triggerType":"keyword_comment","triggerKeyword":"link,send,interested","actionTemplate":"Hey {{username}}! Here's the link you asked for: https://example.com"}}}},"responses":{"201":{"description":"Automation created"}}}},"/api/v1/automations/{automationId}":{"get":{"tags":["Automations"],"summary":"Get automation rule details","operationId":"getAutomation","parameters":[{"name":"automationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Automation details with recent logs"}}},"put":{"tags":["Automations"],"summary":"Update automation rule","operationId":"updateAutomation","parameters":[{"name":"automationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"}}},"delete":{"tags":["Automations"],"summary":"Delete automation rule","operationId":"deleteAutomation","parameters":[{"name":"automationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"}}}},"/api/v1/automations/{automationId}/logs":{"get":{"tags":["Automations"],"summary":"List automation execution logs","operationId":"listAutomationLogs","parameters":[{"name":"automationId","in":"path","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer"}},{"name":"limit","in":"query","schema":{"type":"integer"}},{"name":"status","in":"query","schema":{"type":"string","enum":["triggered","dm_sent","dm_failed","skipped"]}}],"responses":{"200":{"description":"Paginated logs"}}}},"/api/v1/comments/recent":{"get":{"tags":["Comments"],"summary":"Get recent comments/mentions for an account","operationId":"getRecentComments","description":"Fetches recent mentions from X API (live, not cached). Supports `sinceDate` for windowed fetching (maps to X API `start_time`, max 7 days back). Rate limit: 60 req/min.","parameters":[{"name":"accountId","in":"query","required":true,"schema":{"type":"string"}},{"name":"sinceDate","in":"query","schema":{"type":"string","format":"date-time","description":"ISO 8601 date. Only return mentions after this time (max 7 days back)."}},{"name":"paginationToken","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":100}}],"responses":{"200":{"description":"Comments with pagination"}}}},"/api/v1/comments/{postId}":{"get":{"tags":["Comments"],"summary":"Get comments on a specific post","operationId":"getPostComments","parameters":[{"name":"postId","in":"path","required":true,"schema":{"type":"string"}},{"name":"accountId","in":"query","required":true,"schema":{"type":"string"}},{"name":"paginationToken","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Comments on the post"}}},"post":{"tags":["Comments"],"summary":"Reply to a post (create a reply tweet)","operationId":"replyToPost","parameters":[{"name":"postId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","text"],"properties":{"accountId":{"type":"string"},"text":{"type":"string","maxLength":280}}}}}},"responses":{"201":{"description":"Reply created"}}}},"/api/v1/comments/inbox":{"get":{"tags":["Comments"],"summary":"List detected comments and mentions (cached)","operationId":"listCommentInbox","parameters":[{"name":"accountId","in":"query","schema":{"type":"string"}},{"name":"automationId","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Paginated comment inbox"}}}},"/api/v1/media":{"get":{"tags":["Media"],"summary":"List uploaded media","operationId":"listMedia","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pending","ready","expired"]}},{"name":"page","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Paginated media list"}}}},"/api/v1/media/upload":{"post":{"tags":["Media"],"summary":"Initialize a media upload","operationId":"initMediaUpload","description":"Step 1: Get an upload ID. Step 2: Upload the file to the returned URL. Step 3: Use the media ID in your post.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["filename","contentType"],"properties":{"filename":{"type":"string"},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/gif","image/webp","video/mp4","video/quicktime"]},"sizeBytes":{"type":"integer"}}}}}},"responses":{"201":{"description":"Upload initialized with ID and URL"}}}},"/api/v1/media/{mediaId}":{"get":{"tags":["Media"],"summary":"Check media upload status","operationId":"getMedia","parameters":[{"name":"mediaId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Media status"}}}},"/api/v1/media/{mediaId}/upload":{"post":{"tags":["Media"],"summary":"Complete a media upload","operationId":"completeMediaUpload","parameters":[{"name":"mediaId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"publicUrl":{"type":"string","description":"Hosted URL of the uploaded file"},"sourceUrl":{"type":"string","description":"URL to fetch the file from"}}}}}},"responses":{"200":{"description":"Upload completed"}}}},"/api/v1/analytics/posts":{"get":{"tags":["Analytics"],"summary":"Get post engagement analytics","operationId":"getPostAnalytics","parameters":[{"name":"accountId","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Posts with engagement metrics"}}}},"/api/v1/analytics/accounts/{accountId}":{"get":{"tags":["Analytics"],"summary":"Get account follower growth","operationId":"getAccountAnalytics","parameters":[{"name":"accountId","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","schema":{"type":"integer","default":30}}],"responses":{"200":{"description":"Follower growth data"}}}},"/api/v1/analytics/best-time":{"get":{"tags":["Analytics"],"summary":"Get recommended posting times","operationId":"getBestTimeToPost","parameters":[{"name":"accountId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Best hours and days to post"}}}},"/api/v1/schedules":{"get":{"tags":["Schedules"],"summary":"List schedule slots","operationId":"listSchedules","responses":{"200":{"description":"Schedule slots"}}},"post":{"tags":["Schedules"],"summary":"Create a schedule slot","operationId":"createSchedule","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","name","timezone","slots"],"properties":{"accountId":{"type":"string"},"name":{"type":"string"},"timezone":{"type":"string","example":"America/New_York"},"slots":{"type":"array","items":{"type":"object","properties":{"day":{"type":"integer","minimum":0,"maximum":6,"description":"0=Sun, 6=Sat"},"hour":{"type":"integer","minimum":0,"maximum":23},"minute":{"type":"integer","minimum":0,"maximum":59}}}}}}}}},"responses":{"201":{"description":"Schedule created"}}}},"/api/v1/schedules/{scheduleId}":{"get":{"tags":["Schedules"],"summary":"Get schedule with upcoming slot previews","operationId":"getSchedule","parameters":[{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Schedule with upcoming times"}}},"put":{"tags":["Schedules"],"summary":"Update schedule","operationId":"updateSchedule","parameters":[{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"}}},"delete":{"tags":["Schedules"],"summary":"Delete schedule","operationId":"deleteSchedule","parameters":[{"name":"scheduleId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"}}}},"/api/v1/schedules/next-slot":{"get":{"tags":["Schedules"],"summary":"Get next available posting slot","operationId":"getNextSlot","parameters":[{"name":"accountId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Next slot time with conflict info"}}}},"/api/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhooks","operationId":"listWebhooks","responses":{"200":{"description":"Webhooks"}}},"post":{"tags":["Webhooks"],"summary":"Create webhook","operationId":"createWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","url","events"],"properties":{"name":{"type":"string"},"url":{"type":"string","format":"uri"},"secret":{"type":"string","description":"Used to sign payloads with HMAC-SHA256"},"events":{"type":"array","items":{"type":"string","enum":["dm.received","dm.sent","dm.failed","post.published","post.scheduled","post.failed","post.deleted","comment.received","mention.received","automation.triggered","ai.task.completed","ai.task.failed","credits.low","webhook.test"]}}}}}}},"responses":{"201":{"description":"Webhook created"}}}},"/api/v1/webhooks/{webhookId}":{"get":{"tags":["Webhooks"],"summary":"Get webhook details","operationId":"getWebhook","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Webhook details"}}},"put":{"tags":["Webhooks"],"summary":"Update webhook","operationId":"updateWebhook","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"}}},"delete":{"tags":["Webhooks"],"summary":"Delete webhook","operationId":"deleteWebhook","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted"}}}},"/api/v1/webhooks/{webhookId}/test":{"post":{"tags":["Webhooks"],"summary":"Send a test webhook event","operationId":"testWebhook","description":"Sends a `webhook.test` event to the webhook URL. The payload includes `event: 'webhook.test'` and a `timestamp`.","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Test result with status code and response"}}}},"/api/v1/webhooks/{webhookId}/logs":{"get":{"tags":["Webhooks"],"summary":"List webhook delivery logs","operationId":"listWebhookLogs","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"}},{"name":"success","in":"query","schema":{"type":"boolean"}},{"name":"page","in":"query","schema":{"type":"integer"}},{"name":"limit","in":"query","schema":{"type":"integer"}}],"responses":{"200":{"description":"Delivery logs"}}}},"/api/v1/api-keys":{"get":{"tags":["API Keys"],"summary":"List API keys","operationId":"listApiKeys","responses":{"200":{"description":"API keys (hashed, no raw values)"}}},"post":{"tags":["API Keys"],"summary":"Create API key","operationId":"createApiKey","description":"Returns the raw key ONCE. Store it securely — it cannot be retrieved again.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}}}}}},"responses":{"201":{"description":"Key created (includes raw key)"}}}},"/api/v1/api-keys/{keyId}":{"get":{"tags":["API Keys"],"summary":"Get API key details","operationId":"getApiKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Key details"}}},"patch":{"tags":["API Keys"],"summary":"Update API key name or expiry","operationId":"updateApiKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated"}}},"delete":{"tags":["API Keys"],"summary":"Revoke API key","operationId":"deleteApiKey","parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Revoked"}}}},"/api/v1/usage":{"get":{"tags":["Usage & Billing"],"summary":"Get current plan and usage","operationId":"getUsage","responses":{"200":{"description":"Plan details and current usage"}}}},"/api/v1/usage/history":{"get":{"tags":["Usage & Billing"],"summary":"Get usage over time","operationId":"getUsageHistory","parameters":[{"name":"days","in":"query","schema":{"type":"integer","default":30,"maximum":90}},{"name":"endpoint","in":"query","schema":{"type":"string"}},{"name":"platform","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Daily usage aggregation"}}}}},"tags":[{"name":"Accounts","description":"Manage connected social accounts"},{"name":"DMs","description":"Send direct messages — including cold DMs to new conversations"},{"name":"Inbox","description":"DM inbox — list conversations, read messages"},{"name":"Posts","description":"Create, schedule, and manage social media posts"},{"name":"Automations","description":"Comment-triggered auto-DMs (ManyChat/Hypefury style)"},{"name":"Comments","description":"Comment and mention inbox"},{"name":"Media","description":"Upload and manage media for posts"},{"name":"Analytics","description":"Post engagement and follower growth analytics"},{"name":"Schedules","description":"Time slot scheduling for auto-posting"},{"name":"Webhooks","description":"Real-time event notifications. Events: dm.received, dm.sent, dm.failed, post.*, comment.received, mention.received, automation.triggered, ai.task.*, credits.low, webhook.test. Payloads are HMAC-SHA256 signed."},{"name":"API Keys","description":"Manage API authentication keys"},{"name":"Usage & Billing","description":"Plan limits and usage tracking"}]}