Skip to content
V2 (Legacy) API ReferenceGet started

Chats

Create a new chat
client.chats.create(ChatCreateParams { from, message, to } body, RequestOptionsoptions?): ChatCreateResponse { chat }
POST/v3/chats
List all chats
client.chats.listChats(ChatListChatsParams { cursor, from, limit, to } query?, RequestOptionsoptions?): ListChatsPagination<Chat { id, created_at, display_name, 6 more } >
GET/v3/chats
Get a chat by ID
client.chats.retrieve(stringchatID, RequestOptionsoptions?): Chat { id, created_at, display_name, 6 more }
GET/v3/chats/{chatId}
Update a chat
client.chats.update(stringchatID, ChatUpdateParams { display_name, group_chat_icon } body, RequestOptionsoptions?): ChatUpdateResponse { chat_id, status }
PUT/v3/chats/{chatId}
Mark chat as read
client.chats.markAsRead(stringchatID, RequestOptionsoptions?): void
POST/v3/chats/{chatId}/read
Leave a group chat
client.chats.leaveChat(stringchatID, RequestOptionsoptions?): ChatLeaveChatResponse { message, status, trace_id }
POST/v3/chats/{chatId}/leave
Share your contact card with a chat
client.chats.shareContactCard(stringchatID, RequestOptionsoptions?): void
POST/v3/chats/{chatId}/share_contact_card
Send a voice memo to a chat
client.chats.sendVoicememo(stringchatID, ChatSendVoicememoParams { attachment_id, voice_memo_url } body, RequestOptionsoptions?): ChatSendVoicememoResponse { voice_memo }
POST/v3/chats/{chatId}/voicememo
ModelsExpand Collapse
Chat { id, created_at, display_name, 6 more }
id: string

Unique identifier for the chat

formatuuid
created_at: string

When the chat was created

formatdate-time
display_name: string | null

Display name for the chat. Defaults to a comma-separated list of recipient handles. Can be updated for group chats.

handles: Array<ChatHandle { id, handle, joined_at, 4 more } >

List of chat participants with full handle details. Always contains at least two handles (your phone number and the other participant).

id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_archived: boolean

Whether the chat is archived

is_group: boolean

Whether this is a group chat

updated_at: string

When the chat was last updated

formatdate-time
health_score?: HealthScore | null

[BETA] Health assessment for a chat. Higher score is healthier. null when a score isnโ€™t available yet. Scoring may change during beta.

reason: string

Short summary of whatโ€™s affecting the score. Empty when the score is 100.

score: number

Health score from 0 to 100. Higher is healthier.

minimum0
maximum100
updated_at: string

When this health score was last computed.

formatdate-time
service?: ServiceType | null

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
MediaPart { type, attachment_id, url }
type: "media"

Indicates this is a media attachment part

attachment_id?: string

Reference to a file pre-uploaded via POST /v3/attachments (optional). The file is already stored, so sends using this ID skip the download step โ€” useful when sending the same file to many recipients.

Either url or attachment_id must be provided, but not both.

formatuuid
url?: string

Any publicly accessible HTTPS URL to the media file. The server downloads and sends the file automatically โ€” no pre-upload step required.

Size limit: 10MB maximum for URL-based downloads. For larger files (up to 100MB), use the pre-upload flow: POST /v3/attachments to get a presigned URL, upload directly, then reference by attachment_id.

Requirements:

  • URL must use HTTPS
  • File content must be a supported format (the server validates the actual file content)

Supported formats:

  • Images: .jpg, .jpeg, .png, .gif, .heic, .heif, .tif, .tiff, .bmp
  • Videos: .mp4, .mov, .m4v, .mpeg, .mpg, .3gp
  • Audio: .m4a, .mp3, .aac, .caf, .wav, .aiff, .amr
  • Documents: .pdf, .txt, .rtf, .csv, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .pages, .numbers, .key, .epub, .zip, .html, .htm
  • Contact & Calendar: .vcf, .ics

Tip: Audio sent here appears as a regular file attachment. To send audio as an iMessage voice memo bubble (with inline playback), use /v3/chats/{chatId}/voicememo. For repeated sends of the same file, use attachment_id to avoid redundant downloads.

