Skip to content

Template sending

Sends an approved message template through the WhatsApp Business API. The service resolves the template components directly from Meta: the payload only carries the template reference and its variable values.

Endpoint: POST /v1/template/messages/{did}

Parameters

Path

ParameterTypeRequiredDescription
didstringYesDestination ID. Must match the body did.

Body

FieldTypeRequiredDescription
didstringYesDestination ID. Same as path.
typestringYesFixed value template.
channelstringYesFixed value WHATSAPP.
templateobjectYes{name, language}: name and language of the approved template. Returns 404 if that combination does not exist.
recipientsarrayYesList of recipients {to, params}.
campaignIdnumberNoCampaign ID (camelCase).
client_idnumberNoOperating client. Requires BSP_CN permission when it differs from the token’s client.
attendsobjectNo{waitTime, typification}. See Attends.
message_send_ttl_secondsnumberNoMessage time-to-live in seconds.
componentobjectNoImage, video, document or location header. Required when the template uses that kind of header; type must match the template header format.

Recipient params

All arrays are positional: the first element maps to {{1}}, the second to {{2}}, and so on.

FieldTypeDescription
headerstring[]Values for the HEADER TEXT placeholder.
bodystring[]Values for the BODY placeholders.
buttonsstring[]Values for buttons carrying a variable (dynamic URL or COPY_CODE), in order of appearance. Buttons without variables (QUICK_REPLY, PHONE_NUMBER, static URL) are not declared.
productsobject[]Products for MPM/SPM templates.
cardsobject[]Per-card parameters in carousels: {body, buttons}.

Fields you do not send

The service calculates these and they are not part of the payload: namespace (resolved from the DID’s BSP configuration), the template’s BODY, FOOTER and BUTTONS components (fetched from Meta) and the contact total (derived from recipients). The only component declared in the payload is component.header, for templates with an image, video, document or location header. Sending unrecognized fields can break the request.

Attends

attends configures post-send behavior:

FieldTypeDescription
waitTimenumberSeconds to wait before handing over attention. QA usage: -1 keeps no attention session open, 0 starts immediately. Defaults to 0 when omitted.
typificationnumberInternal typification ID used to classify the interaction. 0 = untyped.

Both fields are optional and passed as-is to the dispatch engine: the service neither validates nor calculates them.

Request

Examples use only required fields plus whatever each case needs. Remember sending is positional-only: templates created with parameter_format = "named" cannot be sent through this API.

Basic example

Text template with two body variables:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "customer_offer",
      "language": "en"
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": {
          "body": ["John", "30"]
        }
      }
    ]
  }'

Plain text without variables

If the template has no placeholders, omit params:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "business_hours",
      "language": "en"
    },
    "recipients": [
      { "to": "521234567890" }
    ]
  }'

Text header + variables

The header array feeds the header placeholder first; the body array, the body ones:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "appointment_reminder",
      "language": "en"
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": {
          "header": ["Appointment confirmation"],
          "body": ["John", "tomorrow 10:00"]
        }
      }
    ]
  }'

Image, video or document header

For templates with a media header, component.header carries the type (which must match the template format), the file’s public URL and its name:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "product_catalog",
      "language": "en"
    },
    "component": {
      "header": {
        "type": "image_url",
        "value": "https://cdn.yourdomain.com/promo.jpg",
        "filename": "promo.jpg"
      }
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": {
          "body": ["John"]
        }
      }
    ]
  }'

Video and documents follow the same shape with "type": "video_url" or "document_url".

Location header

For templates with a LOCATION header, component.header carries the location object. The location is sent on every request even if identical for all recipients:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "nearest_store",
      "language": "en"
    },
    "component": {
      "header": {
        "type": "location",
        "location": {
          "latitude": "-33.3925562",
          "longitude": "-70.6261222",
          "name": "Chattigo",
          "address": "Av. El Salto 4001, floor 4, Huechuraba, Santiago"
        }
      }
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": {
          "body": ["John"]
        }
      }
    ]
  }'

URL button with variable

If the template’s URL button uses a variable in the link, its value travels in buttons:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "order_tracking",
      "language": "en"
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": {
          "body": ["John"],
          "buttons": ["12345"]
        }
      }
    ]
  }'

COPY_CODE button (discount code)

The coupon travels in buttons as a string:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "welcome_coupon",
      "language": "en"
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": {
          "body": ["John"],
          "buttons": ["WELCOME20"]
        }
      }
    ]
  }'

Catalog template (MPM)

For multi-product, products carries the action with the featured product and the catalog sections. IDs are the Meta catalog’s product_retailer_id values:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "hsm_multiproducto",
      "language": "en"
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": {
          "products": [
            {
              "type": "action",
              "action": {
                "thumbnailProductRetailerId": "0003",
                "sections": [
                  {
                    "title": "Clothing and accessories",
                    "product_items": [
                      { "product_retailer_id": "0064" },
                      { "product_retailer_id": "0042" }
                    ]
                  },
                  {
                    "title": "Food and drinks",
                    "product_items": [
                      { "product_retailer_id": "0039" }
                    ]
                  }
                ]
              }
            }
          ]
        }
      }
    ]
  }'

For single-product catalogs (SPM), action carries only thumbnailProductRetailerId.

Carousel

Each card receives its parameters in cards, in the same order as the template cards:

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "template": {
      "name": "carousel_options",
      "language": "en"
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": {
          "cards": [
            { "body": ["Card 1"], "buttons": ["option-a"] },
            { "body": ["Card 2"], "buttons": ["option-b"] }
          ]
        }
      }
    ]
  }'

Full example with optional fields

curl --request POST \
  --url 'https://api.chattigo.com/v1/template/messages/{did}' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
    "did": "5731000000000",
    "type": "template",
    "channel": "WHATSAPP",
    "campaignId": 3612,
    "client_id": 42,
    "attends": { "waitTime": 5, "typification": 383393 },
    "message_send_ttl_seconds": 3600,
    "template": {
      "name": "customer_offer",
      "language": "en"
    },
    "recipients": [
      {
        "to": "521234567890",
        "params": { "body": ["John", "30"] }
      }
    ]
  }'

Response

Success (200)

{
  "success": true
}

With warning (e.g.: campaign or language warning):

{
  "success": true,
  "warning": "..."
}

Errors

CodeCase
400did is required or invalid payload
403DID outside the WABA hierarchy or client_id without BSP_CN permission
404Template does not exist for the requested name/language
422Path did does not match body did, or invalid template
502External service unreachable (Meta or internal dispatch)
  • Only templates in APPROVED status can be sent.
  • Positional only. Parameters (header, body, buttons) are ordered []string and placeholders must be positional ({{1}}, {{2}}, …). parameter_format = "named" is not supported; templates created as named in Meta cannot be sent through api-bsp-chattigo.