Send your first message in 5 minutes
Create an API key with the Send WhatsApp messages preset, put it in your environment, and send a WhatsApp message with one request, in curl, Node.js, Python or PHP.
This guide takes you from no API key to a WhatsApp message on your own phone. You need about five minutes and a terminal.
Before you start
- A connected WhatsApp number. The API sends from your organisation's own numbers. See Numbers and accounts.
- An approved message template. A customer who has never written to your number can only receive a template. Your own phone counts as a new customer. See Message templates.
- An Owner or Admin account. A key can never do more than the person who creates it. The Developer role can't send messages, so it can't create a key that sends.
- A plan that includes the public API. See Plans and trial.
1. Create a key
- Go to Settings › Developers › API keys and click New API key.
- In Name, enter the name of the system that will use the key, for example "Order sync".
- Under What will this key do?, keep Send WhatsApp messages selected. It is marked Recommended and lists what the key will be able to do: send messages, check whether they were delivered, add a contact when you message a new number, and see your numbers and templates.
- Click Create key. If IconEngage asks you to confirm your identity, enter your two-factor code or your password.
- Copy the key and store it somewhere safe. This is the only time it is shown.
Tip: The screen that shows your key also has Send your first message: the same examples as below, already filled in with your number and one of your approved templates. You can copy from there instead.
2. Put the key in your environment
The examples read the key from the ICONENGAGE_API_KEY environment variable, so it never ends up in your code. In the terminal you will use:
export ICONENGAGE_API_KEY="paste-your-key-here"On Windows PowerShell, use $env:ICONENGAGE_API_KEY = "paste-your-key-here" instead.
3. Send a template message
Replace the example values with yours:
to: your own phone number in international format, starting with+and the country code, in place of+91XXXXXXXXXX. Spaces and dashes are fine. A number without the+is refused. The placeholder is refused as it stands, so an example you forget to edit sends nothing.template: the name and language of one of your approved templates, and one value invariablesfor each variable in its body, in order. Leavevariablesout if the template has none. To skip the guesswork,GET /templates/{template_id}returnsexample, a ready-to-send body: copy it and changeto. See Start from the template's example.
If your organisation has one WhatsApp number, the message is sent from it. If it has several, add "from". See Choose the sending number.
Every request also sends an Idempotency-Key header. If a request times out, sending it again with the same key can never deliver the message twice. The examples make a new key each time they run, so each run sends a new message.
The curl examples make the key with uuidgen. If your system doesn't have it (Windows, and some minimal Linux images), use $(python3 -c 'import uuid; print(uuid.uuid4())') in its place. In PowerShell, [guid]::NewGuid() makes one.
curl
curl -X POST https://iconengage.com/api/public/v1/messages \
-H "Authorization: Bearer $ICONENGAGE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"to": "+91XXXXXXXXXX",
"type": "template",
"template": {
"name": "order_update",
"language": "en",
"variables": ["Asha", "#1042"]
}
}'Node.js
Node.js 18 or later. Save this as send.mjs and run node send.mjs:
const response = await fetch("https://iconengage.com/api/public/v1/messages", {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.ICONENGAGE_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
to: '+91XXXXXXXXXX',
type: 'template',
template: { name: 'order_update', language: 'en', variables: ['Asha', '#1042'] },
}),
})
console.log(response.status, await response.json())Python
Python 3 with the requests package (pip install requests):
import os
import uuid
import requests
response = requests.post(
"https://iconengage.com/api/public/v1/messages",
headers={
"Authorization": f"Bearer {os.environ['ICONENGAGE_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"to": "+91XXXXXXXXXX",
"type": "template",
"template": {"name": "order_update", "language": "en", "variables": ["Asha", "#1042"]},
},
)
print(response.status_code, response.json())PHP
PHP 7.4 or later with the curl extension. Run php send.php:
<?php
$body = [
'to' => '+91XXXXXXXXXX',
'type' => 'template',
'template' => ['name' => 'order_update', 'language' => 'en', 'variables' => ['Asha', '#1042']],
];
$ch = curl_init('https://iconengage.com/api/public/v1/messages');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('ICONENGAGE_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => json_encode($body),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), ' ', $response, PHP_EOL;4. Check the answer
A message IconEngage has accepted gets 202 and the stored message:
{
"id": "6f1c2e8a-…",
"type": "template",
"status": "accepted",
"template_name": "order_update",
"wamid": null
}accepted means IconEngage will send it. It has not reached WhatsApp yet. To follow it, ask for the message by its id. Its status moves from accepted to sent, delivered and read, or to failed with a reason:
curl https://iconengage.com/api/public/v1/messages/6f1c2e8a-… \
-H "Authorization: Bearer $ICONENGAGE_API_KEY"If it doesn't work
Every refusal has a code, and for the common ones a fix that says what to change and a docs_url that links to the explanation. The ones you are most likely to meet on a first send:
| Status | code | What to do |
|---|---|---|
401 | unauthenticated | The key is missing, mistyped or revoked. Check that ICONENGAGE_API_KEY is set in the terminal you ran from. See unauthenticated. |
403 | permission_denied | The key lacks a permission. Create one with the Send WhatsApp messages preset. See permission_denied. |
400 | validation_failed with details.reason: to_needs_country_code | to has no + and country code. Write it as +91 XXXXX XXXXX, not XXXXX XXXXX. See to_needs_country_code. |
400 | validation_failed with details.reason: from_required | Your organisation has more than one number. Add "from" with one of details.numbers. See from_required. |
409 | template_required | You sent text to someone who has never written to this number. Send a template. See template_required. |
409 | template_not_approved | The template name, language or number of variables doesn't match an approved template. See template_not_approved. |
409 | conflict with details.reason: no_connected_phone_number | No number can send yet. See no_connected_phone_number. |
If the answer was 202 but the message never arrives, see Messages not delivered.
Send text instead
WhatsApp only delivers text and other free-form messages within 24 hours of the customer's last message to you. To try one, first send any message from your phone to your WhatsApp Business number. Then, within 24 hours:
curl -X POST https://iconengage.com/api/public/v1/messages \
-H "Authorization: Bearer $ICONENGAGE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{ "to": "+91XXXXXXXXXX", "type": "text", "text": { "body": "Hello from the API!" } }'See The 24-hour window and templates.
Next steps
- Send a message with the API: every message type, media, and choosing the sending number.
- Event webhooks: find out about delivery and replies without asking.
- Rate limits and errors: every error and how to fix it.
- Create and manage API keys: presets, revoking and replacing keys.
Still need help?
Write to us at [email protected] and tell us what you were trying to do. Already a customer? Sign in to IconEngage — the same articles are under Help in the app.