Send a message
Send a message to a phone number via iMessage or SMS. If the recipient has iMessage, the message is delivered as an iMessage (blue bubble). Otherwise, it falls back to SMS automatically.
POST/send-api-messageBearer token
Using a trial account?
Send to a verified destination from the shared line. Set up your trial before making your first request.
Request body
messagestringThe text content of the message. Required unless mediaAttachmentUrl or audioAttachmentUrl is supplied.
phonestringRequiredRecipient phone number. Accepts many formats — we normalize to E.164 (e.g. +15551234567).
More options 11 fields
lineIdstring (UUID v4)Optional sender line override. Use the lineId value returned from GET /get-lines. When omitted, messages are load balanced across available lines. Rejected on trial accounts — see Trial Accounts.
mediaAttachmentUrlstringURL to an image, video, or contact card attachment.
audioAttachmentUrlstringURL to an audio file sent as a voice memo.
enableAiVoiceMemobooleanWhen true, generates an AI voice memo from the message text using text-to-speech.
shouldAutoCreateContactbooleanDefaults to true. When enabled and a supported CRM is connected (HighLevel or HubSpot), automatically creates the contact in your CRM if they don't already exist.
firstNamestringFirst name to persist on the auto-created Project Blue contact for this recipient. Applies to accounts without a connected CRM (external/API source).
lastNamestringLast name to persist on the auto-created Project Blue contact for this recipient. Applies to accounts without a connected CRM (external/API source).
emailstringEmail address to persist on the auto-created Project Blue contact for this recipient. Applies to accounts without a connected CRM (external/API source).
customFieldsobjectArbitrary JSON metadata (e.g. order IDs, links) persisted on the auto-created contact and shown in the contact details panel in the Project Blue app. Plain object only; max 10,000 characters when JSON-serialized.
idempotencyKeystring1 to 200 characters. Values outside those bounds are silently ignored, not rejected. When omitted, the key defaults to your user id plus the destination plus the message text, so an identical retry within the hour is collapsed rather than sent twice.
effectstringiMessage-only send effect applied to this one message. Bubble: slam, loud, gentle, invisible-ink. Screen: confetti, balloons, hearts, lasers, fireworks, echo, spotlight, shooting-star, celebration. Invalid on SMS (400). Use sparingly.
The phone parameter is flexible — we accept formats like (555) 123-4567, 555.123.4567, +15551234567, and more. All numbers are normalized to E.164 format before sending.
When lineId is provided, we route through that line. If it is omitted, message sends continue to use default load balancing across your available lines.
iMessage-only send effects
Optional
effect applies to this one message and only works on iMessage. SMS destinations return 400. Bubble effects animate the bubble: slam, loud, gentle, invisible-ink. Screen effects take over the recipient's screen: confetti, balloons, hearts, lasers, fireworks, echo, spotlight, shooting-star, celebration. Use sparingly. GET /get-effects returns the same list.Identical sends are collapsed for an hour
With no
idempotencyKey, the key defaults to your user id plus the destination plus the message text. Sending the same text to the same number twice within the hour returns 200 with deduped: true and does not send a second message. This is the usual reason a first integration looks like it succeeded but nothing arrived on the retry — change the text, or pass a distinct idempotencyKey, when a repeat is intentional.A replay returns status: "done" when the original send finished, or status: "processing" with messageType and devicePhoneNumber still null while it is in flight. Both carry deduped: true; a first-time send never does.