Either url or attachment_id must be provided, but not both.

formaturi
MessageContent { parts, effect, idempotency_key, 2 more }

Message content container. Groups all message-related fields together, separating the โ€œwhatโ€ (message content) from the โ€œwhereโ€ (routing fields like from/to).

parts: Array<TextPart { type, value, text_decorations } | MediaPart { type, attachment_id, url } | LinkPart { type, value } >

Array of message parts. Each part can be text, media, or link. Parts are displayed in order. Text and media can be mixed freely, but a link part must be the only part in the message.

Rich Link Previews:

  • Use a link part to send a URL with a rich preview card
  • A link part must be the only part in the message
  • To send a URL as plain text (no preview), use a text part instead

Supported Media:

  • Images: .jpg, .jpeg, .png, .gif, .heic, .heif, .tif, .tiff, .bmp
  • Videos: .mp4, .mov, .m4v, .mpeg, .mpg, .3gp
  • Audio: .m4a, .mp3, .aac, .caf, .wav, .aiff, .amr
  • Documents: .pdf, .txt, .rtf, .csv, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .pages, .numbers, .key, .epub, .zip, .html, .htm
  • Contact & Calendar: .vcf, .ics

Audio:

  • Audio files (.m4a, .mp3, .aac, .caf, .wav, .aiff, .amr) are fully supported as media parts
  • To send audio as an iMessage voice memo bubble (inline playback UI), use the dedicated /v3/chats/{chatId}/voicememo endpoint instead

Validation Rules:

  • A link part must be the only part in the message. It cannot be combined with text or media parts.
  • Consecutive text parts are not allowed. Text parts must be separated by media parts. For example, [text, text] is invalid, but [text, media, text] is valid.
  • Maximum of 100 parts total.
  • Media parts using a public url (downloaded by the server on send) are capped at 40. Parts using attachment_id or presigned URLs are exempt from this sub-limit. For bulk media sends exceeding 40 files, pre-upload via POST /v3/attachments and reference by attachment_id or download_url.
One of the following:
TextPart { type, value, text_decorations }
type: "text"

Indicates this is a text message part

value: string

The text content of the message. This value is sent as-is with no parsing or transformation โ€” Markdown syntax will be delivered as plain text. Use text_decorations to apply inline formatting and animations (iMessage only).

minLength1
maxLength10000
text_decorations?: Array<TextDecoration { range, animation, style } >

Optional array of text decorations applied to character ranges in the value field (iMessage only).

Each decoration specifies a character range [start, end) and exactly one of style or animation.

Styles: bold, italic, strikethrough, underline Animations: big, small, shake, nod, explode, ripple, bloom, jitter

Style ranges may overlap (e.g. bold + italic on the same text), but animation ranges must not overlap with other animations or styles.

Characters are measured as UTF-16 code units. Most characters count as 1; some emoji count as 2.

Note: Text decorations only render for iMessage recipients. For SMS/RCS, text decorations are not applied.

range: Array<number>

Character range [start, end) in the value string where the decoration applies. start is inclusive, end is exclusive. Characters are measured as UTF-16 code units. Most characters count as 1; some emoji count as 2.

animation?: "big" | "small" | "shake" | 5 more

Animated text effect to apply. Mutually exclusive with style.

One of the following:
"big"
"small"
"shake"
"nod"
"explode"
"ripple"
"bloom"
"jitter"
style?: "bold" | "italic" | "strikethrough" | "underline"

Text style to apply. Mutually exclusive with animation.

One of the following:
"bold"
"italic"
"strikethrough"
"underline"
MediaPart { type, attachment_id, url }
type: "media"

Indicates this is a media attachment part

attachment_id?: string

Reference to a file pre-uploaded via POST /v3/attachments (optional). The file is already stored, so sends using this ID skip the download step โ€” useful when sending the same file to many recipients.

Either url or attachment_id must be provided, but not both.

formatuuid
url?: string

Any publicly accessible HTTPS URL to the media file. The server downloads and sends the file automatically โ€” no pre-upload step required.

