Sikio for developers
Automate WhatsApp messages.
Keep the conversation going.
Send WhatsApp notifications from your application. Connect customer data from your existing systems. Keep API messages, incoming enquiries and WhatsApp broadcasts together in Sikio’s conversation inbox.
REST APIs · cURL, JavaScript and Python examples · Workspace API keys
01 · Messaging
WhatsApp API
Send a message when something happens in your system.
Trigger payment confirmations, order updates or appointment reminders from your application, CRM or billing system. Send an approved WhatsApp template with one API request.
- Connect a WhatsApp channel in Sikio and create an API key with
whatsapp:readandwhatsapp:send. - Find your channel ID and an approved template ID. This example uses a fixed-text template with no variables.
- Replace the credentials, IDs and sample number with a consenting test recipient. Give each new message its own
UNIQUE_MESSAGE_KEY; keep it unchanged for retries.
Continue in the inbox. Your API message appears in the customer’s WhatsApp conversation with its integration source. Replies stay in that conversation, ready for your team to answer.
Add variables, supported buttons or optional media when your template needs them. You can also attach a private business reference and message context for your team.
Examples use staging. Choose the matching environment and credentials. Run samples on your server; keep the API secret private.
Send an approved template
curl --fail-with-body \
--user 'YOUR_API_KEY:YOUR_API_SECRET' \
--write-out '\nHTTP %{http_code}\n' \
--request POST \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: UNIQUE_MESSAGE_KEY' \
--data-binary @- \
'https://stage.api.ictlife.com/v1/integrations/whatsapp/channels/CHANNEL_ID/messages' <<'JSON'
{
"recipient": "+254700000001",
"template_id": "YOUR_APPROVED_TEMPLATE_ID"
}
JSONconst credentials = Buffer.from('YOUR_API_KEY:YOUR_API_SECRET').toString('base64');
const response = await fetch("https://stage.api.ictlife.com/v1/integrations/whatsapp/channels/CHANNEL_ID/messages", {
method: 'POST',
headers: {
Authorization: 'Basic ' + credentials,
'Content-Type': 'application/json',
'Idempotency-Key': 'UNIQUE_MESSAGE_KEY',
},
body: JSON.stringify({
"recipient": "+254700000001",
"template_id": "YOUR_APPROVED_TEMPLATE_ID"
}),
});
const text = await response.text();
if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);
console.log(response.status, text ? JSON.parse(text) : null);import base64, json
import urllib.request, urllib.error
credentials = base64.b64encode(b'YOUR_API_KEY:YOUR_API_SECRET').decode()
headers = {'Authorization': 'Basic ' + credentials}
body = json.dumps({
"recipient": "+254700000001",
"template_id": "YOUR_APPROVED_TEMPLATE_ID"
}).encode()
headers['Content-Type'] = 'application/json'
headers['Idempotency-Key'] = 'UNIQUE_MESSAGE_KEY'
request = urllib.request.Request("https://stage.api.ictlife.com/v1/integrations/whatsapp/channels/CHANNEL_ID/messages", method='POST', headers=headers, data=body)
try:
with urllib.request.urlopen(request, timeout=30) as response:
text = response.read().decode()
print(response.status, json.loads(text) if text else None)
except urllib.error.HTTPError as error:
raise SystemExit(f'HTTP {error.code}: {error.read().decode()}')Example response
{
"id": 1042,
"channel_id": 42,
"status": "accepted",
"conversation_id": "CONVERSATION_ID",
"message_id": "MESSAGE_ID",
"provider_message_id": "wamid.EXAMPLE",
"created_at": "2026-10-16T09:00:00Z",
"updated_at": "2026-10-16T09:00:01Z"
}Illustrative values. HTTP 202 is not proof of delivery: inspect status, then check the request and receipts. The conversation and message IDs link the accepted send to the inbox.
02 · Customer data
Contacts API
Bring useful customer context into every conversation.
Your CRM, checkout or payment notifications already know who the customer is. Use the Contacts API to read, create and update the profiles your team uses in Sikio.
For example, when a payment notification reaches your system, upsert the customer’s name and WhatsApp number. The same identity connects that profile to the customer your team speaks with in the inbox, so they have a name and useful background when an enquiry arrives.
- Keep records connected. Upsert by phone, WhatsApp number or email to create or update a matching contact. Conflicting identities are rejected.
- Share the context your team needs. Synchronize names, identities and workspace-defined custom profile fields, such as a customer reference or account type.
- Read changes back. Fetch and search contacts to keep your existing system informed. Your integration decides when to read and write.
Use a key with contacts:write for this request, and replace the sample contact details. acquisition_source records where the contact came from; it is not a payment ledger. Creating a contact does not grant consent to send WhatsApp messages.
Create or update a customer profile
curl --fail-with-body \
--user 'YOUR_API_KEY:YOUR_API_SECRET' \
--write-out '\nHTTP %{http_code}\n' \
--request POST \
--header 'Content-Type: application/json' \
--data-binary @- \
'https://stage.api.ictlife.com/v1/integrations/contacts/upsert' <<'JSON'
{
"display_name": "Amina Customer",
"whatsapp_number": "+254700000001",
"email": "amina@example.com",
"consent_status": "unknown",
"acquisition_source": "payment_notification"
}
JSONconst credentials = Buffer.from('YOUR_API_KEY:YOUR_API_SECRET').toString('base64');
const response = await fetch("https://stage.api.ictlife.com/v1/integrations/contacts/upsert", {
method: 'POST',
headers: {
Authorization: 'Basic ' + credentials,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"display_name": "Amina Customer",
"whatsapp_number": "+254700000001",
"email": "amina@example.com",
"consent_status": "unknown",
"acquisition_source": "payment_notification"
}),
});
const text = await response.text();
if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);
console.log(response.status, text ? JSON.parse(text) : null);import base64, json
import urllib.request, urllib.error
credentials = base64.b64encode(b'YOUR_API_KEY:YOUR_API_SECRET').decode()
headers = {'Authorization': 'Basic ' + credentials}
body = json.dumps({
"display_name": "Amina Customer",
"whatsapp_number": "+254700000001",
"email": "amina@example.com",
"consent_status": "unknown",
"acquisition_source": "payment_notification"
}).encode()
headers['Content-Type'] = 'application/json'
request = urllib.request.Request("https://stage.api.ictlife.com/v1/integrations/contacts/upsert", method='POST', headers=headers, data=body)
try:
with urllib.request.urlopen(request, timeout=30) as response:
text = response.read().decode()
print(response.status, json.loads(text) if text else None)
except urllib.error.HTTPError as error:
raise SystemExit(f'HTTP {error.code}: {error.read().decode()}')Example response
{
"action": "create",
"contact": {
"id": 91,
"display_name": "Amina Customer",
"whatsapp_number": "+254700000001",
"email": "amina@example.com",
"consent_status": "unknown",
"acquisition_source": "payment_notification"
}
}Illustrative values. action is create or update. Keep the returned contact ID for later reads and updates. Contact profiles are separate from the private context attached to an individual API message.
03 · The conversation
One inbox for the whole conversation
Your automated message can be the start of a conversation.
API notifications, WhatsApp broadcasts sent from the dashboard, customer replies and incoming enquiries appear in the customer’s conversation on that WhatsApp channel.
Your team can see which messages came from an API integration or a campaign, read the customer’s replies and continue the conversation from the dashboard. Contact profiles bring the customer’s details alongside that history.
Use the WhatsApp API for automated sends from your systems, the Contacts API for shared customer data, and Sikio’s dashboard for broadcasts and human follow-up.
- WhatsApp APIYour order system
Your order is ready for collection.
- WhatsApp broadcastSent from the dashboard
We’re open until 6 pm this Saturday.
- Customer replyIncoming WhatsApp message
Thanks! Can I collect after 5?
Your team sees the message history and customer profile, then replies from Sikio.
Start with your first WhatsApp API message
Connect a channel, choose an approved template and follow the send into your inbox. Add contact synchronization when your integration needs it.
Follow the WhatsApp quickstart →