/v1/comms/sendSend a text or an email to an address
THE SEND: a medium ("sms", "imessage" or "email"), the address to write to (contact_identifier) and the words (content). Opens the thread with that address if this workspace has never written to it, then queues the message. No record, no picker and no conversation id — reach for this to compose to somebody: "send an email to …", "email this person", "send them a text", "text this number". An email also takes subject and an optional content_html. NOTHING refuses an email with no subject and nothing supplies one, so it arrives blank in somebody's inbox — on 2026-09-20 a model asked to "send an email that says hi" sent exactly that. Write a subject for an email unless the person gave you words that are plainly the subject. An address that asked us to stop is refused. Name template_id to send a workspace template instead of writing the words: definition_key + row_id name the record whose values fill its {{placeholders}} (read under your own row wall and column mask). A placeholder the record has no value for refuses the send (400, naming it); an email template on a text, or the reverse, is refused; a subject or content you also send wins over the template's.
Access class: workspace.
Send request
Use the documented inputs to call this endpoint directly.
Request body
application/jsonrequiredResponses
the action's answer
{
"conversation": {
"account_identifier": "string",
"contact_identifier": "string",
"contact_name": "string",
"contact_role": "string",
"created_at": "string",
"id": 1,
"is_archived": true,
"is_muted": true,
"is_pinned": true,
"is_starred": true,
"last_message_at": "string",
"last_message_direction": "string",
"last_message_preview": "string",
"medium": "string",
"ownerAccountId": "",
"records": [
{
"definition_id": "",
"definition_key": "string",
"linked_at": "string",
"name": "string",
"row_id": "",
"status": "string",
"status_label": "string",
"status_tone": "string"
}
],
"subject": "string",
"unread_count": 1,
"visibility": "string"
},
"message": {
"call": {
"ai_summary": "string",
"answered_at": "string",
"duration_seconds": 1,
"ended_at": "string",
"provider": "string",
"recording_count": 1,
"recording_url": "string",
"result": "string",
"started_at": "string",
"transcript": "string"
},
"content": "string",
"content_html": "string",
"conversation_id": 1,
"delivered_at": "string",
"delivery": {
"attempts": 1,
"claimed_at": "string",
"claimed_by": "string",
"error": "string",
"next_attempt_at": "string",
"settled_at": "string",
"state": "string"
},
"direction": "string",
"external_id": "",
"id": 1,
"is_deleted": true,
"medium": "string",
"occurred_at": "string",
"parent_message_id": 1,
"read_at": "string",
"recorded_at": "string",
"sender_id": 1,
"sender_name": "string",
"sender_type": "string",
"status": "string",
"subject": "string",
"text": {
"error_code": "string",
"error_message": "string",
"media_count": 1,
"provider": "string",
"segment_count": 1
}
}
}a refusal: {"error": "<what a person needs to read>"}. 401 no credential, 402 the plan does not include this, 403 the seat does not, 404 the thing does not exist or is not yours to see.
{
"error": "string"
}