{"openapi":"3.0.3","info":{"title":"WAFlow Public API","version":"1.0.0","description":"Send WhatsApp messages, manage templates and contacts, run campaigns, and receive delivery/inbound events via webhooks. Authenticate with an API key created in Settings → API Keys, sent as `X-API-Key: <key>` or `Authorization: Bearer <key>`. Each key carries scopes (e.g. `messages.send`, `templates.write`, `contacts.write`); a call without the required scope returns 403.\n\nWebhook endpoints are managed outside this base path, at `/api/webhook-endpoints`, and accept either a dashboard session or an API key carrying `webhooks.read` / `webhooks.write`. Those two scopes are never granted implicitly — a key must be created with them explicitly. Destination URLs must be https and must not resolve to private, loopback, or link-local addresses."},"servers":[{"url":"/api/v1","description":"Current host"}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"tags":[{"name":"Messages","description":"Send individual WhatsApp messages"},{"name":"Campaigns","description":"Template broadcasts to many recipients"},{"name":"Templates","description":"Create, submit, and manage message templates"},{"name":"Contacts","description":"Manage contacts and contact lists"}],"paths":{"/messages":{"post":{"tags":["Messages"],"summary":"Send a message","description":"Send one message (text, template, media, interactive buttons, or list) to one recipient. Requires scope: `messages.send`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageRequest"},"examples":{"text":{"value":{"to":"+919812345678","type":"text","text":"Hello from WAFlow"}},"template":{"value":{"to":"+919812345678","type":"template","template":{"name":"order_update","language":"en_US","bodyParameters":["Raj","#1234"]}}},"buttons":{"value":{"to":"+919812345678","type":"buttons","interactive":{"body":"Confirm your order?","buttons":[{"id":"yes","title":"Yes"},{"id":"no","title":"No"}]}}}}}}},"responses":{"200":{"description":"Accepted for delivery","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing messages.send scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Provider send failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/send":{"post":{"tags":["Campaigns"],"summary":"Send a template broadcast","description":"Create and start a campaign that sends an approved template to up to 1000 numbers. Requires scope: `campaigns.create`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendCampaignRequest"}}}},"responses":{"201":{"description":"Campaign created/started"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Template not found or not approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/{campaignId}/status":{"get":{"tags":["Campaigns"],"summary":"Get campaign status","description":"Delivery statistics for a campaign. Requires scope: `campaigns.read`.","parameters":[{"name":"campaignId","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Campaign status"},"404":{"description":"Campaign not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates":{"get":{"tags":["Templates"],"summary":"List approved templates","description":"Approved templates available to send. Requires scope: `templates.read`.","responses":{"200":{"description":"Approved templates"}}},"post":{"tags":["Templates"],"summary":"Create & submit a template","description":"Create a template locally and submit it to Meta for approval. Requires scope: `templates.write`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateRequest"},"example":{"name":"order_update","category":"UTILITY","language":"en_US","body":"Hi {{1}}, your order {{2}} shipped."}}}},"responses":{"201":{"description":"Created and submitted"},"400":{"description":"Validation error, WhatsApp not configured, or Meta rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Missing templates.write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates/{id}":{"get":{"tags":["Templates"],"summary":"Get a template","description":"Full template detail incl. approval status. Requires scope: `templates.read`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Template"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Templates"],"summary":"Delete a template","description":"Requires scope: `templates.write`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates/{id}/sync":{"post":{"tags":["Templates"],"summary":"Sync template status from Meta","description":"Refresh the local approval status from Meta. Requires scope: `templates.read`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Synced template"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts":{"get":{"tags":["Contacts"],"summary":"List contacts","description":"Paginated. Requires scope: `contacts.read`.","parameters":[{"name":"search","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"pageSize","in":"query","schema":{"type":"integer","default":50,"maximum":100}}],"responses":{"200":{"description":"Contacts + pagination"}}},"post":{"tags":["Contacts"],"summary":"Create a contact","description":"Requires scope: `contacts.write`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactRequest"}}}},"responses":{"201":{"description":"Created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contacts/{id}":{"get":{"tags":["Contacts"],"summary":"Get a contact","description":"Requires scope: `contacts.read`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Contact"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Contacts"],"summary":"Update a contact","description":"Requires scope: `contacts.write`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactRequest"}}}},"responses":{"200":{"description":"Updated"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Contacts"],"summary":"Delete a contact","description":"Requires scope: `contacts.write`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contact-lists":{"get":{"tags":["Contacts"],"summary":"List contact lists","description":"Requires scope: `contacts.read`.","responses":{"200":{"description":"Lists"}}},"post":{"tags":["Contacts"],"summary":"Create a contact list","description":"Requires scope: `contacts.write`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"Created"}}}},"/contact-lists/{id}":{"get":{"tags":["Contacts"],"summary":"Get a contact list","description":"Requires scope: `contacts.read`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"List"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Contacts"],"summary":"Delete a contact list","description":"Requires scope: `contacts.write`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/contact-lists/{id}/contacts":{"post":{"tags":["Contacts"],"summary":"Add contacts to a list","description":"Requires scope: `contacts.write`.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["contactIds"],"properties":{"contactIds":{"type":"array","items":{"type":"integer"}}}}}}},"responses":{"200":{"description":"Added"},"404":{"description":"List not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"},"BearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Error":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}},"SendMessageRequest":{"type":"object","required":["to","type"],"properties":{"to":{"type":"string","description":"E.164, e.g. +919812345678"},"type":{"type":"string","enum":["text","template","media","buttons","list"]},"text":{"type":"string","description":"For type=text"},"template":{"type":"object","properties":{"name":{"type":"string"},"language":{"type":"string","default":"en_US"},"bodyParameters":{"type":"array","items":{"type":"string"}}}},"media":{"type":"object","properties":{"type":{"type":"string","enum":["image","video","audio","document"]},"url":{"type":"string"},"caption":{"type":"string"},"filename":{"type":"string"}}},"interactive":{"type":"object","properties":{"body":{"type":"string"},"buttons":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"}}}},"header":{"type":"string"},"footer":{"type":"string"}}}}},"SendMessageResponse":{"type":"object","properties":{"success":{"type":"boolean"},"messageId":{"type":"string"},"to":{"type":"string"},"type":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"SendCampaignRequest":{"type":"object","required":["templateName","phoneNumbers","campaignName"],"properties":{"templateName":{"type":"string"},"campaignName":{"type":"string"},"phoneNumbers":{"type":"array","items":{"type":"string"},"maxItems":1000},"variables":{"type":"object","additionalProperties":{"type":"string"}},"sendImmediately":{"type":"boolean","default":true},"scheduledFor":{"type":"string","format":"date-time"}}},"CreateTemplateRequest":{"type":"object","required":["name","body"],"properties":{"name":{"type":"string","description":"lowercase letters, digits, underscores"},"category":{"type":"string","enum":["MARKETING","UTILITY","AUTHENTICATION"],"default":"UTILITY"},"language":{"type":"string","default":"en_US"},"body":{"type":"string","description":"Template body, use {{1}}, {{2}} for variables"}}},"CreateContactRequest":{"type":"object","required":["phoneNumber"],"properties":{"phoneNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"customFields":{"type":"object"},"notes":{"type":"string"}}},"UpdateContactRequest":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"customFields":{"type":"object"},"notes":{"type":"string"},"optedOut":{"type":"boolean"}}}}}}