Size limit: 10MB maximum for URL-based downloads. For larger files (up to 100MB), use the pre-upload flow: POST /v3/attachments to get a presigned URL, upload directly, then reference by attachment_id.

Requirements:

  • URL must use HTTPS
  • File content must be a supported format (the server validates the actual file content)

Supported formats:

  • Images: .jpg, .jpeg, .png, .gif, .heic, .heif, .tif, .tiff, .bmp
  • Videos: .mp4, .mov, .m4v, .mpeg, .mpg, .3gp
  • Audio: .m4a, .mp3, .aac, .caf, .wav, .aiff, .amr
  • Documents: .pdf, .txt, .rtf, .csv, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .pages, .numbers, .key, .epub, .zip, .html, .htm
  • Contact & Calendar: .vcf, .ics

Tip: Audio sent here appears as a regular file attachment. To send audio as an iMessage voice memo bubble (with inline playback), use /v3/chats/{chatId}/voicememo. For repeated sends of the same file, use attachment_id to avoid redundant downloads.

Either url or attachment_id must be provided, but not both.

formaturi
effect?: MessageEffect { name, type }

iMessage effect to apply to this message (screen or bubble effect)

name?: string

Name of the effect. Common values:

  • Screen effects: confetti, fireworks, lasers, sparkles, celebration, hearts, love, balloons, happy_birthday, echo, spotlight
  • Bubble effects: slam, loud, gentle, invisible
type?: "screen" | "bubble"

Type of effect

One of the following:
"screen"
"bubble"
idempotency_key?: string

Optional idempotency key for this message. Use this to prevent duplicate sends of the same message.

maxLength255
preferred_service?: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
reply_to?: ReplyTo { message_id, part_index }

Reply to another message to create a threaded conversation

message_id: string

The ID of the message to reply to

formatuuid
part_index?: number

The specific message part to reply to (0-based index). Defaults to 0 (first part) if not provided. Use this when replying to a specific part of a multipart message.

formatint32
minimum0
TextPart { type, value, text_decorations }
type: "text"

Indicates this is a text message part

value: string

The text content of the message. This value is sent as-is with no parsing or transformation โ€” Markdown syntax will be delivered as plain text. Use text_decorations to apply inline formatting and animations (iMessage only).

minLength1
maxLength10000
text_decorations?: Array<TextDecoration { range, animation, style } >

Optional array of text decorations applied to character ranges in the value field (iMessage only).

Each decoration specifies a character range [start, end) and exactly one of style or animation.

Styles: bold, italic, strikethrough, underline Animations: big, small, shake, nod, explode, ripple, bloom, jitter

Style ranges may overlap (e.g. bold + italic on the same text), but animation ranges must not overlap with other animations or styles.

Characters are measured as UTF-16 code units. Most characters count as 1; some emoji count as 2.

Note: Text decorations only render for iMessage recipients. For SMS/RCS, text decorations are not applied.

range: Array<number>

Character range [start, end) in the value string where the decoration applies. start is inclusive, end is exclusive. Characters are measured as UTF-16 code units. Most characters count as 1; some emoji count as 2.

animation?: "big" | "small" | "shake" | 5 more

Animated text effect to apply. Mutually exclusive with style.

One of the following:
"big"
"small"
"shake"
"nod"
"explode"
"ripple"
"bloom"
"jitter"
style?: "bold" | "italic" | "strikethrough" | "underline"

Text style to apply. Mutually exclusive with animation.

One of the following:
"bold"
"italic"
"strikethrough"
"underline"
ChatCreateResponse { chat }

Response for creating a new chat with an initial message

chat: Chat { id, display_name, handles, 4 more }
id: string

Unique identifier for the created chat (UUID)

formatuuid
display_name: string | null

Display name for the chat. Defaults to a comma-separated list of recipient handles. Can be updated for group chats.

handles: Array<ChatHandle { id, handle, joined_at, 4 more } >

List of participants in the chat. Always contains at least two handles (your phone number and the other participant).

id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_group: boolean

Whether this is a group chat

