POST
/
whatsapp
/
{phoneNumberId}
/
template-message
curl --request POST \
  --url https://api.chatvolt.ai/whatsapp/{phoneNumberId}/template-message \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "to": "55987654321",
  "text": "Hello! Please check our latest offers.",
  "agentId": "abcd123465",
  "templateName": "special_offer",
  "templateLangCode": "en_US"
}'

This endpoint allows you to send WhatsApp template messages with dynamic variables to contacts through your registered WhatsApp Business account.

Prerequisites

  • An active premium subscription
  • A configured WhatsApp Business account integration
  • Agent configured with the WhatsApp channel
  • Template must be pre-approved on WhatsApp Business Manager

Path Parameters

ParameterTypeRequiredDescription
phoneNumberIdstringYesThe WhatsApp Business phone number ID

Request Body

{
  to: string;                  // Recipient's phone number with country code (e.g., "491234567890")
  text: string;                // Message text to store in conversation history
  agentId: string;             // ID of the agent to associate with this message
  templateName: string;        // Name of the pre-approved WhatsApp template
  templateLangCode: string;    // Language code (e.g., "en_US", "es_ES")

  contactName?: string;        // Optional: Contact name for new contacts (defaults to "wao-" + phone number)
  crmScenarioId?: string;      // Optional: ID of the CRM scenario for synchronization
  crmStepId?: string;          // Optional: ID of the CRM step for synchronization
  hasButtonVariables?: boolean; // Optional: Indicates if the template has button variables
  defaultAssigneeId?: string | null; // Optional: Default user ID for conversation assignment
  defaultStatus?: "RESOLVED" | "UNRESOLVED" | "HUMAN_REQUESTED"; // Optional: Set a default status for the conversation
  conversationStatus?: "RESOLVED" | "UNRESOLVED" | "HUMAN_REQUESTED"; // Optional: Override conversation status

  // Media Header (optional)
  header_type?: "image" | "video" | "document" | "text"; // Type of media for the header
  header_text?: string;             // Required if header_type is "text"
  header_link?: string;             // URL for the media file (if not using an ID)
  header_id?: string;               // ID of an uploaded media file
  header_filename?: string;         // Optional: Filename for documents

  // Dynamic template variables (optional)
  var_[variableName]: string;  // Template variables with "var_" prefix
                               // Example: var_customer_name, var_order_id, var_date
}

Sending Media Templates

To send a template with a media header (image, video, or document), provide the header_type and the corresponding media source (header_link or header_id).

  • Using a URL: Set header_type and provide the public URL in header_link.
  • Using a Media ID: Set header_type and provide the ID of a previously uploaded media file in header_id.
  • Text Header: Set header_type to "text" and provide the text in header_text.

Body Variables

You can include dynamic variables in your template body by adding fields with the var_ prefix to your request body. These will be automatically mapped to the template parameters.

You can include dynamic variables in your template by adding fields with the var_ prefix to your request body. These will be automatically mapped to the template parameters.

Format: var_[parameter_name]: "value"

Examples:

  • var_customer_name: "John Doe" → maps to parameter customer_name
  • var_order_id: "12345" → maps to parameter order_id
  • var_delivery_date: "2024-01-15" → maps to parameter delivery_date

Response

Returns the created conversation object, including details about the message sent, contact, agent, and conversation metadata.

Example Response:

{
  "id": "conversation-id-123",
  "channel": "whatsapp",
  "channelExternalId": "to-number",
  "status": "RESOLVED",
  "createdAt": "2024-11-11T18:07:55.000Z",
  "updatedAt": "2024-11-11T18:07:55.000Z",
  "messages": [
    {
      "id": "message-id-789",
      "from": "agent",
      "text": "Your provided message text",
      "createdAt": "2024-11-11T18:07:55.000Z"
    }
  ]
}

Example JS Code

Basic Template (No Variables)

const apiUrl = 'https://api.chatvolt.ai';
const apiKey = 'XXX';
const phoneNumberId = 'XXX'; // Your WhatsApp Business Phone Number ID

const res = await fetch(
  `${apiUrl}/whatsapp/${phoneNumberId}/template-message`,
  {
    method: 'POST',
    body: JSON.stringify({
      to: '491234567890',
      text: 'Hello! Please check our latest offers.',
      agentId: 'abcd123456',
      templateName: 'special_offer',
      templateLangCode: 'en_US',
    }),
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${apiKey}`,
    },
  }
);

const data = await res.json();

Template with Variables

const apiUrl = 'https://api.chatvolt.ai';
const apiKey = 'XXX';
const phoneNumberId = 'XXX'; // Your WhatsApp Business Phone Number ID

const res = await fetch(
  `${apiUrl}/whatsapp/${phoneNumberId}/template-message`,
  {
    method: 'POST',
    body: JSON.stringify({
      to: '491234567890',
      text: 'Order confirmation for John Doe - Order #12345',
      agentId: 'abcd123456',
      templateName: 'order_confirmation',
      templateLangCode: 'en_US',

      // Template variables
      var_customer_name: 'John Doe',
      var_order_id: '12345',
      var_delivery_date: 'January 25, 2024',
      var_total_amount: '$299.99',
      defaultStatus: 'RESOLVED',
    }),
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${apiKey}`,
    },
  }
);

const data = await res.json();

Template with Image Header

const apiUrl = 'https://api.chatvolt.ai';
const apiKey = 'XXX';
const phoneNumberId = 'XXX'; // Your WhatsApp Business Phone Number ID

