Skip to main content

Send Text Messages

SendSeven lets you send text messages to existing conversations or directly to contacts on any supported channel. This guide covers both approaches with full examples.

Required Scopes

ScopePurpose
messages:createSend messages to conversations
messages:createSend messages to contacts

Send a Message to a Conversation

If you already have a conversation ID (from a webhook event or the Conversations API), you can send a message directly into it.

POST /api/v1/messages

Request Body

FieldTypeRequiredDescription
conversation_idstringYesTarget conversation ID
textstringYesMessage text content
message_typestringYesMust be text

curl

curl -X POST "https://api.sendseven.com/api/v1/messages" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"conversation_id": "conv_8f3a2b1c",
"text": "Your order #1234 has been shipped! Tracking number: TR-98765.",
"message_type": "text"
}'

Python

import requests

BASE_URL = "https://api.sendseven.com/api/v1"
HEADERS = {
"Authorization": "Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00",
"Content-Type": "application/json",
}

response = requests.post(
f"{BASE_URL}/messages",
headers=HEADERS,
json={
"conversation_id": "conv_8f3a2b1c",
"text": "Your order #1234 has been shipped! Tracking number: TR-98765.",
"message_type": "text",
},
)
message = response.json()
print(f"Message sent: {message['id']} - Status: {message['status']}")

JavaScript

const BASE_URL = "https://api.sendseven.com/api/v1";
const HEADERS = {
"Authorization": "Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00",
"Content-Type": "application/json",
};

const response = await fetch(`${BASE_URL}/messages`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({
conversation_id: "conv_8f3a2b1c",
text: "Your order #1234 has been shipped! Tracking number: TR-98765.",
message_type: "text",
}),
});
const message = await response.json();
console.log(`Message sent: ${message.id}`);

Response

{
"id": "msg_c3d4e5f6",
"conversation_id": "conv_8f3a2b1c",
"direction": "outbound",
"text": "Your order #1234 has been shipped! Tracking number: TR-98765.",
"message_type": "text",
"status": "pending",
"created_at": "2026-02-10T15:10:00Z"
}

Send a Message Without a Conversation ID

You can also send messages without an existing conversation ID. SendSeven automatically creates or resumes the appropriate conversation. The POST /api/v1/messages endpoint supports three resolution modes:

POST /api/v1/messages

Mode 1: Send via Contact Method ID (Cleanest)

If you know the contact method ID (from the Contacts API), this is the simplest way to send. The system resolves the recipient and channel automatically.

FieldTypeRequiredDescription
contact_method_idstringYesContact method ID (resolves recipient and channel)
textstringYesMessage text content
message_typestringNoDefault: text
curl -X POST "https://api.sendseven.com/api/v1/messages" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"contact_method_id": "cm_a1b2c3d4",
"text": "Your appointment is confirmed for tomorrow at 10:00 AM.",
"message_type": "text"
}'

Mode 2: Send to Contact with Channel (Explicit)

Specify the contact, channel, and optionally a recipient address. The to field is optional -- when omitted, SendSeven resolves the recipient from the contact's stored details.

FieldTypeRequiredDescription
contact_idstringYesTarget contact ID
channel_idstringNoChannel to send through. When omitted, SendSeven auto-selects an active channel for the contact (priority: WhatsApp, Telegram, Messenger, Instagram, SMS, Email). Pass it to disambiguate when the contact is reachable on several channels.
textstringYesMessage text content
message_typestringNoDefault: text
tostringNoRecipient address (e.g. phone number). Resolved automatically if omitted.
curl -X POST "https://api.sendseven.com/api/v1/messages" \
-H "Authorization: Bearer s7_api_a1b2c3d4e5f6789012345678abcdef00" \
-H "Content-Type: application/json" \
-d '{
"contact_id": "contact_d4e5f6a7",
"channel_id": "ch_tg_001",
"text": "Your appointment is confirmed for tomorrow at 10:00 AM.",
"message_type": "text"
}'

Python

# Mode 1: Via contact method ID
response = requests.post(
f"{BASE_URL}/messages",
headers=HEADERS,
json={
"contact_method_id": "cm_a1b2c3d4",
"text": "Your appointment is confirmed for tomorrow at 10:00 AM.",
"message_type": "text",
},
)
message = response.json()
print(f"Sent to contact: {message['id']}")

# Mode 2: Via contact + channel
response = requests.post(
f"{BASE_URL}/messages",
headers=HEADERS,
json={
"contact_id": "contact_d4e5f6a7",
"channel_id": "ch_tg_001",
"text": "Your appointment reminder: tomorrow at 2 PM.",
"message_type": "text",
},
)
message = response.json()
print(f"Sent to contact: {message['id']}")

JavaScript

// Mode 1: Via contact method ID
const response = await fetch(`${BASE_URL}/messages`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({
contact_method_id: "cm_a1b2c3d4",
text: "Your appointment reminder: tomorrow at 2 PM.",
message_type: "text",
}),
});
const message = await response.json();
console.log("Sent:", message.id);

Response

{
"id": "msg_d4e5f6g7",
"conversation_id": "conv_new_or_existing",
"direction": "outbound",
"text": "Your appointment is confirmed for tomorrow at 10:00 AM.",
"message_type": "text",
"status": "pending",
"created_at": "2026-02-10T15:20:00Z"
}
tip

When sending without a conversation ID, SendSeven automatically finds or creates the right conversation. Use contact_method_id when possible -- it is the cleanest approach and requires the fewest fields.

Message Status Values

After sending, a message progresses through these statuses:

StatusDescription
pendingMessage accepted and queued for delivery (the initial status returned by POST /messages)
sentMessage sent to the channel provider
deliveredDelivery confirmed by the channel
readMessage read by the recipient (if supported)
failedDelivery failed
warning

For WhatsApp, you can only send free-form text messages within a 24-hour window after the contact's last message. Outside this window, you must use an approved template.

Error Responses

StatusError CodeDescription
401INVALID_TOKENToken is invalid or expired
403INSUFFICIENT_SCOPEToken lacks messages:create
404RESOURCE_NOT_FOUNDConversation or contact not found
422VALIDATION_ERRORInvalid message content or missing required fields

Next Steps