message: SentMessage { id, created_at, delivery_status, 9 more }

A message that was sent (used in CreateChat and SendMessage responses)

id: string

Message identifier (UUID)

formatuuid
created_at: string

When the message was created

formatdate-time
delivery_status: "pending" | "queued" | "sent" | 2 more

Current delivery status of a message

One of the following:
"pending"
"queued"
"sent"
"delivered"
"failed"
is_read: boolean

Whether the message has been read

parts: Array<TextPartResponse { reactions, type, value, text_decorations } | MediaPartResponse { id, filename, mime_type, 4 more } | LinkPartResponse { reactions, type, value } >

Message parts in order (text, media, and link)

One of the following:
TextPartResponse { reactions, type, value, text_decorations }

A text message part

reactions: Array<Reaction { handle, is_me, type, 2 more } > | null

Reactions on this message part

handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

type: "text"

Indicates this is a text message part

value: string

The text content

text_decorations?: Array<TextDecoration { range, animation, style } > | null

Text decorations applied to character ranges in the value

range: Array<number>

Character range [start, end) in the value string where the decoration applies. start is inclusive, end is exclusive. Characters are measured as UTF-16 code units. Most characters count as 1; some emoji count as 2.

animation?: "big" | "small" | "shake" | 5 more

Animated text effect to apply. Mutually exclusive with style.

One of the following:
"big"
"small"
"shake"
"nod"
"explode"
"ripple"
"bloom"
"jitter"
style?: "bold" | "italic" | "strikethrough" | "underline"

Text style to apply. Mutually exclusive with animation.

One of the following:
"bold"
"italic"
"strikethrough"
"underline"
MediaPartResponse { id, filename, mime_type, 4 more }

A media attachment part

id: string

Unique attachment identifier

formatuuid
filename: string

Original filename

mime_type: string

MIME type of the file

reactions: Array<Reaction { handle, is_me, type, 2 more } > | null

Reactions on this message part

handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

size_bytes: number

File size in bytes

type: "media"

Indicates this is a media attachment part

url: string

Presigned URL for downloading the attachment (expires in 1 hour).

formaturi
handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

sent_at: string | null

When the message was actually sent (null if still queued)

formatdate-time
delivered_at?: string | null

When the message was delivered

formatdate-time
effect?: MessageEffect { name, type } | null

iMessage effect applied to a message (screen or bubble effect)

name?: string

Name of the effect. Common values:

  • Screen effects: confetti, fireworks, lasers, sparkles, celebration, hearts, love, balloons, happy_birthday, echo, spotlight
  • Bubble effects: slam, loud, gentle, invisible
type?: "screen" | "bubble"

Type of effect

One of the following:
"screen"
"bubble"
from_handle?: ChatHandle { id, handle, joined_at, 4 more } | null

The sender of this message as a full handle object

id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
preferred_service?: ServiceType | null

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
reply_to?: ReplyTo { message_id, part_index } | null

Indicates this message is a threaded reply to another message

message_id: string

The ID of the message to reply to

formatuuid
part_index?: number

The specific message part to reply to (0-based index). Defaults to 0 (first part) if not provided. Use this when replying to a specific part of a multipart message.

formatint32
minimum0
service?: ServiceType | null

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
health_score?: HealthScore | null

[BETA] Health assessment for a chat. Higher score is healthier. null when a score isnโ€™t available yet. Scoring may change during beta.

reason: string

Short summary of whatโ€™s affecting the score. Empty when the score is 100.

score: number

Health score from 0 to 100. Higher is healthier.

minimum0
maximum100
updated_at: string

When this health score was last computed.

formatdate-time
ChatUpdateResponse { chat_id, status }
chat_id?: string
formatuuid
status?: string
ChatLeaveChatResponse { message, status, trace_id }
message?: string
status?: string
trace_id?: string
ChatSendVoicememoResponse { voice_memo }

Response for sending a voice memo to a chat

voice_memo: VoiceMemo { id, chat, created_at, 5 more }
id: string

Message identifier

formatuuid
chat: Chat { id, handles, is_active, 2 more }
id: string