const res = await fetch(
  `${apiUrl}/whatsapp/${phoneNumberId}/template-message`,
  {
    method: 'POST',
    body: JSON.stringify({
      to: '491234567890',
      text: 'Here is your ticket.',
      agentId: 'abcd123456',
      templateName: 'ticket_with_image',
      templateLangCode: 'en_US',

      // Header
      header_type: 'image',
      header_link: 'https://example.com/ticket.png',

      // Body variables
      var_event_name: 'Tech Conference 2025',
      var_seat_number: 'A42',
    }),
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${apiKey}`,
    },
  }
);

const data = await res.json();

Template Variable Mapping

The API automatically converts var_ prefixed fields into WhatsApp Cloud API template components:

Request Body:

{
  "var_customer_name": "John Doe",
  "var_order_id": "12345"
}

Generated WhatsApp Components:

{
  "components": [
    {
      "type": "body",
      "parameters": [
        {
          "type": "text",
          "parameter_name": "customer_name",
          "text": "John Doe"
        },
        {
          "type": "text",
          "parameter_name": "order_id",
          "text": "12345"
        }
      ]
    }
  ]
}

Error Responses

Status CodeDescriptionDetails
400Bad Request - Missing required parametersOcorre se algum campo obrigatório estiver ausente (to, templateName, templateLangCode, phoneNumberId ou agentId). Significado: A requisição está malformada devido a parâmetros obrigatórios faltando. Verifique se todos os campos requeridos foram enviados.
401Unauthorized - Invalid token or accessOcorre se o agente não pertencer à organização do usuário logado. Significado: O usuário não tem permissão para usar este agente. Verifique autenticação e permissões.
402Payment Required - Premium subscription requiredOcorre se a organização não tiver uma assinatura ativa (premium). Significado: Recurso requer assinatura premium. Atualize a assinatura para continuar.
404Not Found - Phone number ID, agent or organization not foundOcorre se credenciais do phoneNumberId não forem encontradas, organização não existir ou campos requeridos estiverem ausentes (mapeado como 404, mas pode ser 400 na prática). Significado: Recurso não encontrado (phone number ID, agente ou organização). Verifique se o phoneNumberId está correto e configurado.
500Internal Server ErrorOcorre se o envio da mensagem WhatsApp falhar (!result), erros na sincronização com CRM (loggado mas não lança erro), ou outros erros não tratados (e.g., Prisma, sendWhatsAppMessage). Significado: Erro interno do servidor. Pode ser problema na integração WhatsApp (rede, credenciais inválidas, template rejeitado pelo WhatsApp), ou falha no banco/CRM. Verifique logs do servidor para detalhes. Para templates, verifique se o template está aprovado no WhatsApp Business Manager e se os componentes estão corretos.

CRM Integration

The API supports optional CRM (Customer Relationship Management) integration. If crmScenarioId and crmStepId are provided, the conversation will be automatically synchronized with the specified CRM scenario and step after the template message is sent.

  • Default Synchronization: If only the agent is provided, the conversation will be synchronized with the default CRM scenario associated with the agent.
  • Error Handling: Failures during CRM synchronization are logged but do not prevent the template message from being sent successfully.
  • Related Fields: crmScenarioId, crmStepId (optional) in the request body.

Webhooks

After sending a template message, a webhook with the event type AGENT_MESSAGE_SENDED is triggered asynchronously. It includes details about the message sent, conversation, agent, and contact.

Example Webhook Payload:

{
  eventType: "AGENT_MESSAGE_SENDED",
  conversationId: string,
  messageId: string,
  agentId: string,
  agentName: string,
  channel: "whatsapp",
  conversationStatus: string,
  conversationPriority: string,
  assigneeUserId: string,
  isAiEnabled: boolean,
  userName: string,
  userEmail: string,
  userPhoneNumber: string,
  summary: string,
  agentResponse: string
}

Notes:

  • The webhook is sent via WebhookFactory.sendAgentMessageSended if the agent has an external URL configured (agent.configUrlExternal.url).
  • It occurs after the message is successfully created and sent (or simulated in development).
{
  eventType: "AGENT_MESSAGE_SENDED",
  conversationId: string,
  messageId: string,
  agentId: string,
  agentName: string,
  channel: "whatsapp",
  conversationStatus: string,
  conversationPriority: string,
  assigneeUserId: string,
  isAiEnabled: boolean,
  userName: string,
  userEmail: string,
  userPhoneNumber: string,
  summary: string,
  agentResponse: string
}

Authorizations

Authorization
string
headerrequired

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

phoneNumberId
string
required

ID of the WhatsApp Business phone number

Body

application/json
to
string
required

Recipient's phone number with country code

text
string
required

Message text to store in conversation history

agentId
string
required

ID of the agent to associate with this message

templateName
string
required

Name of the pre-approved WhatsApp template

templateLangCode
string
required

Language code for the template

defaultStatus
enum<string>

The default status to set for the conversation.

Available options:
RESOLVED,
UNRESOLVED,
HUMAN_REQUESTED
{key}
string

Dynamic template variables with 'var_' prefix (e.g., var_customer_name, var_order_id)

Response

200 - application/json
id
string

Conversation ID

channelExternalId
string

External ID for the channel

channel
enum<string>

Conversation channel

Available options:
whatsapp
messages
object[]

Messages in the conversation