Send messages: Skipping-inbox

Use the Aircall Public API to send WhatsApp text, template, and media messages 

Overview

Skipping-inbox mode sends WhatsApp messages straight to the customer without an agent inbox. Your messages stay outside Aircall Workspace, so your integration owns the conversation end to end.

Aircall sends inbound replies and delivery-status updates to the callbackUrl you configure on the line. Use this mode for automated, high-volume, or non-conversational messaging, such as order updates, alerts, and reminders.

When a human agent needs to see and continue the thread, use agent conversation mode instead.

Sequence diagram of the messaging flow. Your app sends a message to Aircall, which delivers it to the customer. Aircall sends a message.status_updated webhook to your app after delivery. When the customer replies, Aircall sends a message.received webhook to your app.

Prerequisites

  • A registered WhatsApp-capable number — See the WhatsApp overview for registration.
  • A valid OAuth access token — See OAuth page to learn how to get one.
  • A publicly reachable HTTPS callbackUrl to receive replies and delivery-status updates.

Configure the line

Skipping-inbox mode requires a one-time line configuration. Configure the line with type: "whatsapp".

import 'dotenv/config';

const LINE_ID = 123; //Your Aircall number with active WhatsApp Addon

const configureLine = async () => {
  const res = await fetch(
    `https://api.aircall.io/v1/numbers/${LINE_ID}/messages/configuration`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.AIRCALL_ACCESS_TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        callbackUrl: 'https://your-app.example.com/aircall/whatsapp',
        type: 'whatsapp'
      })
    }
  );

  if (!res.ok) throw new Error(`Failed to configure line: ${res.status}`);

  const { token } = await res.json();
  // Store the token against your line record. It identifies the Aircall
  // account on incoming callbacks
  return token
}

The response returns a token and confirms the line as WhatsApp Public API. Once configured, the line no longer sends or receives WhatsApp through the Aircall workspace — all traffic flows through the API and your callbackUrl.

Send a template message

Templates are pre-approved message formats. Use one to start a conversation or to reach a customer outside the 24-hour window.

Get the templates

First, list the line's approved templates to find the template you need to send.

const LINE_ID = 123; //Your Aircall number with active WhatsApp Addon

const listApprovedTemplates = async () => {
  const res = await fetch(
    `https://api.aircall.io/v1/numbers/${LINE_ID}/templates?status=APPROVED`,
    { headers: { 'Authorization': `Bearer ${process.env.AIRCALL_ACCESS_TOKEN}` } }
  );

  if (!res.ok) throw new Error(`Failed to list templates: ${res.status}`);

  const { templates } = await res.json();
  return templates
}

Send the template

Send the template by passing templateParams instead of text. The body array fills the template's variables, matching each placeholder key to a value.

const sendWhatsAppTemplate = async () => {
  const res = await fetch('https://api.aircall.io/v1/messages/whatsapp/send', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.AIRCALL_ACCESS_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      lineId: 123,
      to: '+14155552671',
      templateParams: {
        id: '1234',
        body: [
          { key: '{{1}}', value: 'Jordan' },
          { key: '{{2}}', value: '2026-06-18' }
        ]
      }
    })
  });

  if (!res.ok) throw new Error(`Send failed: ${res.status}`);
  return res.json()
}
📘

Each key in body must match a variable configured for that template in Aircall. You define those variables under the number's Integration page, specifically, in the WhatsApp in Aircall section; they correspond to the template's placeholders ({{1}}, {{2}}, ...). Set each key to the same variable so its value lands in the right placeholder.

Send a text message

Free-form text is allowed while the 24-hour customer service window is open — that is, within 24 hours of the customer's last inbound message. The two modes use different endpoints and name the recipient differently: agent conversation uses externalNumber, skipping-inbox uses to. Both carry lineId in the request body.

const sendWhatsAppMessage = async () => {
  const res = await fetch('https://api.aircall.io/v1/messages/whatsapp/send', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.AIRCALL_ACCESS_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      lineId: 123,
      to: '+14155552671',
      text: 'Thanks for reaching out — an agent will follow up shortly.'
    })
  });

  if (!res.ok) throw new Error(`Send failed: ${res.status}`);
  return res.json()
}
🚧

Outside the window, free-form is rejected. When more than 24 hours have passed since the customer's last reply, a text or media send fails. Send an approved template instead, or queue the message until the customer messages again.

Send media

Media sends are supported only on the skipping-inbox mode. Pass a single publicly reachable mediaUrl.

const sendMedia = async () => {
  const res = await fetch('https://api.aircall.io/v1/messages/whatsapp/send', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.AIRCALL_ACCESS_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      lineId: 123,
      to: '+14155552671',
      mediaUrl: 'https://your-app.example.com/receipts/4821.pdf'
    })
  });

  if (!res.ok) throw new Error(`Send failed: ${res.status}`);
  return res.json()
};
⚠️

Host the file where Aircall can fetch it. mediaUrl must resolve to a publicly accessible file over HTTPS. Aircall retrieves it at send time. URLs behind authentication or on a private network are not accessible to Aircall, so the message cannot include the media.

Response codes

These codes apply to all messaging endpoints.

Status codeWhat it means
200Request accepted.
403Line is not configured or WhatsApp add-on is inactive.
404The template is not found. Re-list the line's templates and confirm the id is still APPROVED.
429Rate limit exceeded

See the full list of response codes here.


Did this page help you?