Chat identifier

formatuuid
handles: Array<ChatHandle { id, handle, joined_at, 4 more } >

Chat participants

id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_active: boolean

Whether the chat is active

is_group: boolean

Whether this is a group chat

service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
created_at: string

When the voice memo was created

formatdate-time
from: string

Sender phone number

status: string

Current delivery status

to: Array<string>

Recipient handles (phone numbers or email addresses)

voice_memo: VoiceMemo { id, filename, mime_type, 3 more }
id: string

Attachment identifier

formatuuid
filename: string

Original filename

mime_type: string

Audio MIME type

size_bytes: number

File size in bytes

url: string

CDN URL for downloading the voice memo

formaturi
duration_ms?: number | null

Duration in milliseconds

service?: ServiceType | null

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"

ChatsParticipants

A Chat is a conversation thread with one or more participants.

To begin a chat, you must create a Chat with at least one recipient handle. Including multiple handles creates a group chat.

When creating a chat, the from field specifies which of your authorized phone numbers the message originates from. Your authentication token grants access to one or more phone numbers, but the from field determines the actual sender.

Handle Format:

  • Handles can be phone numbers or email addresses
  • Phone numbers MUST be in E.164 format (starting with +)
  • Phone format: +[country code][subscriber number]
  • Example phone: +12223334444 (US), +442071234567 (UK), +81312345678 (Japan)
  • Example email: [email protected]
  • No spaces, dashes, or parentheses in phone numbers
Add a participant to a chat
client.chats.participants.add(stringchatID, ParticipantAddParams { handle } body, RequestOptionsoptions?): ParticipantAddResponse { message, status, trace_id }
POST/v3/chats/{chatId}/participants
Remove a participant from a chat
client.chats.participants.remove(stringchatID, ParticipantRemoveParams { handle } body, RequestOptionsoptions?): ParticipantRemoveResponse { message, status, trace_id }
DELETE/v3/chats/{chatId}/participants
ModelsExpand Collapse
ParticipantAddResponse { message, status, trace_id }
message?: string
status?: string
trace_id?: string
ParticipantRemoveResponse { message, status, trace_id }
message?: string
status?: string
trace_id?: string

ChatsTyping

A Chat is a conversation thread with one or more participants.

To begin a chat, you must create a Chat with at least one recipient handle. Including multiple handles creates a group chat.

When creating a chat, the from field specifies which of your authorized phone numbers the message originates from. Your authentication token grants access to one or more phone numbers, but the from field determines the actual sender.

Handle Format:

  • Handles can be phone numbers or email addresses
  • Phone numbers MUST be in E.164 format (starting with +)
  • Phone format: +[country code][subscriber number]
  • Example phone: +12223334444 (US), +442071234567 (UK), +81312345678 (Japan)
  • Example email: [email protected]
  • No spaces, dashes, or parentheses in phone numbers
Start typing indicator
client.chats.typing.start(stringchatID, RequestOptionsoptions?): void
POST/v3/chats/{chatId}/typing
Stop typing indicator
client.chats.typing.stop(stringchatID, RequestOptionsoptions?): void
DELETE/v3/chats/{chatId}/typing

ChatsMessages

Messages are individual communications within a chat thread.

Messages can include text, media attachments, rich link previews, special effects (like confetti or fireworks), and reactions. All messages are associated with a specific chat and sent from a phone number you own.

Messages support delivery status tracking, read receipts, and editing capabilities.

Send a URL as a link part to deliver it with a rich preview card showing the pageโ€™s title, description, and image (when available). A link part must be the only part in the message โ€” it cannot be combined with text or media parts. To send a URL without a preview card, include it in a text part instead.

Limitations:

  • A link part cannot be combined with other parts in the same message.
  • Maximum URL length: 2,048 characters.
Send a message to an existing chat
client.chats.messages.send(stringchatID, MessageSendParams { message } body, RequestOptionsoptions?): MessageSendResponse { chat_id, message }
POST/v3/chats/{chatId}/messages
Get messages from a chat
client.chats.messages.list(stringchatID, MessageListParams { cursor, limit } query?, RequestOptionsoptions?): ListMessagesPagination<Message { id, chat_id, created_at, 14 more } >
GET/v3/chats/{chatId}/messages
ModelsExpand Collapse
SentMessage { id, created_at, delivery_status, 9 more }

