Skip to content
Get started

Send a message (auto-selected from-number)

client.Messages.New(ctx, params) (*MessageNewResponse, error)
POST/v3/messages

Send a message to one or more recipients without supplying a from number. Linq resolves both the sending line and the target chat for you, then returns exactly which line was used, which chat the message landed in, whether a new chat was created, and every resulting message id.

This fuses “create chat” and “send message” behind a single message-centric resource. Provide only the recipients (to) and the message; the platform decides the rest.

How the from-number and chat are chosen

  • Reuse — if a chat with exactly these recipients already exists and the line it lives on is healthy, the message is sent into that chat on its existing line (from_selection.reason = reused_active_chat).
  • New — if no such chat exists, a new chat is created on the best available line (from_selection.reason = new_best_number).
  • Failover — if a matching chat exists but its line has been flagged, a new chat is created on a fresh best line and the flagged chat is abandoned (from_selection.reason = failover_flagged, previous_chat_id set). If you supply continuation_message, that text is sent as the single message INSTEAD of message (useful as a fresh-number-appropriate opener). Exactly one message is sent either way.

Recipients (to) are an order-independent set: a single handle is a direct chat, multiple handles a group chat.

Differences from POST /v3/chats

  • The first message may contain a link (including for a newly created chat). Note: sending a link as the very first message on a freshly selected line can elevate that line’s flagging risk — it is allowed, not recommended.
  • Voice memos are not supported here. To send an iMessage voice-memo bubble, use POST /v3/chats/{chatId}/voicememo with a known chat id.

Service preference, effects, decorations

Set message.preferred_service (iMessage | RCS | SMS), message.effect, and per-part text_decorations exactly as on the other send endpoints.

Always responds 202 Accepted — chat creation is incidental to the send.

ParametersExpand Collapse
params MessageNewParams
Message param.Field[MessageContent]

Body param: Message content container. Groups all message-related fields together, separating the “what” (message content) from the “where” (routing fields like from/to).

To param.Field[[]string]

Body param: Recipient handles (E.164 phone numbers or email addresses). One handle is a direct chat; multiple handles a group chat. Order-independent — the set identifies the chat.

ContinuationMessage param.Field[MessageNewParamsContinuationMessage]Optional

Body param: Text-only fallback that replaces message ONLY on the failover branch — when a chat with these recipients already existed but its line was flagged, so a new chat is created on a fresh line. On that branch this text is sent as the single message instead of message (the recipient is on a new number, so you typically want a fresh-number-appropriate opener rather than the original content). Ignored otherwise (a healthy reuse, or genuine first contact). Carries no parts, media, or effects — exactly one message is ever sent.

Text string

The replacement message text, sent as the single message on failover.

minLength1
maxLength10000
IdempotencyKey param.Field[string]Optional

Header param: Optional idempotency key for the send. Reuse the same key to safely retry without sending twice. May also be supplied as message.idempotency_key.

maxLength255
ReturnsExpand Collapse
type MessageNewResponse struct{…}

Result of an auto-from send. Self-describing: which line was used, which chat the message landed in, whether a new chat was created, and the resulting message id(s).

ChatID string

The resolved chat (reused or newly created) the message landed in.

formatuuid
CreatedNewChat bool

True when a new chat was created (new or failover), false on reuse.

From string

The line (E.164) the message was actually sent from.

FromSelection MessageNewResponseFromSelection

Why this line/chat was chosen.

Reason string
  • reused_active_chat — reused an existing chat on its healthy line
  • new_best_number — created a new chat on the best available line
  • failover_flagged — prior chat’s line was flagged; created a new chat on a fresh line
One of the following:
const MessageNewResponseFromSelectionReasonReusedActiveChat MessageNewResponseFromSelectionReason = "reused_active_chat"
const MessageNewResponseFromSelectionReasonNewBestNumber MessageNewResponseFromSelectionReason = "new_best_number"
const MessageNewResponseFromSelectionReasonFailoverFlagged MessageNewResponseFromSelectionReason = "failover_flagged"
ReusedExistingChat bool

True only when an existing chat was reused.

Handles []ChatHandle

Participants of the resolved chat.

ID string

Unique identifier for this handle

formatuuid
Handle string

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

