Skip to content
Get started

Polls

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.

Ephemeral Messages (Privacy Tier)

For regulated or sensitive conversations, opt in to the ephemeral messages tier by contacting your Linq support contact. When enabled, every message on the covered phone numbers is automatically given a fixed 24-hour retention window — after that window the platform permanently deletes the message from Linq storage. There is no per-message flag; ephemerality is applied automatically based on your configuration.

You can request it at two scopes:

ScopeEffect
Partner-wideEvery outbound and inbound message on every phone number under your account is retained for 24 hours, then deleted.
Per phone numberOnly the specified phone numbers have their messages auto-deleted. The rest follow the standard message-retention policy.

Behavioral differences vs the standard default:

AspectStandardEphemeral
RetentionRetained per the standard message-retention policyHard backstop: 24 hours from when the message is created
After expiryMessage stays retrievableMessage is permanently deleted — GET /v3/messages/{messageId} returns 404 and it no longer appears in GET /v3/chats/{chatId}/messages
Content on expiryN/AText, formatting, and attachment references are scrubbed; the message is gone, not blanked out
Cross-partner isolationEnforcedEnforced

How the 24-hour window works:

  • The window is fixed at 24 hours from message creation (created_at) and cannot be configured per message.
  • It mirrors the ephemeral attachments 1-day backstop, so a message and any media it carries expire together.
  • Expiry is delivery-independent — the clock starts when the message is created, not when it is delivered or read.

What you observe:

  • No expiry timestamp is exposed. API responses and webhook payloads do not include the deletion time. If you need it, compute created_at + 24h yourself.
  • No deletion webhook is sent. There is no message.deleted event — a message simply stops being retrievable once its window passes.
  • Delivery is unaffected. Ephemeral messages send, deliver, and fire the usual message.sent / message.received and status webhooks exactly like standard messages. Only retention changes.

When to choose ephemeral:

  • You have a compliance requirement that the platform must not retain message content beyond a short window.
  • The conversation is high-sensitivity (PHI, financial, identity verification) and you do not want it sitting in storage long-term.
  • Your application is the system of record — you capture what you need from the delivery webhook in real time and do not rely on reading message history back from Linq later.

Important: ephemeral applies in both directions — messages you send and messages received by the phone numbers in that scope. Because Linq can no longer return the message after 24 hours, persist anything you need to keep from the webhook payload at the time it is delivered.

Create and send a poll in a chat
client.chats.polls.create(stringchatID, PollCreateParams { poll } body, RequestOptionsoptions?): PollEnvelope { chat_id, created_at, message_id, 3 more }
POST/v3/chats/{chatId}/polls
ModelsExpand Collapse
Poll { options, total_voters }

Poll content — options and the aggregate voter count.

options: Array<Option>
can_be_edited: boolean
creator_handle: ChatHandle { id, handle, joined_at, 4 more }

The participant who added this option (poll creator for the initial options; whoever added later ones).

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"
option_id: string
formatuuid
text: string
voters: Array<Voter>

Participants who voted for this option (vote_count = voters.length).

handle: string
voted_at: string
formatdate-time
total_voters: number

Distinct participants across the whole poll (a voter picking two options counts once).

PollEnvelope { chat_id, created_at, message_id, 3 more }

Message-level envelope returned by every poll endpoint.

chat_id: string
formatuuid
created_at: string
formatdate-time
message_id: string

The poll-definition message’s ID — reference this poll by it.

formatuuid
poll: Poll { options, total_voters }

Poll content — options and the aggregate voter count.

options: Array<Option>
can_be_edited: boolean
creator_handle: ChatHandle { id, handle, joined_at, 4 more }

The participant who added this option (poll creator for the initial options; whoever added later ones).

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"
option_id: string
formatuuid
text: string
voters: Array<Voter>

Participants who voted for this option (vote_count = voters.length).

handle: string
voted_at: string
formatdate-time
total_voters: number

Distinct participants across the whole poll (a voter picking two options counts once).

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

Tapbacks/stickers on the whole poll (message part 0).

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

updated_at: string
formatdate-time