Schedule a message to a list of phone numbers, or to one of your phonebook groups, at a time you choose.
https://telcomw.com/api/v3/campaignsSend a JSON body with the header Content-Type: application/json. Your API key goes in the X-API-Key header.
| Parameter | Sent in | Required | Description |
X-API-Key |
header | YES | Your API key, sent as a header. You can also send it as Authorization: Bearer YOUR_API_KEY. |
Idempotency-Key |
header | NO | A unique value you make for this request (8 to 64 letters, digits, dots, dashes or underscores). If you send the same request again with the same key, for example after a timeout, you get the first answer back and are not charged twice. Keys are kept for 24 hours. |
name |
body | YES | A name for the campaign, up to 150 characters. You see it in the dashboard under Campaigns. |
message |
body | YES | The text of the message. |
sender_id |
body | YES | The sender ID the message shows as, for example WGIT. It must be approved on your account, see Sender IDs. |
scheduled_at |
body | YES | When the campaign runs: a date and time with its time zone, like 2026-11-20T09:00:00+02:00. At least one minute from now and not more than a year ahead. |
to |
body | NO | The phone numbers, as a list of text. Send this or group_id. |
group_id |
body | NO | The number of one of your phonebook groups: the campaign goes to every number of the group when you create it. Send this or to. |
skip_invalid |
body | NO | true to leave out the phone numbers that are not valid and send to the rest. By default one invalid number rejects the whole request, and nothing is sent or charged. |
notify_before |
body | NO | true (the default) to get an email a few minutes before the campaign runs, with its cost and whether your balance covers it. |
curl --location --request POST 'https://telcomw.com/api/v3/campaigns' \
--header 'X-API-Key: YOUR_API_KEY' \
--header 'Idempotency-Key: campaign-nov-sale-001' \
--header 'Content-Type: application/json' \
--data '{
"name": "November sale",
"message": "Our sale starts today. Visit us!",
"sender_id": "WGIT",
"to": [
"0999123456",
"0888123456"
],
"scheduled_at": "2026-11-20T09:00:00+02:00"
}'
curl --location --request POST "https://telcomw.com/api/v3/campaigns" ^
--header "X-API-Key: YOUR_API_KEY" ^
--header "Idempotency-Key: campaign-nov-sale-001" ^
--header "Content-Type: application/json" ^
--data "{\"name\":\"November sale\",\"message\":\"Our sale starts today. Visit us!\",\"sender_id\":\"WGIT\",\"to\":[\"0999123456\",\"0888123456\"],\"scheduled_at\":\"2026-11-20T09:00:00+02:00\"}"
<?php
$headers = [
'X-API-Key: YOUR_API_KEY',
'Idempotency-Key: campaign-nov-sale-001',
'Content-Type: application/json',
];
$data = [
'name' => 'November sale',
'message' => 'Our sale starts today. Visit us!',
'sender_id' => 'WGIT',
'to' => [
'0999123456',
'0888123456'
],
'scheduled_at' => '2026-11-20T09:00:00+02:00'
];
$ch = curl_init('https://telcomw.com/api/v3/campaigns');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
print_r(json_decode($response, true));
const axios = require('axios');
axios.request({
method: 'post',
url: 'https://telcomw.com/api/v3/campaigns',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Idempotency-Key': 'campaign-nov-sale-001',
'Content-Type': 'application/json'
},
data: {
"name": "November sale",
"message": "Our sale starts today. Visit us!",
"sender_id": "WGIT",
"to": [
"0999123456",
"0888123456"
],
"scheduled_at": "2026-11-20T09:00:00+02:00"
}
}).then((res) => console.log(res.data))
.catch((err) => console.error(err.response ? err.response.data : err.message));
import requests
headers = {
'X-API-Key': 'YOUR_API_KEY',
'Idempotency-Key': 'campaign-nov-sale-001',
'Content-Type': 'application/json'
}
payload = {
'name': 'November sale',
'message': 'Our sale starts today. Visit us!',
'sender_id': 'WGIT',
'to': [
'0999123456',
'0888123456'
],
'scheduled_at': '2026-11-20T09:00:00+02:00'
}
response = requests.request('POST', 'https://telcomw.com/api/v3/campaigns', headers=headers, json=payload)
print(response.json())
The response is JSON.
{
"success": true,
"request_id": "req_5f2c9a1d0e7b4a63",
"data": {
"campaign_id": 42,
"name": "November sale",
"sender_id": "WGIT",
"message": "Our sale starts today. Visit us!",
"status": "scheduled",
"scheduled_at": "2026-11-20T07:00:00.000Z",
"recipients_source": "numbers",
"group_id": null,
"recipients": 2,
"queued": 0,
"failed": 0,
"cost": 0,
"currency": "MWK",
"notify_before": true,
"batch_ids": [],
"error": null,
"started_at": null,
"completed_at": null,
"created_at": "2026-11-05T09:12:44.000Z",
"estimate": {
"pages": 2,
"cost": 40,
"balance": 4250.5,
"enough": true,
"currency": "MWK"
}
}
}
{
"success": false,
"request_id": "req_5f2c9a1d0e7b4a63",
"error": {
"code": "INVALID_SCHEDULE",
"message": "Choose a time at least one minute from now",
"details": {
"field": "scheduled_at"
}
}
}
| Field | Description |
success | true when the request worked. |
request_id | The number of this request. Quote it if you contact us. |
data.campaign_id | The id of the campaign. Use it in the other campaign calls. |
data.status | scheduled, running, completed, failed or cancelled. |
data.scheduled_at | When the campaign runs (UTC). |
data.recipients_source | numbers (a list you sent) or group (a phonebook group). |
data.recipients | How many numbers the campaign has. |
data.queued | After it ran: how many messages were queued for delivery. |
data.failed | After it ran: how many could not be queued. |
data.cost | After it ran: what it cost, in MWK. 0 before. |
data.error | Why a failed campaign failed, otherwise null. |
data.estimate | What the campaign would cost today: pages, cost, your balance, and enough (false when your balance would not cover it; short_by says how much is missing). |
data.rejected | With skip_invalid: how many invalid numbers (invalid_count) and repeated numbers (duplicates) were left out. |