A message that was sent (used in CreateChat and SendMessage responses)

id: string

Message identifier (UUID)

formatuuid
created_at: string

When the message was created

formatdate-time
delivery_status: "pending" | "queued" | "sent" | 2 more

Current delivery status of a message

One of the following:
"pending"
"queued"
"sent"
"delivered"
"failed"
is_read: boolean

Whether the message has been read

parts: Array<TextPartResponse { reactions, type, value, text_decorations } | MediaPartResponse { id, filename, mime_type, 4 more } | LinkPartResponse { reactions, type, value } >

Message parts in order (text, media, and link)

One of the following:
TextPartResponse { reactions, type, value, text_decorations }

A text message part

reactions: Array<Reaction { handle, is_me, type, 2 more } > | null

Reactions on this message part

handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

type: "text"

Indicates this is a text message part

value: string

The text content

text_decorations?: Array<TextDecoration { range, animation, style } > | null

Text decorations applied to character ranges in the value

range: Array<number>

Character range [start, end) in the value string where the decoration applies. start is inclusive, end is exclusive. Characters are measured as UTF-16 code units. Most characters count as 1; some emoji count as 2.

animation?: "big" | "small" | "shake" | 5 more

Animated text effect to apply. Mutually exclusive with style.

One of the following:
"big"
"small"
"shake"
"nod"
"explode"
"ripple"
"bloom"
"jitter"
style?: "bold" | "italic" | "strikethrough" | "underline"

Text style to apply. Mutually exclusive with animation.

One of the following:
"bold"
"italic"
"strikethrough"
"underline"
MediaPartResponse { id, filename, mime_type, 4 more }

A media attachment part

id: string

Unique attachment identifier

formatuuid
filename: string

Original filename

mime_type: string

MIME type of the file

reactions: Array<Reaction { handle, is_me, type, 2 more } > | null

Reactions on this message part

handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

size_bytes: number

File size in bytes

type: "media"

Indicates this is a media attachment part

url: string

Presigned URL for downloading the attachment (expires in 1 hour).

formaturi
handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

sent_at: string | null

When the message was actually sent (null if still queued)

formatdate-time
delivered_at?: string | null

When the message was delivered

formatdate-time
effect?: MessageEffect { name, type } | null

iMessage effect applied to a message (screen or bubble effect)

name?: string

Name of the effect. Common values:

  • Screen effects: confetti, fireworks, lasers, sparkles, celebration, hearts, love, balloons, happy_birthday, echo, spotlight
  • Bubble effects: slam, loud, gentle, invisible
type?: "screen" | "bubble"

Type of effect

One of the following:
"screen"
"bubble"
from_handle?: ChatHandle { id, handle, joined_at, 4 more } | null

The sender of this message as a full handle object

id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
preferred_service?: ServiceType | null

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
reply_to?: ReplyTo { message_id, part_index } | null

Indicates this message is a threaded reply to another message

message_id: string

The ID of the message to reply to

formatuuid
part_index?: number

The specific message part to reply to (0-based index). Defaults to 0 (first part) if not provided. Use this when replying to a specific part of a multipart message.

formatint32
minimum0
service?: ServiceType | null

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
MessageSendResponse { chat_id, message }

Response for sending a message to a chat

chat_id: string

Unique identifier of the chat this message was sent to

formatuuid
message: SentMessage { id, created_at, delivery_status, 9 more }

A message that was sent (used in CreateChat and SendMessage responses)

id: string

Message identifier (UUID)

formatuuid
created_at: string

When the message was created

formatdate-time
delivery_status: "pending" | "queued" | "sent" | 2 more

Current delivery status of a message

One of the following:
"pending"
"queued"
"sent"
"delivered"
"failed"
is_read: boolean

Whether the message has been read

