Developer docs

IotaBot WhatsApp API

Send and receive WhatsApp messages from your code — on every number you connected.

Get an API key

Send WhatsApp marketing messages via API

Offers and announcements go through Meta's Marketing Messages API — the route built for marketing.

  • Use an approved MARKETING template — category in the template list tells you which.
  • Meta optimises delivery for marketing on this route. IotaBot campaigns send the same way.
  • Not onboarded yet? It still sends — Meta falls back to the Cloud API. marketing_messages on GET /channels shows the status.
  • Order updates and one-time codes are not marketing: send those with POST /messages.
GET/v1/whatsapp/templatesmessages:sendThe API key needs the messages:send permission. Without it the call is refused with 403 insufficient_scope.Sign in to try

Find your marketing templates

The ones with category: "MARKETING".

Request
curl -X GET "https://api.iotabot.com/v1/whatsapp/templates" \
  -H "Authorization: Bearer $IOTABOT_API_KEY"
Response · 200
{
  "data": {
    "items": [
      {
        "name": "order_update",
        "language": "en_US",
        "category": "UTILITY",
        "whatsapp_account_id": "6a4c01aa…",
        "inputs": {
          "body": [
            "order number",
            "delivery date"
          ]
        }
      },
      {
        "name": "festive_offer",
        "language": "en_US",
        "category": "MARKETING",
        "whatsapp_account_id": "6a4c01aa…",
        "inputs": {
          "body": [
            "customer name"
          ]
        }
      }
    ]
  }
}
POST/v1/whatsapp/marketing-messagesmessages:sendThe API key needs the messages:send permission. Without it the call is refused with 403 insufficient_scope.Sign in to try

Send an offer

Request
curl -X POST "https://api.iotabot.com/v1/whatsapp/marketing-messages" \
  -H "Authorization: Bearer $IOTABOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "+919812345678",
  "template": {
    "name": "festive_offer",
    "language": "en_US",
    "parameters": [
      "Priya"
    ]
  }
}'
Response · 202
{
  "data": {
    "id": "6a4ba0f1c3f1a2b3c4d5e735",
    "object": "message",
    "status": "queued",
    "channel": "whatsapp",
    "via": "marketing_messages",
    "conversation_id": "6a4b9e21c3f1a2b3c4d5e6f7",
    "created_at": "2026-10-01T09:16:10.004Z"
  }
}
Errors
template_not_marketingtemplate_not_approvedrecipient_opted_outinvalid_phonewhatsapp_account_requiredno_whatsapp_accountintegration_pausedapi_quota_exceededidempotency_key_reusedidempotency_in_progress
POST/v1/whatsapp/marketing-messagesmessages:sendThe API key needs the messages:send permission. Without it the call is refused with 403 insufficient_scope.Sign in to try

Header image, coupon and button link

Request
curl -X POST "https://api.iotabot.com/v1/whatsapp/marketing-messages" \
  -H "Authorization: Bearer $IOTABOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "to": "+919812345678",
  "template": {
    "name": "festive_offer",
    "language": "en_US",
    "parameters": [
      "Priya"
    ],
    "values": {
      "headerMediaUrl": "https://cdn.acme.com/diwali.jpg",
      "couponCode": "DIWALI20",
      "urlSuffix": {
        "0": "diwali?ref=wa"
      }
    }
  }
}'
Response · 202
{
  "data": {
    "id": "6a4ba0f1c3f1a2b3c4d5e735",
    "object": "message",
    "status": "queued",
    "channel": "whatsapp",
    "via": "marketing_messages",
    "conversation_id": "6a4b9e21c3f1a2b3c4d5e6f7",
    "created_at": "2026-10-01T09:16:10.004Z"
  }
}
Errors
template_not_marketingtemplate_not_approvedrecipient_opted_outinvalid_phonewhatsapp_account_requiredno_whatsapp_accountintegration_pausedapi_quota_exceededidempotency_key_reusedidempotency_in_progress
Meta limits how many marketing messages one person receives. A message held back by that limit fails with the reason on message.status — try that person again another day.

