Skip to content
V2 (Legacy) API ReferenceGet started

Create a new chat

chats.create(ChatCreateParams**kwargs) -> ChatCreateResponse
POST/v3/chats

Create a new chat with specified participants and send an initial message. The initial message is required when creating a chat.

Message Effects

You can add iMessage effects to make your messages more expressive. Effects are optional and can be either screen effects (full-screen animations) or bubble effects (message bubble animations).

Screen Effects: confetti, fireworks, lasers, sparkles, celebration, hearts, love, balloons, happy_birthday, echo, spotlight

Bubble Effects: slam, loud, gentle, invisible

Only one effect type can be applied per message.

Inline Text Decorations (iMessage only)

Use the text_decorations array on a text part to apply styling and animations to character ranges.

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

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

{
  "type": "text",
  "value": "Hello world",
  "text_decorations": [
    { "range": [0, 5], "style": "bold" },
    { "range": [6, 11], "animation": "shake" }
  ]
}

Note: Style ranges (bold, italic, etc.) may overlap, but animation ranges must not overlap with other animations or styles. Text decorations only render for iMessage recipients. For SMS/RCS, text decorations are not applied.

To protect sender deliverability, the first outbound message of a new chat cannot be a link. The request is rejected with 400 (error code 1005) when:

  • The message contains a link part (explicit rich-preview link), or
  • Any text part contains a URL.

This rule applies only to POST /v3/chats. Follow-up messages on an existing chat (POST /v3/chats/{chatId}/messages) are not subject to this restriction.

ParametersExpand Collapse
from_: str

Sender phone number in E.164 format. Must be a phone number that the authenticated partner has permission to send from.

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

parts: List[Part]

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:
class TextPart: โ€ฆ
type: Literal["text"]

Indicates this is a text message part