JoinedAt Time

When this participant joined the chat

formatdate-time
Service ServiceType

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
IsMe boolOptional

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

LeftAt TimeOptional

When they left (if applicable)

formatdate-time
Status ChatHandleStatusOptional

Participant status

One of the following:
const ChatHandleStatusActive ChatHandleStatus = "active"
const ChatHandleStatusLeft ChatHandleStatus = "left"
const ChatHandleStatusRemoved ChatHandleStatus = "removed"
IsGroup bool

Whether the resolved chat is a group chat.

Message SentMessage

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

ID string

Message identifier (UUID)

formatuuid
CreatedAt Time

When the message was created

formatdate-time
DeliveryStatus SentMessageDeliveryStatus

Current delivery status of a message

One of the following:
const SentMessageDeliveryStatusPending SentMessageDeliveryStatus = "pending"
const SentMessageDeliveryStatusQueued SentMessageDeliveryStatus = "queued"
const SentMessageDeliveryStatusSent SentMessageDeliveryStatus = "sent"
const SentMessageDeliveryStatusDelivered SentMessageDeliveryStatus = "delivered"
const SentMessageDeliveryStatusReceived SentMessageDeliveryStatus = "received"
const SentMessageDeliveryStatusRead SentMessageDeliveryStatus = "read"
const SentMessageDeliveryStatusFailed SentMessageDeliveryStatus = "failed"
DeprecatedIsRead bool

DEPRECATED: Use delivery_status == "read" instead. Whether the message has been read.

Parts []SentMessagePartUnion

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

One of the following:
type TextPartResponse struct{…}

A text message part

Reactions []Reaction

Reactions on this message part

Handle ChatHandle
ID string

Unique identifier for this handle

formatuuid
Handle string

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

JoinedAt Time

When this participant joined the chat

formatdate-time
Service ServiceType

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
IsMe boolOptional

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

LeftAt TimeOptional

When they left (if applicable)

formatdate-time
Status ChatHandleStatusOptional

Participant status

One of the following:
const ChatHandleStatusActive ChatHandleStatus = "active"
const ChatHandleStatusLeft ChatHandleStatus = "left"
const ChatHandleStatusRemoved ChatHandleStatus = "removed"
IsMe 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:
const ReactionTypeLove ReactionType = "love"
const ReactionTypeLike ReactionType = "like"
const ReactionTypeDislike ReactionType = "dislike"
const ReactionTypeLaugh ReactionType = "laugh"
const ReactionTypeEmphasize ReactionType = "emphasize"
const ReactionTypeQuestion ReactionType = "question"
const ReactionTypeCustom ReactionType = "custom"
const ReactionTypeSticker ReactionType = "sticker"
CustomEmoji stringOptional

Custom emoji if type is “custom”, null otherwise

Sticker ReactionStickerOptional

Sticker attachment details when reaction_type is “sticker”. Null for non-sticker reactions.

FileName stringOptional

Filename of the sticker

Height int64Optional

Sticker image height in pixels

MimeType stringOptional

MIME type of the sticker image

URL stringOptional

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

formaturi
Width int64Optional

Sticker image width in pixels

Type TextPartResponseType

Indicates this is a text message part

Value string

The text content

TextDecorations []TextDecorationOptional

Text decorations applied to character ranges in the value

Range []int64

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 TextDecorationAnimationOptional

Animated text effect to apply. Mutually exclusive with style.

One of the following:
const TextDecorationAnimationBig TextDecorationAnimation = "big"
const TextDecorationAnimationSmall TextDecorationAnimation = "small"
const TextDecorationAnimationShake TextDecorationAnimation = "shake"
const TextDecorationAnimationNod TextDecorationAnimation = "nod"
const TextDecorationAnimationExplode TextDecorationAnimation = "explode"
const TextDecorationAnimationRipple TextDecorationAnimation = "ripple"
const TextDecorationAnimationBloom TextDecorationAnimation = "bloom"
const TextDecorationAnimationJitter TextDecorationAnimation = "jitter"
Style TextDecorationStyleOptional

Text style to apply. Mutually exclusive with animation.

