{"openapi":"3.0.0","info":{"title":"WAQU Developer API Reference","version":"1.0.0","description":"Public REST API reference for integrating WhatsApp OTP, notifications, media dispatch, and webhooks into your applications.","contact":{"name":"WAQU Developer Support","email":"support@waqu.biz.id","url":"https://waqu.biz.id"}},"servers":[{"url":"https://api.waqu.biz.id","description":"Production Gateway"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT token for dashboard and user authentication"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"API key for programmatic WhatsApp dispatch (`x-api-key: your_api_key`)"}},"schemas":{"StandardSuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"Operation completed successfully"}}},"StandardErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","example":"Detailed error description"}}},"WebhookInboundMessagePayload":{"type":"object","description":"Dispatched to your Webhook URL when a customer sends an incoming WhatsApp message","properties":{"event":{"type":"string","example":"message.received"},"messageId":{"type":"string","example":"wamid.HBgLMjY4..."},"from":{"type":"string","description":"Sender WhatsApp number (E.164)","example":"628123456789"},"fromName":{"type":"string","nullable":true,"example":"Budi Santoso"},"body":{"type":"string","example":"Halo, saya mau konfirmasi pembayaran pesanan #1029"},"hasMedia":{"type":"boolean","example":false},"mediaType":{"type":"string","nullable":true,"example":"image"},"poolId":{"type":"string","example":"pool_clx1820a90001"},"poolNumber":{"type":"string","nullable":true,"example":"628999888777"},"poolName":{"type":"string","nullable":true,"example":"CS Support Pool"},"timestamp":{"type":"string","format":"date-time","example":"2026-11-03T01:30:00.000Z"}}},"WebhookMessageStatusPayload":{"type":"object","description":"Dispatched when an outbound message status transitions (sent, failed)","properties":{"event":{"type":"string","example":"message_status"},"messageId":{"type":"string","example":"msg_clx849200000a1"},"status":{"type":"string","enum":["sent","failed"],"example":"sent"},"to":{"type":"string","example":"628123456789"},"externalId":{"type":"string","nullable":true,"example":"true_628123456789@c.us_3EB0..."},"error":{"type":"string","nullable":true,"example":null},"timestamp":{"type":"string","format":"date-time","example":"2026-11-03T01:30:04.000Z"}}}}},"tags":[{"name":"Messages","description":"Send text, OTP, media attachments, and check message delivery status"},{"name":"Webhooks","description":"Configure callback URLs for incoming messages and delivery reports"},{"name":"API Keys","description":"Manage developer API keys and IP whitelists"},{"name":"WhatsApp Devices","description":"Inspect user WhatsApp device connections and session states"}],"paths":{"/api/v1/send":{"post":{"summary":"Send a WhatsApp message (Text, OTP, or Media)","description":"Dispatch a text message, OTP verification, or media attachment (image, PDF, document, audio, video) via WhatsApp. Also available via alias /api/v1/messages/send.","tags":["Messages"],"security":[{"apiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to","message"],"properties":{"to":{"type":"string","description":"Recipient phone number in international E.164 format (e.g. 628123456789)","example":"628123456789"},"message":{"type":"string","description":"Message text or media caption. Field body is also accepted as alias.","example":"Halo, kode verifikasi OTP Anda adalah 849201. Berlaku 5 menit."},"attachment_url":{"type":"string","format":"uri","description":"Optional public direct URL to file/image/document (JPEG, PNG, PDF, MP4, MP3, etc.)","example":"https://example.com/invoice-992.pdf"},"attachment_type":{"type":"string","enum":["image","document","audio","video"],"description":"Type of media attachment","example":"document"},"sender_pool":{"type":"string","description":"Pool ID or auto for automatic load-balanced device selection","default":"auto","example":"auto"}}}}}},"responses":{"202":{"description":"Message accepted and queued for outbound dispatch","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"messageId":{"type":"string","example":"msg_cm830ad820000a1"},"status":{"type":"string","example":"queued"}}}}}},"400":{"description":"Invalid input parameters or phone number format"},"401":{"description":"Missing or invalid API key (x-api-key header)"},"403":{"description":"Quota exceeded or inactive subscription package"},"429":{"description":"Rate limit exceeded (standard 60 req/min)"}}}},"/api/v1/send-bulk":{"post":{"summary":"Send WhatsApp messages to multiple recipients","description":"Queue messages for multiple destination numbers in a single API call (up to 100 recipients). Also available via alias /api/v1/messages/send-bulk.","tags":["Messages"],"security":[{"apiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["recipients","message"],"properties":{"recipients":{"type":"array","items":{"type":"string"},"description":"Array of recipient phone numbers (max 100)","example":["628123456789","628987654321"]},"message":{"type":"string","description":"Message content to broadcast. Field body is also accepted as alias.","example":"Pemberitahuan: Layanan pemeliharaan sistem akan berlangsung malam ini pukul 23:00 WIB."},"sender_pool":{"type":"string","description":"Pool ID or auto for automatic selection","default":"auto"}}}}}},"responses":{"202":{"description":"Bulk messages queued","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"success":{"type":"array","items":{"type":"object","properties":{"to":{"type":"string"},"messageId":{"type":"string"}}}},"failed":{"type":"array","items":{"type":"object","properties":{"to":{"type":"string"},"error":{"type":"string"}}}},"meta":{"type":"object","properties":{"total":{"type":"integer"},"successful":{"type":"integer"},"failed":{"type":"integer"},"remainingQuota":{"type":"integer"}}}}}}}}}},"400":{"description":"Invalid input or no pools available"},"403":{"description":"Quota exceeded"},"429":{"description":"Rate limit exceeded"}}}},"/api/v1/messages":{"get":{"summary":"List sent messages","description":"Retrieve paginated history of sent WhatsApp messages with delivery status. Authenticate via Bearer JWT or x-api-key.","tags":["Messages"],"security":[{"bearerAuth":[]},{"apiKeyAuth":[]}],"parameters":[{"in":"query","name":"page","schema":{"type":"integer","default":1},"description":"Page number"},{"in":"query","name":"limit","schema":{"type":"integer","default":20},"description":"Items per page (max 100)"}],"responses":{"200":{"description":"List of messages","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}}}}}}}},"/api/v1/messages/analytics":{"get":{"summary":"Get message analytics for charts","tags":["Messages"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"period","schema":{"type":"string","enum":["week","month"],"default":"week"},"description":"Time period for analytics"}],"responses":{"200":{"description":"Analytics data including trends, top pools, and peak hours"}}}},"/api/v1/messages/stats":{"get":{"summary":"Get message statistics","tags":["Messages"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Message statistics"}}}},"/api/v1/messages/{id}":{"get":{"summary":"Get message by ID","description":"Check delivery status, timestamps, and error logs of a specific message ID. Authenticate via Bearer JWT or x-api-key.","tags":["Messages"],"security":[{"bearerAuth":[]},{"apiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Message UUID or ID returned when queued"}],"responses":{"200":{"description":"Message details and delivery status"},"404":{"description":"Message not found"}}}},"/api/v1/messages/admin/analytics":{"get":{"summary":"Get admin analytics for all users (admin only)","tags":["Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"period","schema":{"type":"string","enum":["week","month"],"default":"week"}}],"responses":{"200":{"description":"Admin analytics data"}}}},"/api/v1/webhooks":{"post":{"summary":"Set webhook URL","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Webhook URL to receive events"},"secret":{"type":"string","description":"Optional secret for signature verification"}}}}}},"responses":{"200":{"description":"Webhook configured"}}},"get":{"summary":"Get webhook configuration","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Webhook configuration"}}},"delete":{"summary":"Delete webhook","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Webhook deleted"}}}},"/api/v1/webhooks/test":{"post":{"summary":"Test webhook","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Test result"}}}},"/api/v1/webhooks/toggle":{"patch":{"summary":"Toggle webhook active status","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["active"],"properties":{"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Webhook toggled"}}}},"/api/v1/webhooks/incoming":{"post":{"summary":"Set incoming webhook URL","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"secret":{"type":"string"},"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Incoming webhook configured"}}},"delete":{"summary":"Delete incoming webhook","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Incoming webhook deleted"}}}},"/api/v1/webhooks/incoming/toggle":{"patch":{"summary":"Toggle incoming webhook active status","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["active"],"properties":{"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Incoming webhook toggled"}}}},"/api/v1/webhooks/incoming/test":{"post":{"summary":"Test incoming webhook","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Test result"}}}},"/api/v1/api-keys":{"post":{"summary":"Generate a new API key","tags":["API Keys"],"security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","default":"Default"},"origin":{"type":"string","description":"Optional domain binding"}}}}}},"responses":{"201":{"description":"API key created"},"403":{"description":"Maximum keys limit reached"}}},"get":{"summary":"List user's API keys","tags":["API Keys"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of API keys (masked)"}}}},"/api/v1/api-keys/{id}":{"get":{"summary":"Get API key by ID","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"API key details"},"404":{"description":"API key not found"}}},"put":{"summary":"Update API key settings","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"allowedIps":{"type":"array","items":{"type":"string"},"description":"IP whitelist (empty array allows all IPs)"}}}}}},"responses":{"200":{"description":"API key updated"},"404":{"description":"API key not found"}}},"delete":{"summary":"Revoke an API key","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"API key revoked"},"404":{"description":"API key not found"}}}},"/api/v1/my-pools":{"get":{"summary":"List customer's private pools","tags":["My Pools"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of customer's private pools"}}},"post":{"summary":"Create a new private pool","tags":["My Pools"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"region":{"type":"string","default":"ID"}}}}}},"responses":{"201":{"description":"Pool created"}}}},"/api/v1/my-pools/allowance":{"get":{"summary":"Get customer's pool allowance based on active package","tags":["My Pools"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Pool allowance info"}}}},"/api/v1/my-pools/{id}":{"get":{"summary":"Get pool details","tags":["My Pools"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Pool details"}}},"delete":{"summary":"Delete pool","tags":["My Pools"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Pool deleted"}}}},"/api/v1/my-pools/{id}/initialize":{"post":{"summary":"Initialize pool and start WhatsApp connection","tags":["My Pools"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Initialization started"}}}},"/api/v1/my-pools/{id}/qr":{"get":{"summary":"Get QR code for pool","tags":["My Pools"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"QR code image (base64)"}}}},"/api/v1/my-pools/{id}/status":{"get":{"summary":"Get pool status","tags":["My Pools"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Pool status"}}}},"/api/v1/my-pools/{id}/disconnect":{"post":{"summary":"Disconnect pool","tags":["My Pools"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Pool disconnected"}}}}}}