Every request needs your API key as a Bearer token. Create one in the app under Developer Tools › Access Tokens. Keep it secret: anyone with the key can send messages from your number.
Authorization: Bearer your-api-key
401 means the key is missing or wrong. 403 means your subscription has ended or you hit a plan limit, such as contacts.
Verify
get/api/verifyVerify API key
# Confirms the Bearer token is valid and the organization subscription is active before calling other endpoints.
# HTTP 200: token OK. 401: missing/invalid token. 403: subscription inactive.
curl -X GET
https://swiftcampaigns.com/api/verify
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
Contacts
get/api/contactsGet contact list
# Optional query: ?page=1&per_page=10 (per_page max 100).
curl -X GET
https://swiftcampaigns.com/api/contacts?page=1&per_page=10
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
post/api/contactsAdd contact
# JSON body fields:
# phone (required) — international number; validated and stored as E.164. Must be unique per organization (400 if duplicate).
# first_name, last_name, email (optional) — omit, null, or "" for contacts without names.
# street, city, state, zip, country (optional) — stored in address JSON.
# metadata (optional) — arbitrary JSON-serializable value.
# group (optional) — array of contact-group UUID strings.
# Responses: 200 success { statusCode, id, message }; 400 validation; 403 subscription inactive or contact limit reached.
curl -X POST 'https://swiftcampaigns.com/api/contacts' \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{"phone":"+15551234567","first_name":"Jane","last_name":"Doe","email":"[email protected]"}'
put/api/contacts/{uuid}Edit contact
# Same JSON fields as Add contact. Path {uuid} is the contact id returned when created.
# phone is required on every update; if you change it, the new number must not belong to another contact (400 duplicate).
# Updating with the same phone as this contact is allowed.
curl -X PUT 'https://swiftcampaigns.com/api/contacts/your-uuid-here' \
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{"phone":"+15551234567","first_name":"Jane","last_name":"Smith","email":"[email protected]"}'
# Get one saved reply
curl -X GET
https://swiftcampaigns.com/api/canned-replies/your-uuid-here
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
WhatsApp lines
get/api/whatsapp-connectionsList connections
# Returns each line\'s uuid (use as whatsapp_connection on /api/send). No internal database ids.
curl -X GET
https://swiftcampaigns.com/api/whatsapp-connections
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
Messages
post/api/sendSend message
# Same endpoint for WhatsApp Cloud API and WhatsApp QR connect. Optional: whatsapp_connection (UUID from GET /api/whatsapp-connections). Omit to use the organization default line. Interactive header/footer/buttons apply to Cloud only; WhatsApp QR connect sends plain text.
curl -X POST
https://swiftcampaigns.com/api/send
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Content-Type: application/json'
-d '{
"phone": "+1 (968) 082-5846",
"message": "Hello John, how are you?",
"whatsapp_connection": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"header": "Test header",
"footer": "Test footer",
"buttons": [
{
"id": "id_1",
"title": "Fine"
},
{
"id": "id_2",
"title": "Not well"
}
]
}'
post/api/send/mediaSend media
# Optional whatsapp_connection (UUID) selects the WhatsApp Cloud or WhatsApp QR connect instance.
curl -X POST
https://swiftcampaigns.com/api/send/media
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Content-Type: application/json'
-d '{
"phone": "+1 (968) 082-5846",
"whatsapp_connection": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"media_type": "image",
"media_url": "https://images.pexels.com/photos/276267/pexels-photo-276267.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
"caption": "your caption for image or video media types",
"file_name": "testFileName"
}'
post/api/campaignsCreate campaign (WhatsApp QR connect)
# Use when whatsapp_connection points to a WhatsApp QR connect line from GET /api/whatsapp-connections.
#
# Required: name, whatsapp_connection (UUID), contacts ("all" or a contact-group UUID).
# Schedule: send_immediately true, OR scheduled_at (ISO 8601, UTC) with send_immediately false.
# Content: whatsapp_qr_connect_message (plain text) and/or whatsapp_qr_connect_media_url + whatsapp_qr_connect_media_kind (image|video|document).
curl -X POST
https://swiftcampaigns.com/api/campaigns
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Content-Type: application/json'
-d '{
"name": "API campaign",
"whatsapp_connection": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"contacts": "all",
"send_immediately": true,
"whatsapp_qr_connect_message": "Hello from the API"
}'
post/api/campaignsCreate campaign (WABA template with variables)
# Use when whatsapp_connection is a WhatsApp Cloud (WABA) line from GET /api/whatsapp-connections.
#
# PREREQUISITES
# - template: UUID of a row from GET /api/templates (organization-scoped), NOT the public template name string.
# - Match variable counts to your approved template: open the template metadata in the UI or Meta — BODY uses {{1}}, {{2}}, … in order.
# - You must supply one body parameter for each BODY placeholder, in the same order. Too few or too many will fail at WhatsApp (e.g. error 132000).
#
# FIELD NOTES
# - header: REQUIRED object. For templates with no header variables use: { "format": "TEXT", "parameters": [] }.
# - body: use body.parameters[] for variables. API format (recommended): { "type": "text", "value": "literal for {{1}}" } per slot.
# Alternative (dashboard-style): { "selection": "static", "value": "..." } or { "selection": "dynamic", "value": "first name" } (maps contact fields).
# - footer / buttons: optional; use [] or {} if unused. Templates with URL/quick-reply variables need buttons[] shaped like the web campaign form.
# - Media header (IMAGE|VIDEO|DOCUMENT): header.parameters[] with type (IMAGE|VIDEO|DOCUMENT), "selection": "link", "value": "https://..." (public URL; API cannot upload files).
#
# RESPONSE: 200 { "statusCode": 200, "uuid": "...", "message": "..." }. Poll GET /api/campaigns/{uuid}/logs for per-recipient status.
curl -X POST
https://swiftcampaigns.com/api/campaigns
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Content-Type: application/json'
-d '{
"name": "Billing reminder blast",
"whatsapp_connection": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"contacts": "all",
"send_immediately": true,
"template": "281a3383-985c-4084-bcb0-9ec523c952de",
"header": { "format": "TEXT", "parameters": [] },
"body": {
"parameters": [
{ "type": "text", "value": "Jane" },
{ "type": "text", "value": "Ksh 500" },
{ "type": "text", "value": "30 June 2026" }
]
},
"footer": {},
"buttons": []
}'
post/api/templatesCreate a template and submit it to Meta
# Create a template and submit it to Meta (name, category, language, header, body, footer, buttons)
curl -X POST
https://swiftcampaigns.com/api/templates
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
-H 'Content-Type: application/json'
-d '{
"name": "order_shipped",
"category": "UTILITY",
"language": "en",
"body": {"text": "Hi {{1}}, your order {{2}} is on its way.", "example": [["Aarav", "#4417"]]}
}'
get/api/templates/{uuid}Get a template with its Meta status
# Get a template with its Meta status
curl -X GET
https://swiftcampaigns.com/api/templates/your-uuid-here
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
put/api/templates/{uuid}Edit a template and resubmit it to Meta
# Edit a template and resubmit it to Meta
curl -X PUT
https://swiftcampaigns.com/api/templates/your-uuid-here
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
-H 'Content-Type: application/json'
-d '{
"name": "order_shipped",
"category": "UTILITY",
"language": "en",
"body": {"text": "Hi {{1}}, your order {{2}} is on its way.", "example": [["Aarav", "#4417"]]}
}'
delete/api/templates/{uuid}Delete a template from Meta and Swift Campaigns
# Delete a template from Meta and Swift Campaigns
curl -X DELETE
https://swiftcampaigns.com/api/templates/your-uuid-here
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
Flows
get/api/flowsList flows
# List flows
curl -X GET
https://swiftcampaigns.com/api/flows
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
post/api/flowsCreate a flow
# Create a flow (name, description, steps, links). Starts turned off.
curl -X POST
https://swiftcampaigns.com/api/flows
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
-H 'Content-Type: application/json'
-d '{
"name": "Welcome menu",
"description": "Main menu for anyone who says hi",
"steps": [{"id": "start", "type": "start", "fields": {"keywords": ["hi", "menu"]}}],
"links": []
}'
get/api/flows/{uuid}Get a flow with its steps and links
# Get a flow with its steps and links
curl -X GET
https://swiftcampaigns.com/api/flows/your-uuid-here
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
put/api/flows/{uuid}Update a flow
# Update a flow. A live flow that becomes incomplete turns off.
curl -X PUT
https://swiftcampaigns.com/api/flows/your-uuid-here
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
-H 'Content-Type: application/json'
-d '{
"name": "Welcome menu",
"description": "Main menu for anyone who says hi",
"steps": [{"id": "start", "type": "start", "fields": {"keywords": ["hi", "menu"]}}],
"links": []
}'
# Turn a flow on. 422 lists the steps that need fixing.
curl -X POST
https://swiftcampaigns.com/api/flows/your-uuid-here/publish
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
post/api/flows/{uuid}/unpublishTurn a flow off
# Turn a flow off
curl -X POST
https://swiftcampaigns.com/api/flows/your-uuid-here/unpublish
-H 'Authorization: Bearer <YOUR_AUTHORIZATION_TOKEN>'
-H 'Accept: application/json'
Base URL
All endpoints live under one address. Requests and responses are JSON.