value: str

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: Optional[List[TextDecoration]]

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: List[int]

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: Optional[Literal["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: Optional[Literal["bold", "italic", "strikethrough", "underline"]]

Text style to apply. Mutually exclusive with animation.

One of the following:
"bold"
"italic"
"strikethrough"
"underline"
class MediaPart: โ€ฆ
type: Literal["media"]

Indicates this is a media attachment part

attachment_id: Optional[str]

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: Optional[str]

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: Optional[MessageEffect]

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

name: Optional[str]

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: Optional[Literal["screen", "bubble"]]

Type of effect

One of the following:
"screen"
"bubble"
idempotency_key: Optional[str]

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

maxLength255
preferred_service: Optional[ServiceType]

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
reply_to: Optional[ReplyTo]

Reply to another message to create a threaded conversation

message_id: str

The ID of the message to reply to

formatuuid
part_index: Optional[int]

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
to: Sequence[str]

Array of recipient handles (phone numbers in E.164 format or email addresses). For individual chats, provide one recipient. For group chats, provide multiple.

ReturnsExpand Collapse
class ChatCreateResponse: โ€ฆ

Response for creating a new chat with an initial message

chat: Chat
id: str

Unique identifier for the created chat (UUID)

formatuuid
display_name: Optional[str]

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

handles: List[ChatHandle]

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

id: str

Unique identifier for this handle

formatuuid
handle: str

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

joined_at: datetime

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me: Optional[bool]

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

left_at: Optional[datetime]

When they left (if applicable)

formatdate-time
status: Optional[Literal["active", "left", "removed"]]

Participant status

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

Whether this is a group chat

message: SentMessage

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

id: str

Message identifier (UUID)

formatuuid
created_at: datetime

When the message was created

formatdate-time
delivery_status: Literal["pending", "queued", "sent", 2 more]

Current delivery status of a message

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

Whether the message has been read

parts: List[Part]

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

One of the following:
class TextPartResponse: โ€ฆ

A text message part

reactions: Optional[List[Reaction]]

Reactions on this message part

handle: ChatHandle
id: str

Unique identifier for this handle

formatuuid
handle: str

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

joined_at: datetime

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me: Optional[bool]

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

left_at: Optional[datetime]

When they left (if applicable)

formatdate-time
status: Optional[Literal["active", "left", "removed"]]

Participant status

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

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: Optional[str]

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

sticker: Optional[Sticker]

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

file_name: Optional[str]

Filename of the sticker

height: Optional[int]

Sticker image height in pixels

mime_type: Optional[str]

MIME type of the sticker image

url: Optional[str]

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

formaturi
width: Optional[int]

Sticker image width in pixels

type: Literal["text"]

Indicates this is a text message part

value: str

The text content

text_decorations: Optional[List[TextDecoration]]

Text decorations applied to character ranges in the value

range: List[int]

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: Optional[Literal["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: Optional[Literal["bold", "italic", "strikethrough", "underline"]]

Text style to apply. Mutually exclusive with animation.

One of the following:
"bold"
"italic"
"strikethrough"
"underline"
class MediaPartResponse: โ€ฆ

A media attachment part

id: str

Unique attachment identifier

formatuuid
filename: str

Original filename

mime_type: str

MIME type of the file

reactions: Optional[List[Reaction]]

Reactions on this message part

handle: ChatHandle
id: str

Unique identifier for this handle

formatuuid
handle: str

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

joined_at: datetime

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me: Optional[bool]

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

left_at: Optional[datetime]

When they left (if applicable)

formatdate-time
status: Optional[Literal["active", "left", "removed"]]

Participant status

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

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: Optional[str]

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

sticker: Optional[Sticker]

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

file_name: Optional[str]

Filename of the sticker

height: Optional[int]

Sticker image height in pixels

mime_type: Optional[str]

MIME type of the sticker image

url: Optional[str]

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

formaturi
width: Optional[int]

Sticker image width in pixels

size_bytes: int

File size in bytes

type: Literal["media"]

Indicates this is a media attachment part

url: str

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

formaturi
handle: ChatHandle
id: str

Unique identifier for this handle

formatuuid
handle: str

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

joined_at: datetime

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me: Optional[bool]

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

left_at: Optional[datetime]

When they left (if applicable)

formatdate-time
status: Optional[Literal["active", "left", "removed"]]

Participant status

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

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: Optional[str]

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

sticker: Optional[Sticker]

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

file_name: Optional[str]

Filename of the sticker

height: Optional[int]

Sticker image height in pixels

mime_type: Optional[str]

MIME type of the sticker image

url: Optional[str]

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

formaturi
width: Optional[int]

Sticker image width in pixels

sent_at: Optional[datetime]

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

formatdate-time
delivered_at: Optional[datetime]

When the message was delivered

formatdate-time
effect: Optional[MessageEffect]

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

name: Optional[str]

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: Optional[Literal["screen", "bubble"]]

Type of effect

One of the following:
"screen"
"bubble"
from_handle: Optional[ChatHandle]

The sender of this message as a full handle object

id: str

Unique identifier for this handle

formatuuid
handle: str

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

joined_at: datetime

When this participant joined the chat

formatdate-time
service: ServiceType

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
is_me: Optional[bool]

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

left_at: Optional[datetime]

When they left (if applicable)

formatdate-time
status: Optional[Literal["active", "left", "removed"]]

Participant status

One of the following:
"active"
"left"
"removed"
preferred_service: Optional[ServiceType]

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
reply_to: Optional[ReplyTo]

Indicates this message is a threaded reply to another message

message_id: str

The ID of the message to reply to

formatuuid
part_index: Optional[int]

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: Optional[ServiceType]

Messaging service type

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

Messaging service type

One of the following:
"iMessage"
"SMS"
"RCS"
health_score: Optional[ChatHealthScore]

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

reason: str

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

score: int

Health score from 0 to 100. Higher is healthier.

minimum0
maximum100
updated_at: datetime

When this health score was last computed.

formatdate-time

Create a new chat

import os
from linq import LinqAPIV3

client = LinqAPIV3(
    api_key=os.environ.get("LINQ_API_V3_API_KEY"),  # This is the default and can be omitted
)
chat = client.chats.create(
    from_="+12052535597",
    message={
        "parts": [{
            "type": "text",
            "value": "Hello! How can I help you today?",
        }]
    },
    to=["+12052532136"],
)
print(chat.chat)
{
  "chat": {
    "id": "94c6bf33-31d9-40e3-a0e9-f94250ecedb9",
    "display_name": "+14155551234, +14155559876",
    "handles": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440010",
        "handle": "+14155551234",
        "joined_at": "2025-05-21T15:30:00.000Z",
        "service": "iMessage",
        "is_me": true,
        "left_at": "2019-12-27T18:11:19.117Z",
        "status": "active"
      },
      {
        "id": "550e8400-e29b-41d4-a716-446655440011",
        "handle": "+14155559876",
        "joined_at": "2025-05-21T15:30:00.000Z",
        "service": "iMessage",
        "is_me": false,
        "left_at": "2019-12-27T18:11:19.117Z",
        "status": "active"
      }
    ],
    "is_group": false,
    "message": {
      "id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
      "created_at": "2025-10-23T13:07:55.019-05:00",
      "delivery_status": "pending",
      "is_read": false,
      "parts": [
        {
          "reactions": [
            {
              "handle": {
                "id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
                "handle": "+15551234567",
                "joined_at": "2025-05-21T15:30:00.000-05:00",
                "service": "iMessage",
                "is_me": false,
                "left_at": "2019-12-27T18:11:19.117Z",
                "status": "active"
              },
              "is_me": false,
              "type": "love",
              "custom_emoji": null,
              "sticker": {
                "file_name": "sticker.png",
                "height": 420,
                "mime_type": "image/png",
                "url": "https://cdn.linqapp.com/attachments/a1b2c3d4/sticker.png?signature=...",
                "width": 420
              }
            }
          ],
          "type": "text",
          "value": "Hello!",
          "text_decorations": [
            {
              "range": [
                0,
                5
              ],
              "animation": "shake",
              "style": "bold"
            }
          ]
        }
      ],
      "sent_at": null,
      "delivered_at": null,
      "effect": {
        "name": "confetti",
        "type": "screen"
      },
      "from_handle": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "handle": "+15551234567",
        "joined_at": "2025-05-21T15:30:00.000-05:00",
        "service": "iMessage",
        "is_me": false,
        "left_at": "2019-12-27T18:11:19.117Z",
        "status": "active"
      },
      "preferred_service": "iMessage",
      "reply_to": {
        "message_id": "550e8400-e29b-41d4-a716-446655440000",
        "part_index": 0
      },
      "service": "iMessage"
    },
    "service": "iMessage",
    "health_score": {
      "reason": "Not enough engagement",
      "score": 35,
      "updated_at": "2026-05-01T18:28:25Z"
    }
  }
}
{
  "error": {
    "status": 400,
    "code": 1002,
    "message": "Phone number must be in E.164 format"
  },
  "success": false
}
{
  "error": {
    "status": 401,
    "code": 2004,
    "message": "Unauthorized - missing or invalid authentication token"
  },
  "success": false
}
{
  "error": {
    "status": 500,
    "code": 3006,
    "message": "Internal server error"
  },
  "success": false
}
Returns Examples
{
  "chat": {
    "id": "94c6bf33-31d9-40e3-a0e9-f94250ecedb9",
    "display_name": "+14155551234, +14155559876",
    "handles": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440010",
        "handle": "+14155551234",
        "joined_at": "2025-05-21T15:30:00.000Z",
        "service": "iMessage",
        "is_me": true,
        "left_at": "2019-12-27T18:11:19.117Z",
        "status": "active"
      },
      {
        "id": "550e8400-e29b-41d4-a716-446655440011",
        "handle": "+14155559876",
        "joined_at": "2025-05-21T15:30:00.000Z",
        "service": "iMessage",
        "is_me": false,
        "left_at": "2019-12-27T18:11:19.117Z",
        "status": "active"
      }
    ],
    "is_group": false,
    "message": {
      "id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
      "created_at": "2025-10-23T13:07:55.019-05:00",
      "delivery_status": "pending",
      "is_read": false,
      "parts": [
        {
          "reactions": [
            {
              "handle": {
                "id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
                "handle": "+15551234567",
                "joined_at": "2025-05-21T15:30:00.000-05:00",
                "service": "iMessage",
                "is_me": false,
                "left_at": "2019-12-27T18:11:19.117Z",
                "status": "active"
              },
              "is_me": false,
              "type": "love",
              "custom_emoji": null,
              "sticker": {
                "file_name": "sticker.png",
                "height": 420,
                "mime_type": "image/png",
                "url": "https://cdn.linqapp.com/attachments/a1b2c3d4/sticker.png?signature=...",
                "width": 420
              }
            }
          ],
          "type": "text",
          "value": "Hello!",
          "text_decorations": [
            {
              "range": [
                0,
                5
              ],
              "animation": "shake",
              "style": "bold"
            }
          ]
        }
      ],
      "sent_at": null,
      "delivered_at": null,
      "effect": {
        "name": "confetti",
        "type": "screen"
      },
      "from_handle": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "handle": "+15551234567",
        "joined_at": "2025-05-21T15:30:00.000-05:00",
        "service": "iMessage",
        "is_me": false,
        "left_at": "2019-12-27T18:11:19.117Z",
        "status": "active"
      },
      "preferred_service": "iMessage",
      "reply_to": {
        "message_id": "550e8400-e29b-41d4-a716-446655440000",
        "part_index": 0
      },
      "service": "iMessage"
    },
    "service": "iMessage",
    "health_score": {
      "reason": "Not enough engagement",
      "score": 35,
      "updated_at": "2026-05-01T18:28:25Z"
    }
  }
}
{
  "error": {
    "status": 400,
    "code": 1002,
    "message": "Phone number must be in E.164 format"
  },
  "success": false
}
{
  "error": {
    "status": 401,
    "code": 2004,
    "message": "Unauthorized - missing or invalid authentication token"
  },
  "success": false
}
{
  "error": {
    "status": 500,
    "code": 3006,
    "message": "Internal server error"
  },
  "success": false
}