Messages

Overview

A Message object in Sent is the fundamental record of any communication sent to a contact. It represents a single, trackable instance of a message sent through a specific channel (SMS or WhatsApp).

Every time you initiate a communication via the API, a Message object is created. This object allows you to:

  • Track Delivery: Monitor the complete lifecycle of a message from queue to delivery.
  • Audit Communications: Maintain a verifiable history of all messages sent to your contacts.
  • Debug Issues: Access detailed status history and provider responses to troubleshoot delivery problems.
  • Manage Costs: See the precise cost associated with each message sent.

The Message Lifecycle

When you send a message, it progresses through several statuses. Understanding this lifecycle is key to building a robust integration.

Successful Message Flow

Failed Message Flow

Status Descriptions

  • Queued: Your API request was successful, and the message is in Sent's queue awaiting processing. This is the initial status you receive in the API response.
  • Sent: The message has been successfully dispatched from Sent to the channel provider (e.g., SMS provider, Meta for WhatsApp).
  • Delivered: The channel provider has confirmed the message was successfully delivered to the recipient's device.
  • Read: (WhatsApp Only) The recipient has opened and read the message.
  • Failed: The message could not be delivered. The Message object will contain an error object with details.

You will receive real-time updates for these status changes via webhooks.

📚 Want to learn more about webhooks? Check out our Webhooks guide.

Automatic Channel Selection

One of the most powerful features of Sent is its ability to choose the best communication channel for you. If you omit the channel field when sending a message, Sent will:

  1. Check the Contact's channel availability.
  2. Prioritize WhatsApp if it is available (as it offers a richer experience and is often more cost-effective).
  3. Fall back to SMS if WhatsApp is not available.
  4. The selected channel can be retrieved in the Message Object using webhooks.

This allows you to maintain a simple integration while Sent handles the channel complexity.

Sending Messages

Messages can be sent either through the Sent Dashboard playground or programmatically via the API.

Dashboard Playground

You can send messages through the integrated Playground in your Sent Dashboard. The playground provides:

  • Visual message composer with template selection and template variable testing
  • Message history and delivery tracking
  • One-click sending to contacts or phone numbers

Every outbound message incurs a cost, which is automatically deducted from your customer account balance.

  • Pricing is determined by the channel and the recipient's country.
  • If your balance is insufficient to cover the cost of a message, the API call to send it will fail with a 402 Payment Required error.
  • The final cost is confirmed in the Message object, accessible via API or webhooks.

Message Status Tracking

The journey of a message after the initial API call is asynchronous. Polling the API for status updates is not supported and is highly discouraged.

The correct way to track message delivery is to use webhooks. When a message's status changes (e.g., from sent to delivered), Sent will immediately send a message.status.updated event to your configured webhook URL. This provides real-time, push-based updates without requiring you to make constant API calls.

📚 Want to learn more about webhooks? Check out our Webhooks guide.

The Message Object: Schema

This is the schema of a Message object you will receive in a webhook payload.

FieldTypeDescription
idGUIDThe unique identifier for the Message. Store this ID to track the message.
customerIdGUIDThe ID of the customer account that sent the message.
contactobjectA summary object of the recipient contact.
templateobjectA summary object of the template used for the message.
channelstringThe channel used for delivery ("sms" or "whatsapp").
messageBodystringThe final, rendered text content of the message after variable substitution.
statusstringThe current delivery status of the message. See The Message Lifecycle.
statusHistoryarrayAn array of objects, providing a complete chronological history of status changes.
channelResponseobjectThe raw response or status object from the channel provider. Useful for advanced debugging.
pricingobjectAn object detailing the cost of the message.
createdAtstringThe ISO 8601 timestamp when the message was created.
updatedAtstringThe ISO 8601 timestamp when the message's status was last updated.

Example statusHistory Object:

"statusHistory": [
  { "status": "sent", "timestamp": "2025-01-15T08:30:01Z" },
  { "status": "delivered", "timestamp": "2025-01-15T08:30:15Z" }
]

Example pricing Object:

"pricing": {
  "originalPrice": 0.0125,
  "correctedPrice": 0.0125,
  "currency": "USD"
}

Best Practices

  • Store the messageId: This is your primary key for tracking a message's lifecycle. Log it in your local database against the relevant user or event. It is essential for correlating webhook events and for any communication with Sent support.
  • Implement Webhooks: A robust webhook handler is critical for a reliable messaging integration. It is the only way to get real-time delivery confirmations and failure notifications.
  • Handle Failures Gracefully: When you receive a webhook for a failed message, use the error code to decide on a course of action. For certain transient errors, you might retry the message. For permanent failures (like an invalid number), you should flag the contact in your system.
  • Leverage Automatic Channel Selection: Unless you have a specific business reason to force a channel (e.g., sending a time-sensitive OTP where SMS is preferred), let Sent choose the optimal channel for you.
  • Use contactId: Always send messages using the contactId rather than a raw phone number. This is more efficient as it bypasses the need for Sent to perform a contact lookup and validation on every send.