VocalDocscontracts 1.65.0

Send a message

POST /v1/messages

PropertyValue
Operationcreate_message
GroupMessages
Scopemessages:write
Route classcontrol
IdempotencyIdempotency-Key required: a retry with the same key replays the first answer
AuditAudited channels.message.send (mutation)
Released in1.60.0
Phase 0 hostServed (the hosted api pins 1.65.0)

The send action (1.60.0; channels.md section 2): one message to one recipient over one Connection through one of its send tools. In 1.60.0 every request is refused with capability_not_available and nothing is sent. From 1.61.0 (roadmap slice 2.15) the route checks the recipient's consent on the tool's channel for the Organization and for the Connection as sender, the rule of check_consent, and refuses an opted-out recipient with 422 contact_opted_out, one detail whose reason is a ConsentCheckReason, queuing nothing; otherwise it records the Message queued and hands it to the exec role as a leased action task, which checks the consent again before it sends (check_send_consent). Quiet hours defer a Message (deferred), never drop it. The Audit event names the Connection and the tool, never the recipient or the text.

Request

Set VOCAL_API to the base URL of your API and VOCAL_API_KEY to an API key with the messages:write scope (Authentication and keys). Replace each placeholder, such as agt_... or <name>, with your own value.

curl -X POST "$VOCAL_API/v1/messages" \
  -H "Authorization: Bearer $VOCAL_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "con_...",
    "tool": "<tool>",
    "to": "<to>",
    "body": "<body>"
  }'

Parameters

NameInTypeRequiredDescription
idempotency-keyheaderstringyesA client-chosen key, kept 24 hours per Organization, environment and route. A replay returns the stored response.

Request body

Content type application/json, required: MessageCreateRequest.

FieldTypeRequiredDescription
bodystringyes
connection_idConnectionIdyes
related_call_idCallIdno
subjectstringno
tostringyes
toolUpstreamToolNameyesA send tool of the Connection's Connector.

Responses

StatusContent typeShapeError codes
201application/jsonMessage
400application/jsonErrorEnvelopeinvalid_request
401application/jsonErrorEnvelopeunauthenticated
403application/jsonErrorEnvelopeforbidden, org_suspended
409application/jsonErrorEnvelopeconnection_revoked, idempotency_in_progress, idempotency_key_reused
422application/jsonErrorEnvelopevalidation_failed, capability_not_available, contact_opted_out
429application/jsonErrorEnveloperate_limited
500application/jsonErrorEnvelopeinternal_error

Fields of the 201 answer

The shape is Message.

FieldTypeRequiredDescription
actionMessagingActionyes
channelMessageChannelyes
connection_idConnectionIdyes
contentMessageContent or nullyesThe recipient and text: answered by the single read, an audited content read; null in a list.
created_atTimestampyes
deferred_untilTimestamp or nullyesWhen a deferred Message is sent; null otherwise.
delivered_atTimestamp or nullyes
directionMessageDirectionyes
environmentEnvironmentyes
error_codeToolErrorCode or nullyes
idMessageIdyes
notification_rule_idNotificationRuleId or nullyes
object"message"yes
organization_idOrganizationIdyes
related_call_idCallId or nullyes
run_idRunId or nullyes
segmentsinteger or nullyesThe SMS segments counted; null for other channels.
sent_atTimestamp or nullyes
statusMessageStatusyes
thread_idnullyesReserved for conversation Channels; always null.
toolUpstreamToolNameyes
trigger_event_idTriggerEventId or nullyes
updated_atTimestampyes
vendor_message_idstring or nullyes