One of the following:
const TextDecorationStyleBold TextDecorationStyle = "bold"
const TextDecorationStyleItalic TextDecorationStyle = "italic"
const TextDecorationStyleStrikethrough TextDecorationStyle = "strikethrough"
const TextDecorationStyleUnderline TextDecorationStyle = "underline"
type MediaPartResponse struct{…}

A media attachment part

ID string

Unique attachment identifier

formatuuid
Filename string

Original filename

MimeType string

MIME type of the file

Reactions []Reaction

Reactions on this message part

Handle ChatHandle
ID string

Unique identifier for this handle

formatuuid
Handle string

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

JoinedAt Time

When this participant joined the chat

formatdate-time
Service ServiceType

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
IsMe boolOptional

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

LeftAt TimeOptional

When they left (if applicable)

formatdate-time
Status ChatHandleStatusOptional

Participant status

One of the following:
const ChatHandleStatusActive ChatHandleStatus = "active"
const ChatHandleStatusLeft ChatHandleStatus = "left"
const ChatHandleStatusRemoved ChatHandleStatus = "removed"
IsMe 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:
const ReactionTypeLove ReactionType = "love"
const ReactionTypeLike ReactionType = "like"
const ReactionTypeDislike ReactionType = "dislike"
const ReactionTypeLaugh ReactionType = "laugh"
const ReactionTypeEmphasize ReactionType = "emphasize"
const ReactionTypeQuestion ReactionType = "question"
const ReactionTypeCustom ReactionType = "custom"
const ReactionTypeSticker ReactionType = "sticker"
CustomEmoji stringOptional

Custom emoji if type is “custom”, null otherwise

Sticker ReactionStickerOptional

Sticker attachment details when reaction_type is “sticker”. Null for non-sticker reactions.

FileName stringOptional

Filename of the sticker

Height int64Optional

Sticker image height in pixels

MimeType stringOptional

MIME type of the sticker image

URL stringOptional

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

formaturi
Width int64Optional

Sticker image width in pixels

SizeBytes int64

File size in bytes

Type MediaPartResponseType

Indicates this is a media attachment part

URL string

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

formaturi
Handle ChatHandle
ID string

Unique identifier for this handle

formatuuid
Handle string

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

JoinedAt Time

When this participant joined the chat

formatdate-time
Service ServiceType

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
IsMe boolOptional

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

LeftAt TimeOptional

When they left (if applicable)

formatdate-time
Status ChatHandleStatusOptional

Participant status

One of the following:
const ChatHandleStatusActive ChatHandleStatus = "active"
const ChatHandleStatusLeft ChatHandleStatus = "left"
const ChatHandleStatusRemoved ChatHandleStatus = "removed"
IsMe 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:
const ReactionTypeLove ReactionType = "love"
const ReactionTypeLike ReactionType = "like"
const ReactionTypeDislike ReactionType = "dislike"
const ReactionTypeLaugh ReactionType = "laugh"
const ReactionTypeEmphasize ReactionType = "emphasize"
const ReactionTypeQuestion ReactionType = "question"
const ReactionTypeCustom ReactionType = "custom"
const ReactionTypeSticker ReactionType = "sticker"
CustomEmoji stringOptional

Custom emoji if type is “custom”, null otherwise

Sticker ReactionStickerOptional

Sticker attachment details when reaction_type is “sticker”. Null for non-sticker reactions.

FileName stringOptional

Filename of the sticker

Height int64Optional

Sticker image height in pixels

MimeType stringOptional

MIME type of the sticker image

URL stringOptional

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

formaturi
Width int64Optional

Sticker image width in pixels

type SentMessagePartIMessageAppPartResponse struct{…}

An iMessage app card part.

App SentMessagePartIMessageAppPartResponseApp

Identifies the iMessage app (Messages app extension) that backs the card.

BundleID string

Bundle identifier of the Messages app extension. Must not contain :.

minLength1
maxLength255
Name string

Display name of the app, shown by Messages’ fallback UI.

minLength1
maxLength64
TeamID string

The app’s 10-character uppercase alphanumeric team identifier.

AppStoreID int64Optional

The owning app’s App Store id (optional). When set, recipients without the iMessage app installed see a “Get the app” affordance.

formatint64
minimum1
Layout SentMessagePartIMessageAppPartResponseLayout

