---
title: "Send a message"
method: POST
path: "/v1/projects/{project_id}/messages/send"
tags: ["Message"]
---

# Send a message

`POST /v1/projects/{project_id}/messages/send`

## Request

- Base URL: `https://api.telerivet.com`
- URL: `https://api.telerivet.com/v1/projects/{project_id}/messages/send`
- Auth: one of:
  - HTTP basic
  - OAuth 2 (authorization code, authorization URL `https://telerivet.com/oauth/authorize`, token URL `https://api.telerivet.com/oauth/token`)

Sends one message (SMS, MMS, chat app message, voice call, or USSD request).

 If Message Review is enabled for the project and this message requires approval (because the project requires approval for messages sent via AI tools, or its review threshold is 0 or its daily or monthly review budget is exhausted), the message will not be sent immediately; instead, it will be submitted for review as a scheduled message, and will be sent when a reviewer approves it. In this case, the response will contain `status`=`pending_review`, `scheduled_message_id`, and `url` (a link to the approval page in the web app) properties instead of the message properties. The project's `message_review` property (returned by getProjectById) shows in advance whether sends will require approval.

## Path parameters

- `project_id` string, required

## Request body

- object
  - `message_type` 'text' | 'sms' | 'mms' | 'ussd' | 'call' | 'chat' | 'service': Type of message to send. If `text`, will use the default text message type for the selected route.
  - `content` string: Content of the message to send (if `message_type` is `call`, the text will be spoken during a text-to-speech call)
  - `to_number` string: Phone number to send the message to
  - `contact_id` string: ID of the contact to send the message to
  - `route_id` string: ID of the phone or route to send the message from
  - `status_url` string: Webhook callback URL to be notified when message status changes
  - `status_secret` string: POST parameter 'secret' passed to status_url
  - `replace_variables` boolean: Set to true to evaluate variables like [[contact.name]] in message content. (See available variables)
  - `track_clicks` boolean: If true, URLs in the message content will automatically be replaced with unique short URLs.
  - `short_link_params` object: If `track_clicks` is true, `short_link_params` may be used to specify custom parameters for each short link in the message. The following parameters are supported: `domain` (string): A custom short domain name to use for the short links. The domain name must already be registered for your project or organization. `expiration_sec` (integer): The number of seconds after the message is created (queued to send) when the short links will stop forwarding to the destination URL. If null, the short links will not expire.
  - `media` object[]: Array of media attachments for the text message. If sending a type of message that doesn't support attachments (e.g. SMS), short links to each media URL will be appended to the end of the content (separated by a new line). To attach the Contact Card (a `.vcf` file that the recipient can save to their address book) of the route that sends the message, include the media item `{"type": "route_vcard"}`. The card is attached when each message is sent, using the current card of the phone that actually sends it (see the `vcard` property of the Phone object). If that route's Contact Card is not enabled, the message is sent without it. Alternatively, you can use the `media_urls` parameter with an array of URL strings.
    - `url` string: URL of the media file. Required unless file_id is provided. Use a https:// or http:// URL for media files that are already accessible via the internet. For media files that are not already accessible via the internet or uploaded as a stored file, the URL may be a data URI with the file data encoded via Base64 (e.g. "data:image/png;base64,..."), with a maximum decoded file size of 5 MB. Telerivet will automatically store this file in your project.
    - `file_id` string: ID of a previously uploaded stored file (see [project.uploadFile](#Project.uploadFile)). If file_id is provided, url is not required.
    - `type` string: MIME type of the media file (e.g. image/png). if not provided, Telerivet will attempt to determine the MIME type automatically from the extension of the filename or URL path component. Ignored if file_id is provided. To attach the Contact Card of the route that sends the message, use a media item with only `type` set to `route_vcard`.
    - `filename` string: Original filename of the media. Ignored if file_id is provided.
  - `route_params` object: Route-specific parameters for the message. When sending messages via chat apps such as WhatsApp, the route_params parameter can be used to send messages with app-specific features such as quick replies and link buttons. For more details, see Route-Specific Parameters.
  - `variants` object[]: Alternative message bodies (text messages only). Allows sending different message bodies depending on the route that sends the message, or the contact that the message is sent to. Each variant has conditions and its own message body. When each message is sent, the first variant whose conditions match is used instead of the default message body; if no variant matches, the default message body is used. A variant replaces the entire message body: content, media, route_params, track_clicks and short_link_params that are not specified in the variant are empty, not inherited from the default message body. Conditions are evaluated when the message is sent by a particular basic route, and can use the same variables as outgoing message content: contact variables such as [[contact.name]] and [[contact.vars.\*]], [[to_number]], [[time]], [[project.\*]], and variables of the basic route sending the message: [[phone.type]] (e.g. whatsapp), [[phone.id]], [[phone.vars.\*]], and [[phone.supports_quick_replies]], [[phone.supports_link_button]], [[phone.supports_native_attachments]] (1 if the route supports the feature, otherwise 0). Variables may include filters, e.g. [[contact.vars.language|default:"en"]]. For all available variables, see the [Variable Reference](https://telerivet.com/api/rest#variables). For A/B testing, a variant can have a random split (split_percent) so that it is only used for a random percentage of recipients, e.g. a single variant with split_percent 50 is used for about half of the recipients, and the default message body for the others. A random split can be combined with other conditions to run separate A/B tests for different routes or contacts. Since the first matching variant is used, list more specific variants before more general ones. For example, a variant with a condition `[[contact.vars.language]] is 'fr'` and split_percent 50 must be listed before a variant with only the condition `[[contact.vars.language]] is 'fr'`. Up to 10 variants are supported, each with up to 5 conditions.
    - `conditions` object[]: Conditions for using this variant (up to 5). Required unless the variant has a `split_percent`.
      - `variable` string: Variable to compare (required except when condition type is `contact_is_in_group` or `contact_not_in_group`), surrounded by double square brackets, e.g. `[[phone.type]]` or `[[contact.vars.lang]]`
      - `type` string, required: Type of condition
      - `value` string, required: Value to compare with the variable, or the group name if the condition type is `contact_is_in_group` or `contact_not_in_group`
    - `op` string: Operator to join multiple conditions: `and` (default) or `or`. If `split_percent` is specified, `or` is not supported.
    - `split_percent` integer: For A/B testing, the approximate percentage of recipients (1-100) randomly selected for this variant. Each variant with a `split_percent` is used for a separate random group of recipients, and recipients not selected for any variant receive the default message body (e.g. a single variant with a `split_percent` of 50 is used for about half of the recipients). Recipients are assigned to groups deterministically, so each contact is in the same group for all messages in the same broadcast or campaign. The total `split_percent` of all variants with the same conditions can be at most 100. If `split_percent` is omitted, the variant is used for all recipients that match its conditions.
    - `content` string: Content of the message when this variant is used
    - `media` object[]: Array of media attachments when this variant is used (same format as the `media` parameter)
    - `route_params` object: Route-specific parameters when this variant is used
    - `track_clicks` boolean: Whether to shorten links and track link clicks when this variant is used
    - `short_link_params` object: Parameters for short links when `track_clicks` is enabled (same format as the `short_link_params` parameter)
  - `label_ids` string: List of IDs of labels to add to this message
  - `vars` object: Custom variables to store with the message
  - `priority` 1 | 2: Priority of the message. Telerivet will attempt to send messages with higher priority numbers first (for example, so you can prioritize an auto-reply ahead of a bulk message to a large group).
  - `simulated` boolean: Set to true to test the Telerivet API without actually sending a message from the route
  - `service_id` string: Service that defines the call flow of the voice call (when `message_type` is `call`)
  - `audio_url` string: The URL of an MP3 file to play when the contact answers the call (when `message_type` is `call`). If `audio_url` is provided, the text-to-speech voice is not used to say `content`, although you can optionally use `content` to indicate the script for the audio. For best results, use an MP3 file containing only speech. Music is not recommended because the audio quality will be low when played over a phone line.
  - `tts_lang` 'en-US' | 'en-GB' | 'en-GB-WLS' | 'en-AU' | 'en-IN' | 'da-DK' | 'nl-NL' | 'fr-FR' | 'fr-CA' | 'de-DE' | 'is-IS' | 'it-IT' | 'pl-PL' | 'pt-BR' | 'pt-PT' | 'ru-RU' | 'es-ES' | 'es-US' | 'sv-SE': The language of the text-to-speech voice (when `message_type` is `call`)
  - `tts_voice` 'female' | 'male': The name of the text-to-speech voice (when message_type=call)

## Response `200`

Successful response

- Message: Represents a single message.
  - `id` string: ID of the message
  - `direction` 'incoming' | 'outgoing': Direction of the message: incoming messages are sent from one of your contacts to your phone; outgoing messages are sent from your phone to one of your contacts
  - `status` 'ignored' | 'processing' | 'received' | 'sent' | 'queued' | 'failed' | 'failed_queued' | 'cancelled' | 'delivered' | 'not_delivered' | 'read': Current status of the message
  - `message_type` 'sms' | 'mms' | 'ussd' | 'ussd_session' | 'call' | 'chat' | 'service': Type of the message
  - `source` 'phone' | 'provider' | 'web' | 'api' | 'service' | 'webhook' | 'scheduled' | 'integration' | 'mcp' | 'welcome': How the message originated within Telerivet
  - `time_created` integer: The time that the message was created on Telerivet's servers
  - `time_sent` integer, nullable: The time that the message was reported to have been sent (null for incoming messages and messages that have not yet been sent)
  - `time_updated` integer: The time that the message was last updated in Telerivet.
  - `from_number` string: The phone number that the message originated from (your number for outgoing messages, the contact's number for incoming messages)
  - `to_number` string: The phone number that the message was sent to (your number for incoming messages, the contact's number for outgoing messages)
  - `content` string: The text content of the message (null for USSD messages and calls)
  - `starred` boolean: Whether this message is starred in Telerivet
  - `simulated` boolean: Whether this message was simulated within Telerivet for testing (and not actually sent to or received by a real phone)
  - `label_ids` string: List of IDs of labels applied to this message
  - `route_params` object, nullable: Route-specific parameters for the message. When sending messages via chat apps such as WhatsApp, the route_params parameter can be used to send messages with app-specific features such as quick replies and link buttons. For more details, see Route-Specific Parameters.
  - `variant` integer, nullable: For outgoing messages sent with `variants`, the index (starting at 0) of the variant used to send the message. Undefined if the default message body was used.
  - `vars` object: Custom variables stored for this message. Variable names may be up to 32 characters in length and can contain the characters a-z, A-Z, 0-9, and _. Values may be strings, numbers, or boolean (true/false). String values may be up to 4096 bytes in length when encoded as UTF-8. Up to 100 variables are supported per object. Setting a variable to null will delete the variable.
  - `priority` integer: Priority of this message. Telerivet will attempt to send messages with higher priority numbers first. Only defined for outgoing messages.
  - `send_attempts` number, nullable: The number of times Telerivet has attempted to send the message. Will be greater than 1 if the message has been resent. Only defined for outgoing messages.
  - `error_message` string: A description of the error encountered while sending a message. (This field is omitted from the API response if there is no error message.)
  - `error_code` string: A route-specific error code encountered while sending a message. The error code values depend on the provider and may be described in the provider's API documentation. Error codes may be strings or numbers, depending on the provider. (This field is omitted from the API response if there is no error code.)
  - `external_id` string: The ID of this message from an external SMS gateway provider (e.g. Twilio or Vonage), if available.
  - `num_parts` number, nullable: The number of SMS parts associated with the message, if applicable and if known.
  - `price` number, nullable: The price of this message, if known.
  - `price_currency` string: The currency of the message price, if applicable.
  - `duration` number, nullable: The duration of the call in seconds, if known, or -1 if the call was not answered.
  - `ring_time` number, nullable: The length of time the call rang in seconds before being answered or hung up, if known.
  - `audio_url` string: For voice calls, the URL of an MP3 file to play when the contact answers the call
  - `tts_lang` 'en-US' | 'en-GB' | 'en-GB-WLS' | 'en-AU' | 'en-IN' | 'da-DK' | 'nl-NL' | 'fr-FR' | 'fr-CA' | 'de-DE' | 'is-IS' | 'it-IT' | 'pl-PL' | 'pt-BR' | 'pt-PT' | 'ru-RU' | 'es-ES' | 'es-US' | 'sv-SE': For voice calls, the language of the text-to-speech voice
  - `tts_voice` 'female' | 'male': For voice calls, the text-to-speech voice
  - `track_clicks` boolean: If true, URLs in the message content are short URLs that redirect to a destination URL.
  - `short_urls` object[]: For text messages containing short URLs, this is an array of objects with the properties `short_url`, `link_type`, `time_clicked` (the first time that URL was clicked), and `expiration_time`. If `link_type` is "redirect", the object also contains a `destination_url` property. If `link_type` is "media", the object also contains an `media_index` property (the index in the media array). If `link_type` is "service", the object also contains a `service_id` property. This property is undefined for messages that do not contain short URLs.
    - `short_url` string: The short URL
    - `link_type` string: Type of link: redirect, media, or service
    - `time_clicked` integer: First time this URL was clicked
    - `expiration_time` integer: When this short URL expires
    - `destination_url` string: Destination URL (when link_type is redirect)
    - `media_index` integer: Index in media array (when link_type is media)
    - `service_id` string: Service ID (when link_type is service)
  - `network_code` string: A string identifying the network that sent or received the message, if known. For mobile networks, this string contains the 3-digit mobile country code (MCC) followed by the 2- or 3-digit mobile network code (MNC), which results in a 5- or 6-digit number. For lists of mobile network operators and their corresponding MCC/MNC values, see [Mobile country code Wikipedia article](https://en.wikipedia.org/wiki/Mobile_country_code). The network_code property may be non-numeric for messages not sent via mobile networks.
  - `media` object[]: Array of media attachments for the text message. This property is undefined for messages that do not contain media files.
    - `url` string: URL of the media file. Note: For files stored by Telerivet (including uploaded files and incoming media attachments), the URL is temporary and may not be valid for more than 1 day.
    - `type` string: MIME type of the media file, or `route_vcard` for the Contact Card of the sending route in a message that has not been sent yet (in which case the other properties are null)
    - `filename` string: Original filename
    - `size` integer: File size in bytes
    - `file_id` string: ID of the stored file, if applicable
  - `mms_parts` object[]: A list of parts in the MMS message (only for incoming MMS messages received via Telerivet Gateway Android app). Each MMS part in the list is an object with the following properties: - cid: MMS content-id - type: MIME type - filename: original filename - size (int): number of bytes - url: URL where the content for this part is stored (secret but publicly accessible, so you could link/embed it in a web page without having to re-host it yourself) In general, the `media` property of the message is recommended for retrieving information about MMS media files, instead of `mms_parts`. The `mms_parts` property is also only present when retrieving an individual MMS message by ID, not when querying a list of messages.
    - `cid` string: MMS content-id
    - `type` string: MIME type
    - `filename` string: Original filename
    - `size` integer: Number of bytes
    - `url` string: URL where the content is stored
  - `time_clicked` integer: If the message contains any short URLs, this is the first time that a short URL in the message was clicked. This property is undefined for messages that do not contain short URLs.
  - `service_id` string: ID of the service that handled the message (for voice calls, the service defines the call flow)
  - `phone_id` string: ID of the phone (basic route) that sent or received the message
  - `contact_id` string: ID of the contact that sent or received the message
  - `route_id` string: ID of the custom route that sent the message (if applicable)
  - `broadcast_id` string: ID of the broadcast that this message is part of (if applicable)
  - `scheduled_id` string: ID of the scheduled message that created this message is part of (if applicable)
  - `user_id` string: ID of the Telerivet user who sent the message (if applicable)
  - `project_id` string: ID of the project this contact belongs to
  - `url` string: URL to the message detail page in the Telerivet web app

## Other responses

- `400`: Invalid request parameters
- `401`: Invalid or missing API key or Bearer token
- `404`: Resource not found

---

[API](https://skmtc.dev/telerivet/apis/telerivet-api.md) · [All operations](https://skmtc.dev/telerivet/apis/telerivet-api/llms.txt) · [OpenAPI document](https://skmtc.dev/telerivet/apis/telerivet-api/revisions/4e14b1c8d917?raw)
