Send campaign from CSV

Send one or more messages defined in a campaign to a list of contacts defined in a CSV file

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…
Path Params
integer
required

Application's ID

integer
required

Campaign's ID

Body Params
string
required

The layout is a JSON with the necessary information to send the messages.
The variables should be enclosed in double curly braces (ex: {{variable}}).

Important: Variable names can only contain letters, numbers, dots (.) and underscores (_). Spaces or special characters are not allowed inside variable placeholders (e.g. {{nombre cliente}} is invalid, use {{nombre_cliente}} instead).

The only required fields are contactCode + channelType, externalCode alone, or bsuid alone (inside the contact object).

You can use externalCode instead of contactCode to identify contacts by their external code. When using externalCode, channelType is not required. If multiple contacts share the same externalCode, a message will be sent to each of them.

You can also use bsuid instead of contactCode to identify contacts by their bsuid. channelType is not required: bsuid only applies to CLOUD_API (WhatsApp) contacts, so channelType is always treated as cloud_api. Unlike externalCode, bsuid is treated as a direct sending identifier (like contactCode).

Optionally, you can use the 'customFields' property to define which columns in the CSV correspond to the variables used in the campaign to be sent.

Other fields like sendType or messageContent are defined in the campaign, so you don't need to define them in the layout.

An examples of layouts:

Example 1: using both contact variables and custom fields

{
  "contact": {
    "contactCode": "{{contactCode}}",
    "channelType": "{{channelType}}"
  },
  "customFields": { 
      "name": "{{nombre}}",
      "ticketId": "{{ticket_id}}",
      "age": "{{edad}}"
  }
}

Example 2: It's not necessary to define a variable for the channelType property (if all recipients belong to the same channel). It's also not required to define the customFields property if the campaign doesn't have variables.

{
  "contact": {
    "contactCode": "{{contactCode}}",
    "channelType": "cloud_api"
  }
}

Example 3: you can use other names for the variables

{
  "contact": {
    "contactCode": "{{phoneNumber}}",
    "channelType": "{{channel}}"
  },
  "customFields": { 
      "name": "{{nombre_cliente}}",
      "age": "{{edad_cliente}}"
  }
}

Example 4: It's not mandatory to define variables for custom fields; you can use fixed values instead.

{
  "contact": {
    "contactCode": "{{contactCode}}",
    "channelType": "{{channelType}}"
  },
  "customFields": { 
      "name": "Dear client",
      "discount": "10%"
  }
}

Example 5: Using externalCode instead of contactCode to identify contacts. channelType is not required.

{
  "contact": {
    "externalCode": "{{externalCode}}"
  },
  "customFields": { 
      "name": "{{nombre}}"
  }
}

Example 6: Using bsuid instead of contactCode to identify contacts. channelType is not needed (bsuid always targets cloud_api). bsuid is a direct sending identifier: the message is sent using the bsuid value itself (no contact lookup/swap like externalCode), and if the contact doesn't exist yet it's created with contactCode = bsuid.

{
  "contact": {
    "bsuid": "{{bsuid}}"
  },
  "customFields": { 
      "name": "{{nombre}}"
  }
}

Optionally, you can include a context object to update the contact's context. Map context keys to CSV column variable placeholders:

"context": {
  "preferred_store": "{{store_column}}",
  "loyalty_level": "{{level_column}}"
}

Context updates are not allowed for scheduled or delayed sendings.

file
required

A CSV file with the contacts to be sent.

Each row in the CSV file represents a contact to be sent.
Each column in the CSV file represents a variable in the layout.

Remember that you should define the columns for contactCode + channelType or externalCode in the CSV file.
The other custom fields (like name, age, ticketId, etc) depend how you define your variables in the campaign.

An examples of CSV files:

Example 1: using both contact variables and custom fields

contactCode,channelType,nombre,ticket_id,edad
34666777888,cloud_api,John,5123,30
34666555666,cloud_api,Jane,5528,25
34666111222,cloud_api,Alice,4125,28

Example 2: using the same channel for all contacts and not defining the custom fields

contactCode
34666777888
34666555666
34666111222

Example 3: using other names for the variables

phoneNumber,channel,nombre_cliente,edad_cliente
34666777888,cloud_api,John,30
34666555666,cloud_api,Jane,25
34666111222,cloud_api,Alice,28

Example 4: using fixed values for custom fields you don't need to define columns for them

contactCode,channelType
34666777888,cloud_api
34666555666,cloud_api
34666111222,cloud_api
date-time

The date and time when the messages should be sent.
If not provided, the messages will be sent immediately.

The format must be in ISO 8601 (e.g., 2025-10-01T12:15:00Z).

The scheduling date must be within the range from now up to a maximum of 3 months into the future.

string
^P(?!$)(?:(?:\d+Y)?(?:\d+M)?(?:\d+W)?(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+(?:\.\d+)?S)?)?)$

The delay before sending the messages.
The use of this property will schedule the sending of the messages to be sent after the specified delay from the current time.

This property can not be used in conjunction with the scheduleAt property.

The format must be in ISO 8601 duration.

Examples:

  • PT0.25S for 250 milliseconds
  • PT20S for 20 seconds
  • PT15M for 15 minutes
  • PT30M50.5S for 30 minutes, 50 seconds and 500 milliseconds
  • PT4H for 4 hours
  • P3D for 3 days
  • P2W for 2 weeks
  • P1M for 1 month
string
enum
Defaults to fragmentedSlots

The slicing condition allows you to define how the messages should be sliced when sending them.

  • fragmentedSlots: If slicing is enabled, slots will be assigned based on availability starting from the scheduled time, regardless of whether they are consecutive, and only within the next 48 hours.
  • immediateConsecutiveSlots: If slicing is enabled, slots will be assigned based on availability starting from the current time (or from the scheduled time,
    if it's a scheduled sending), and within the next 48 hours — but only if they are consecutive.
    If not enough consecutive slots are found, the task will be marked as canceled and will not be executed.
  • deferredConsecutiveSlots: If slicing is enabled, the system will attempt to find the first set of consecutive available slots starting from the current time
    (or from the scheduled time, if it's a scheduled sending) and within the next 48 hours.
    Unlike immediateConsecutiveSlots, the consecutive block does not need to start in the first evaluated slot, so fully occupied slots can be skipped until a valid block is found.
    If no suitable consecutive block is found, the task will be marked as canceled and will not be executed.

If not provided, the default condition is fragmentedSlots.

Keep in mind that these conditions will only apply to a given sending when the slicing activation criteria are met.
Also, any slots that fall within the configured forbiddenHourRanges will be considered unavailable for all slicing strategies.

Allowed:
string
enum
Defaults to false

If true, allows overriding proactive messaging restrictions.
This requires the 'proactiveRestrictionOverride' feature to be enabled in the application's configuration.
If false or not provided, default contact-level restrictions apply.

Allowed:
string
enum
Defaults to false

If true, preserves the current Typebot session for contacts in this sending.
If false or not provided, proactive sendings clear the session when the Typebot integration exists and is enabled.

Allowed:
Responses

Language
Credentials
Header
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json