Visible layout of the card. At least one of caption, subcaption, trailing_caption, trailing_subcaption, or image_url must be set, otherwise the card renders as an empty bubble.

image_url displays a preview image at the top of the card. The image renders on the recipient’s card whether or not they have your app installed. The small icon beside the caption is the app’s own icon and is not settable here.

* Note - requires a trusted chat w/ inbound activity

image_title and image_subtitle render as text overlaid on the image (title bold, subtitle beneath it). They only appear when image_url is set — without an image there is nothing to overlay — so setting either without image_url is rejected.

Caption stringOptional

Primary label, top-left and bold.

maxLength512
ImageSubtitle stringOptional

Text shown below image_title, overlaid on the card image. Requires image_url.

maxLength512
ImageTitle stringOptional

Bold text overlaid on the card image. Requires image_url (rejected without it).

maxLength512
ImageURL stringOptional

URL of a JPEG image to display as the card’s preview image; an unreachable or non-image URL returns a validation error. Renders for all recipients regardless of whether they have the app. Note - requires a trusted chat w/ inbound activity.

formaturi
maxLength2048
Subcaption stringOptional

Secondary label, below caption on the left.

maxLength512
TrailingCaption stringOptional

Label shown top-right.

maxLength512
TrailingSubcaption stringOptional

Label shown below trailing_caption, on the right.

maxLength512
Reactions []Reaction

Reactions on this message part

Handle ChatHandle
ID string

Unique identifier for this handle

formatuuid
Handle string

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

JoinedAt Time

When this participant joined the chat

formatdate-time
Service ServiceType

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
IsMe boolOptional

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

LeftAt TimeOptional

When they left (if applicable)

formatdate-time
Status ChatHandleStatusOptional

Participant status

One of the following:
const ChatHandleStatusActive ChatHandleStatus = "active"
const ChatHandleStatusLeft ChatHandleStatus = "left"
const ChatHandleStatusRemoved ChatHandleStatus = "removed"
IsMe 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:
const ReactionTypeLove ReactionType = "love"
const ReactionTypeLike ReactionType = "like"
const ReactionTypeDislike ReactionType = "dislike"
const ReactionTypeLaugh ReactionType = "laugh"
const ReactionTypeEmphasize ReactionType = "emphasize"
const ReactionTypeQuestion ReactionType = "question"
const ReactionTypeCustom ReactionType = "custom"
const ReactionTypeSticker ReactionType = "sticker"
CustomEmoji stringOptional

Custom emoji if type is “custom”, null otherwise

Sticker ReactionStickerOptional

Sticker attachment details when reaction_type is “sticker”. Null for non-sticker reactions.

FileName stringOptional

Filename of the sticker

Height int64Optional

Sticker image height in pixels

MimeType stringOptional

MIME type of the sticker image

URL stringOptional

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

formaturi
Width int64Optional

Sticker image width in pixels

Type string

Indicates this is an iMessage app card part.

URL string

The URL delivered to the iMessage app on tap.

formaturi
FallbackText stringOptional

Fallback text for surfaces that cannot render the card.

SentAt Time

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

formatdate-time
DeliveredAt TimeOptional

When the message was delivered

formatdate-time
Effect MessageEffectOptional

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

Name stringOptional

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 MessageEffectTypeOptional

Type of effect

One of the following:
const MessageEffectTypeScreen MessageEffectType = "screen"
const MessageEffectTypeBubble MessageEffectType = "bubble"
FromHandle ChatHandleOptional

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

JoinedAt Time

When this participant joined the chat

formatdate-time
Service ServiceType

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
IsMe boolOptional

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

LeftAt TimeOptional

When they left (if applicable)

formatdate-time
Status ChatHandleStatusOptional

Participant status

One of the following:
const ChatHandleStatusActive ChatHandleStatus = "active"
const ChatHandleStatusLeft ChatHandleStatus = "left"
const ChatHandleStatusRemoved ChatHandleStatus = "removed"
PreferredService ServiceTypeOptional

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
ReplyTo ReplyToOptional

Indicates this message is a threaded reply to another message

MessageID string

The ID of the message to reply to

formatuuid
PartIndex int64Optional

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 ServiceTypeOptional

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
Service ServiceType

Messaging service type