parts: Array<TextPartResponse { reactions, type, value, text_decorations } | MediaPartResponse { id, filename, mime_type, 4 more } | LinkPartResponse { reactions, type, value } >

Message parts in order (text, media, and link)

One of the following:
TextPartResponse { reactions, type, value, text_decorations }

A text message part

reactions: Array<Reaction { handle, is_me, type, 2 more } > | null

Reactions on this message part

handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

type: "text"

Indicates this is a text message part

value: string

The text content

text_decorations?: Array<TextDecoration { range, animation, style } > | null

Text decorations applied to character ranges in the value

range: Array<number>

Character range [start, end) in the value string where the decoration applies. start is inclusive, end is exclusive. Characters are measured as UTF-16 code units. Most characters count as 1; some emoji count as 2.

animation?: "big" | "small" | "shake" | 5 more

Animated text effect to apply. Mutually exclusive with style.

One of the following:
"big"
"small"
"shake"
"nod"
"explode"
"ripple"
"bloom"
"jitter"
style?: "bold" | "italic" | "strikethrough" | "underline"

Text style to apply. Mutually exclusive with animation.

One of the following:
"bold"
"italic"
"strikethrough"
"underline"
MediaPartResponse { id, filename, mime_type, 4 more }

A media attachment part

id: string

Unique attachment identifier

formatuuid
filename: string

Original filename

mime_type: string

MIME type of the file

reactions: Array<Reaction { handle, is_me, type, 2 more } > | null

Reactions on this message part

handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

size_bytes: number

File size in bytes

type: "media"

Indicates this is a media attachment part

url: string

Presigned URL for downloading the attachment (expires in 1 hour).

formaturi
handle: ChatHandle { id, handle, joined_at, 4 more }
id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
is_me: boolean

Whether this reaction is from the current user

Type of reaction. Standard iMessage tapbacks are love, like, dislike, laugh, emphasize, question. Custom emoji reactions have type โ€œcustomโ€ with the actual emoji in the custom_emoji field. Sticker reactions have type โ€œstickerโ€ with sticker attachment details in the sticker field.

One of the following:
"love"
"like"
"dislike"
"laugh"
"emphasize"
"question"
"custom"
"sticker"
custom_emoji?: string | null

Custom emoji if type is โ€œcustomโ€, null otherwise

sticker?: Sticker | null

Sticker attachment details when reaction_type is โ€œstickerโ€. Null for non-sticker reactions.

file_name?: string

Filename of the sticker

height?: number

Sticker image height in pixels

mime_type?: string

MIME type of the sticker image

url?: string

Presigned URL for downloading the sticker image (expires in 1 hour).

formaturi
width?: number

Sticker image width in pixels

sent_at: string | null

When the message was actually sent (null if still queued)

formatdate-time
delivered_at?: string | null

When the message was delivered

formatdate-time
effect?: MessageEffect { name, type } | null

iMessage effect applied to a message (screen or bubble effect)

name?: string

Name of the effect. Common values:

  • Screen effects: confetti, fireworks, lasers, sparkles, celebration, hearts, love, balloons, happy_birthday, echo, spotlight
  • Bubble effects: slam, loud, gentle, invisible
type?: "screen" | "bubble"

Type of effect

One of the following:
"screen"
"bubble"
from_handle?: ChatHandle { id, handle, joined_at, 4 more } | null

The sender of this message as a full handle object

id: string

Unique identifier for this handle

formatuuid
handle: string

Phone number (E.164) or email address of the participant

joined_at: string

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me?: boolean | null

Whether this handle belongs to the sender (your phone number)

left_at?: string | null

When they left (if applicable)

formatdate-time
status?: "active" | "left" | "removed" | null

Participant status

One of the following:
"active"
"left"
"removed"
preferred_service?: ServiceType | null

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
reply_to?: ReplyTo { message_id, part_index } | null

Indicates this message is a threaded reply to another message

message_id: string

The ID of the message to reply to

formatuuid
part_index?: number

The specific message part to reply to (0-based index). Defaults to 0 (first part) if not provided. Use this when replying to a specific part of a multipart message.

formatint32
minimum0
service?: ServiceType | null

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"