Templates go any time. Free text and media go only while the customer's 24-hour window is open — and inside it they are free. Check whose window is open before a campaign, and reach them with a plain message instead of a paid template.

GET/v1/messaging-windowconversations:readThe API key needs the conversations:read permission. Without it the call is refused with 403 insufficient_scope.Sign in to try

Who you can message now

Open WhatsApp windows, closing soonest first.

Parameters
channelQuery — whatsapp or instagram — both when left out
closes_within_minutesQuery — 1–1440: only windows closing within this many minutes
limitQuery — 1–100, default 25
starting_afterQuery — the next_cursor of the previous page
Request
curl -X GET "https://api.iotabot.com/v1/messaging-window?channel=whatsapp" \
  -H "Authorization: Bearer $IOTABOT_API_KEY"
Response · 200
{
  "data": {
    "checked_at": "2026-10-02T09:00:58.000Z",
    "items": [
      {
        "conversation_id": "6a4b9e21c3f1a2b3c4d5e6f8",
        "channel": "instagram",
        "thread": "dm",
        "account_id": "6a4c02bb…",
        "contact": {
          "name": "priya.styles",
          "phone": null,
          "email": null,
          "external_id": "17841400000000001"
        },
        "window_closes_at": "2026-10-02T14:05:00.000Z",
        "seconds_left": 18342,
        "last_customer_message_at": "2026-10-01T14:05:00.000Z",
        "can_send": true,
        "reason": null
      }
    ],
    "has_more": false,
    "next_cursor": null
  }
}
Errors
invalid_channelinvalid_limitinvalid_cursor
POST/v1/messaging-window/checkconversations:readThe API key needs the conversations:read permission. Without it the call is refused with 403 insufficient_scope.Sign in to try

Check a list of numbers

can_send for free text, template_allowed for templates, seconds_left until the window shuts.

Request
curl -X POST "https://api.iotabot.com/v1/messaging-window/check" \
  -H "Authorization: Bearer $IOTABOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "phone": "+919812345678"
    },
    {
      "phone": "+919900112233"
    },
    {
      "conversation_id": "6a4b9e21c3f1a2b3c4d5e6f7"
    }
  ]
}'
Response · 200
{
  "data": {
    "checked_at": "2026-10-02T09:00:58.000Z",
    "items": [
      {
        "input": {
          "instagram_username": "priya.styles"
        },
        "conversation_id": "6a4b9e21c3f1a2b3c4d5e6f8",
        "channel": "instagram",
        "thread": "dm",
        "account_id": "6a4c02bb…",
        "contact": {
          "name": "priya.styles",
          "phone": null,
          "email": null,
          "external_id": "17841400000000001"
        },
        "window_closes_at": "2026-10-02T14:05:00.000Z",
        "seconds_left": 18342,
        "last_customer_message_at": "2026-10-01T14:05:00.000Z",
        "can_send": true,
        "reason": null
      },
      {
        "input": {
          "phone": "+919812345678"
        },
        "conversation_id": "6a4b9e21c3f1a2b3c4d5e6f7",
        "channel": "whatsapp",
        "account_id": "6a4c01aa…",
        "contact": {
          "name": "Priya Sharma",
          "phone": "+919812345678",
          "email": null,
          "external_id": "919812345678"
        },
        "window_closes_at": null,
        "seconds_left": 0,
        "last_customer_message_at": "2026-09-28T09:15:02.881Z",
        "can_send": false,
        "reason": "window_closed",
        "template_allowed": true
      },
      {
        "input": {
          "instagram_username": "arjun.k"
        },
        "conversation_id": null,
        "channel": "instagram",
        "can_send": false,
        "window_closes_at": null,
        "seconds_left": null,
        "last_customer_message_at": null,
        "reason": "no_conversation"
      }
    ]
  }
}
Errors
invalid_request