One of the following:
const ServiceTypeIMessage ServiceType = "iMessage"
const ServiceTypeSMS ServiceType = "SMS"
const ServiceTypeRCS ServiceType = "RCS"
PreviousChatID stringOptional

Set ONLY on failover_flagged: the abandoned flagged chat that was NOT sent into. Null otherwise.

formatuuid

Send a message (auto-selected from-number)

package main

import (
  "context"
  "fmt"

  "github.com/linq-team/linq-go"
  "github.com/linq-team/linq-go/option"
)

func main() {
  client := linqgo.NewClient(
    option.WithAPIKey("My API Key"),
  )
  message, err := client.Messages.New(context.TODO(), linqgo.MessageNewParams{
    Message: linqgo.MessageContentParam{
      Parts: []linqgo.MessageContentPartUnionParam{linqgo.MessageContentPartUnionParam{
        OfText: &linqgo.TextPartParam{
          Type: linqgo.TextPartTypeText,
          Value: "Hi! Thanks for reaching out — how can we help?",
        },
      }},
    },
    To: []string{"+14155559876"},
  })
  if err != nil {
    panic(err.Error())
  }
  fmt.Printf("%+v\n", message.ChatID)
}
{
  "chat_id": "94c6bf33-31d9-40e3-a0e9-f94250ecedb9",
  "created_new_chat": false,
  "from": "+12052535597",
  "from_selection": {
    "reason": "reused_active_chat",
    "reused_existing_chat": true
  },
  "handles": [
    {
      "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"
    }
  ],
  "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",
  "previous_chat_id": null
}
{
  "error": {
    "status": 400,
    "code": 1002,
    "message": "Phone number must be in E.164 format",
    "doc_url": "https://docs.linqapp.com/error/codes/1xxx/1002/"
  },
  "success": false
}
{
  "error": {
    "status": 401,
    "code": 2004,
    "message": "Unauthorized - missing or invalid authentication token",
    "doc_url": "https://docs.linqapp.com/error/codes/2xxx/2004/"
  },
  "success": false
}
{
  "error": {
    "status": 403,
    "code": 2005,
    "message": "Access denied - insufficient permissions for this resource",
    "doc_url": "https://docs.linqapp.com/error/codes/2xxx/2005/"
  },
  "success": false
}
{
  "error": {
    "status": 409,
    "code": 2015,
    "message": "no eligible sending line available",
    "doc_url": "https://docs.linqapp.com/error/codes/2xxx/2015/"
  },
  "success": false
}
{
  "error": {
    "status": 500,
    "code": 3006,
    "message": "Internal server error",
    "doc_url": "https://docs.linqapp.com/error/codes/3xxx/3006/"
  },
  "success": false
}
Returns Examples
{
  "chat_id": "94c6bf33-31d9-40e3-a0e9-f94250ecedb9",
  "created_new_chat": false,
  "from": "+12052535597",
  "from_selection": {
    "reason": "reused_active_chat",
    "reused_existing_chat": true
  },
  "handles": [
    {
      "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"
    }
  ],
  "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",
  "previous_chat_id": null
}
{
  "error": {
    "status": 400,
    "code": 1002,
    "message": "Phone number must be in E.164 format",
    "doc_url": "https://docs.linqapp.com/error/codes/1xxx/1002/"
  },
  "success": false
}
{
  "error": {
    "status": 401,
    "code": 2004,
    "message": "Unauthorized - missing or invalid authentication token",
    "doc_url": "https://docs.linqapp.com/error/codes/2xxx/2004/"
  },
  "success": false
}
{
  "error": {
    "status": 403,
    "code": 2005,
    "message": "Access denied - insufficient permissions for this resource",
    "doc_url": "https://docs.linqapp.com/error/codes/2xxx/2005/"
  },
  "success": false
}
{
  "error": {
    "status": 409,
    "code": 2015,
    "message": "no eligible sending line available",
    "doc_url": "https://docs.linqapp.com/error/codes/2xxx/2015/"
  },
  "success": false
}
{
  "error": {
    "status": 500,
    "code": 3006,
    "message": "Internal server error",
    "doc_url": "https://docs.linqapp.com/error/codes/3xxx/3006/"
  },
  "success": false
}