## Send a message in a chat

**post** `/v1/chats/{chat}/messages`

Sends a reply on an existing chat's unchanged sending number. The chat
supplies the customer and sender; this operation never creates, moves,
repins or fails over a conversation. Acceptance and refusal semantics are
otherwise identical to `POST /v1/messages`.

### Path Parameters

- `chat: string`

### Header Parameters

- `"Idempotency-Key": optional string`

### Body Parameters

- `parts: array of object { body, type, preview_url }  or object { kind, type, caption, 4 more }  or object { language, name, type, 3 more }  or 8 more`

  The message content — sendable parts only, at least one.

  **One outbound part per request.** Each request has its own acceptance
  result and optional idempotency key. Each accepted request maps to one
  native channel message with its own identifier, delivery outcome and
  charge evidence. A request carrying more than one
  part is refused with HTTP 422 (`multiple_parts_not_available`); the API
  neither fans it out nor offers an atomic batch. Separate requests are
  independent, and no cross-request delivery or receipt order is promised.

  - `Text object { body, type, preview_url }`

    A plain text message.

    - `body: string`

      The message text. URLs render as tappable links.

    - `type: "text"`

      - `"text"`

    - `preview_url: optional boolean`

      Render a preview card for the first URL in body. Defaults to false.

  - `Media object { kind, type, caption, 4 more }`

    A media message — image, video, audio, document, or sticker. The two identifiers are distinct namespaces: inbound media carries the channel's transient media_id; outbound media carries our durable upload_ref from POST /v1/media.

    - `kind: "image" or "video" or "audio" or 2 more`

      Which kind of media this is. Captions apply to image, video and document only; filename applies to document only.

      - `"image"`

      - `"video"`

      - `"audio"`

      - `"document"`

      - `"sticker"`

    - `type: "media"`

      - `"media"`

    - `caption: optional string`

      Caption rendered with the media. Image, video and document only — a caption on an audio or sticker part is rejected, never dropped.

    - `filename: optional string`

      Display filename. Documents only — a filename on any other kind is rejected, never dropped.

    - `media_id: optional string`

      Inbound only: the channel's transient media identifier. It expires after seven days and is never an outbound address; an outbound value is rejected with a pointer to media_id and upload_ref as the remedy.

    - `upload_ref: optional string`

      Outbound only: our durable handle returned by POST /v1/media. Handles visibly begin upload. and are reusable within the account and test/live partition that created them.

    - `url: optional string`

      Response only: stable attachment download URL requiring the account Bearer key on every request. Pending capture returns 409 with Retry-After; retained bytes expire 30 days after server receipt. Historical unbound messages omit this field. Never accepted on sends.

  - `Template object { language, name, type, 3 more }`

    An approved message template — the one part type sendable outside an open customer service window. name and language identify the approved template; parameters fills its named placeholders. Authentication templates use this same generic part unchanged: the channel supplies the OTP substitution, so do not invent or pass a code parameter unless the template's published parameter schema explicitly names one. Every sendable template is registered and approved ahead of the send and publishes its own parameter schema — a send referencing an unknown template, a missing or unknown parameter, or a value that breaks the template's rules is rejected with a 422 naming the exact field.

    - `language: string`

      The template's language-and-locale code, e.g. en_US.

    - `name: string`

      The approved template's name. Lowercase letters, digits and underscores only.

    - `type: "template"`

      - `"template"`

    - `cards: optional array of object { card_index, kind, upload_ref, 2 more }`

      Per-card values for an approved media-card carousel. The approved template's send_schema provides structural bounds and an x-rule listing the exact card order, media kind, named body values, and dynamic button slots enforced by runtime L2 validation. Omit for non-carousel templates.

      - `card_index: number`

      - `kind: "image" or "video"`

        - `"image"`

        - `"video"`

      - `upload_ref: string`

        A durable handle returned by POST /v1/media. It is resolved within this key's account and partition, then consumed into a transient channel media identifier only at delivery.

      - `buttons: optional array of object { index, payload, type }`

        - `index: number`

        - `payload: string`

        - `type: "quick_reply" or "url"`

          - `"quick_reply"`

          - `"url"`

      - `parameters: optional unknown`

        Named values for this card's body placeholders.

    - `header: optional object { kind, upload_ref }`

      The uploaded media used for this approved template's media header. Omit unless this template's send_schema requires it.

      - `kind: "image" or "video" or "document"`

        - `"image"`

        - `"video"`

        - `"document"`

      - `upload_ref: string`

        A durable handle returned by POST /v1/media.

    - `parameters: optional unknown`

      Named values for the template's placeholders. The shape is per-template: each registered template publishes its own parameter schema — hand THAT schema to your model when composing a specific template. Omit for templates with no placeholders.

  - `InteractiveList object { body, button, sections, 3 more }`

    An interactive list message: body text plus a button that opens a sectioned list of selectable rows. The customer's selection arrives as an inbound interactive_reply part with kind list_reply, carrying the chosen row's id.

    - `body: string`

      The message body.

    - `button: string`

      Label of the button that opens the list.

    - `sections: array of object { rows, title }`

      The list's sections, each holding selectable rows. At most 10 rows in total across ALL sections combined — not 10 per section.

      - `rows: array of object { id, title, description }`

        This section's rows. The 10-row limit is on the TOTAL across all sections, so a second section reduces what this one may hold.

        - `id: string`

          Your identifier for the row — echoed back as the interactive_reply's id.

        - `title: string`

          The row's visible title.

        - `description: optional string`

          Secondary text under the title.

      - `title: optional string`

        Section title. Required when the list has more than one section.

    - `type: "interactive_list"`

      - `"interactive_list"`

    - `footer: optional string`

      Footer text below the body.

    - `header: optional string`

      Header text above the body.

  - `InteractiveButtons object { body, buttons, type, 3 more }`

    An interactive reply-buttons message: body text plus up to three tappable buttons. The customer's tap arrives as an inbound interactive_reply part with kind button_reply, carrying the tapped button's id.

    - `body: string`

      The message body.

    - `buttons: array of object { id, title }`

      The tappable buttons — at most three.

      - `id: string`

        Your identifier for the button — echoed back as the interactive_reply's id.

      - `title: string`

        The button's visible label.

    - `type: "interactive_buttons"`

      - `"interactive_buttons"`

    - `footer: optional string`

      Footer text below the body.

    - `header: optional string`

      Header text above the body.

    - `media_header: optional object { kind, upload_ref }`

      Uploaded image, video, or document above the body. Use either header or media_header, never both.

      - `kind: "image" or "video" or "document"`

        - `"image"`

        - `"video"`

        - `"document"`

      - `upload_ref: string`

        A durable handle returned by POST /v1/media.

  - `InteractiveCtaURL object { body, display_text, type, 3 more }`

    An interactive call-to-action message: body text plus one button that opens a URL.

    - `body: string`

      The message body.

    - `display_text: string`

      The button's visible label.

    - `type: "interactive_cta_url"`

      - `"interactive_cta_url"`

    - `url: string`

      The URL the button opens. Must be absolute, with an http or https scheme.

    - `footer: optional string`

      Footer text below the body.

    - `header: optional string`

      Header text above the body.

  - `LocationRequest object { body, type }`

    Asks the customer to share a location. The response arrives as a location part.

    - `body: string`

      Prompt shown above the send-location button.

    - `type: "location_request"`

      - `"location_request"`

  - `AddressRequest object { body, country, type }`

    Reserved for asking an eligible customer in India to submit a structured address. Sending this part is not available until business and customer eligibility can be verified at acceptance. Address responses already arrive as address_reply parts.

    - `body: string`

      Prompt shown above the address form.

    - `country: "IN"`

      ISO country code. Structured address requests are currently available only in India.

      - `"IN"`

    - `type: "address_request"`

      - `"address_request"`

  - `Contacts object { contacts, type }`

    One or more contact cards.

    - `contacts: array of object { name, addresses, birthday, 4 more }`

      The contact cards to send. The channel permits far more; this API caps a message at five, because a message carrying hundreds of cards is a mistake rather than a use case.

      - `name: object { formatted_name, first_name, last_name, 3 more }`

        - `formatted_name: string`

          The contact's full display name.

        - `first_name: optional string`

        - `last_name: optional string`

        - `middle_name: optional string`

        - `prefix: optional string`

        - `suffix: optional string`

      - `addresses: optional array of object { city, country, country_code, 4 more }`

        - `city: optional string`

        - `country: optional string`

        - `country_code: optional string`

        - `kind: optional string`

          A label for the address, e.g. WORK, HOME.

        - `state: optional string`

        - `street: optional string`

        - `zip: optional string`

      - `birthday: optional string`

        The contact's birthday as YYYY-MM-DD.

      - `emails: optional array of object { email, kind }`

        - `email: string`

        - `kind: optional string`

          A label for the address, e.g. WORK, HOME.

      - `org: optional object { company, department, title }`

        - `company: optional string`

        - `department: optional string`

        - `title: optional string`

      - `phones: optional array of object { phone, kind, messaging_id }`

        - `phone: string`

          The phone number, ideally in +E.164 form.

        - `kind: optional string`

          A label for the number, e.g. CELL, MAIN, WORK, HOME.

        - `messaging_id: optional string`

          The contact's messaging-account identifier on this channel, when known — makes the card openable in the messaging app.

      - `urls: optional array of object { url, kind }`

        - `url: string`

        - `kind: optional string`

          A label for the URL, e.g. WORK, HOME.

    - `type: "contacts"`

      - `"contacts"`

  - `Location object { latitude, longitude, type, 2 more }`

    A location pin.

    - `latitude: number`

      Latitude in decimal degrees.

    - `longitude: number`

      Longitude in decimal degrees.

    - `type: "location"`

      - `"location"`

    - `address: optional string`

      The place's address, shown under the name.

    - `name: optional string`

      The place's name, shown on the pin.

  - `Reaction object { emoji, type, channel_message_id, message_id }`

    An emoji reaction to an earlier message in the chat. The two identifiers are distinct namespaces: inbound reactions carry the channel's opaque channel_message_id; outbound reactions will carry this API's message_id once sending them becomes available.

    - `emoji: string`

      A single emoji. Send an empty string to remove a previous reaction to the same message.

    - `type: "reaction"`

      - `"reaction"`

    - `channel_message_id: optional string`

      Inbound only: the channel's opaque identifier for the message being reacted to. Match it literally to Message.channel_message_id in the chat transcript; never parse it or compare it with Message.id.

    - `message_id: optional string`

      Outbound only: this API's Message.id for the message being reacted to. Outbound reactions are not available yet; when they land, the API resolves this identifier into the channel namespace before sending.

- `reply_to_message_id: optional string`

  Our opaque `Message.id` for an earlier message in this same chat.

- `send_at: optional string`

  RESERVED — scheduled sends are not yet available. Any value is refused.

### Returns

- `AcceptedMessage object { id, chat_id, created_at, 7 more }`

  An accepted send: the message, plus how its sending number was chosen.

  - `id: string`

    This API's message id. Once outbound reactions are available, put this value in their `message_id`. Mark-as-read targets the latest unread inbound message in a chat, so it takes the chat id.

  - `chat_id: string`

    The chat this message belongs to.

  - `created_at: string`

  - `direction: "inbound" or "outbound"`

    `inbound` (from the customer) or `outbound` (sent by you).

    - `"inbound"`

    - `"outbound"`

  - `parts: array of object { body, type, preview_url }  or object { kind, type, caption, 4 more }  or object { language, name, type, 3 more }  or 14 more`

    The message content — sendable parts, plus the inbound-only types on
    inbound messages. Every message carries at least one part.

    - `Text object { body, type, preview_url }`

      A plain text message.

      - `body: string`

        The message text. URLs render as tappable links.

      - `type: "text"`

        - `"text"`

      - `preview_url: optional boolean`

        Render a preview card for the first URL in body. Defaults to false.

    - `Media object { kind, type, caption, 4 more }`

      A media message — image, video, audio, document, or sticker. The two identifiers are distinct namespaces: inbound media carries the channel's transient media_id; outbound media carries our durable upload_ref from POST /v1/media.

      - `kind: "image" or "video" or "audio" or 2 more`

        Which kind of media this is. Captions apply to image, video and document only; filename applies to document only.

        - `"image"`

        - `"video"`

        - `"audio"`

        - `"document"`

        - `"sticker"`

      - `type: "media"`

        - `"media"`

      - `caption: optional string`

        Caption rendered with the media. Image, video and document only — a caption on an audio or sticker part is rejected, never dropped.

      - `filename: optional string`

        Display filename. Documents only — a filename on any other kind is rejected, never dropped.

      - `media_id: optional string`

        Inbound only: the channel's transient media identifier. It expires after seven days and is never an outbound address; an outbound value is rejected with a pointer to media_id and upload_ref as the remedy.

      - `upload_ref: optional string`

        Outbound only: our durable handle returned by POST /v1/media. Handles visibly begin upload. and are reusable within the account and test/live partition that created them.

      - `url: optional string`

        Response only: stable attachment download URL requiring the account Bearer key on every request. Pending capture returns 409 with Retry-After; retained bytes expire 30 days after server receipt. Historical unbound messages omit this field. Never accepted on sends.

    - `Template object { language, name, type, 3 more }`

      An approved message template — the one part type sendable outside an open customer service window. name and language identify the approved template; parameters fills its named placeholders. Authentication templates use this same generic part unchanged: the channel supplies the OTP substitution, so do not invent or pass a code parameter unless the template's published parameter schema explicitly names one. Every sendable template is registered and approved ahead of the send and publishes its own parameter schema — a send referencing an unknown template, a missing or unknown parameter, or a value that breaks the template's rules is rejected with a 422 naming the exact field.

      - `language: string`

        The template's language-and-locale code, e.g. en_US.

      - `name: string`

        The approved template's name. Lowercase letters, digits and underscores only.

      - `type: "template"`

        - `"template"`

      - `cards: optional array of object { card_index, kind, upload_ref, 2 more }`

        Per-card values for an approved media-card carousel. The approved template's send_schema provides structural bounds and an x-rule listing the exact card order, media kind, named body values, and dynamic button slots enforced by runtime L2 validation. Omit for non-carousel templates.

        - `card_index: number`

        - `kind: "image" or "video"`

          - `"image"`

          - `"video"`

        - `upload_ref: string`

          A durable handle returned by POST /v1/media. It is resolved within this key's account and partition, then consumed into a transient channel media identifier only at delivery.

        - `buttons: optional array of object { index, payload, type }`

          - `index: number`

          - `payload: string`

          - `type: "quick_reply" or "url"`

            - `"quick_reply"`

            - `"url"`

        - `parameters: optional unknown`

          Named values for this card's body placeholders.

      - `header: optional object { kind, upload_ref }`

        The uploaded media used for this approved template's media header. Omit unless this template's send_schema requires it.

        - `kind: "image" or "video" or "document"`

          - `"image"`

          - `"video"`

          - `"document"`

        - `upload_ref: string`

          A durable handle returned by POST /v1/media.

      - `parameters: optional unknown`

        Named values for the template's placeholders. The shape is per-template: each registered template publishes its own parameter schema — hand THAT schema to your model when composing a specific template. Omit for templates with no placeholders.

    - `InteractiveList object { body, button, sections, 3 more }`

      An interactive list message: body text plus a button that opens a sectioned list of selectable rows. The customer's selection arrives as an inbound interactive_reply part with kind list_reply, carrying the chosen row's id.

      - `body: string`

        The message body.

      - `button: string`

        Label of the button that opens the list.

      - `sections: array of object { rows, title }`

        The list's sections, each holding selectable rows. At most 10 rows in total across ALL sections combined — not 10 per section.

        - `rows: array of object { id, title, description }`

          This section's rows. The 10-row limit is on the TOTAL across all sections, so a second section reduces what this one may hold.

          - `id: string`

            Your identifier for the row — echoed back as the interactive_reply's id.

          - `title: string`

            The row's visible title.

          - `description: optional string`

            Secondary text under the title.

        - `title: optional string`

          Section title. Required when the list has more than one section.

      - `type: "interactive_list"`

        - `"interactive_list"`

      - `footer: optional string`

        Footer text below the body.

      - `header: optional string`

        Header text above the body.

    - `InteractiveButtons object { body, buttons, type, 3 more }`

      An interactive reply-buttons message: body text plus up to three tappable buttons. The customer's tap arrives as an inbound interactive_reply part with kind button_reply, carrying the tapped button's id.

      - `body: string`

        The message body.

      - `buttons: array of object { id, title }`

        The tappable buttons — at most three.

        - `id: string`

          Your identifier for the button — echoed back as the interactive_reply's id.

        - `title: string`

          The button's visible label.

      - `type: "interactive_buttons"`

        - `"interactive_buttons"`

      - `footer: optional string`

        Footer text below the body.

      - `header: optional string`

        Header text above the body.

      - `media_header: optional object { kind, upload_ref }`

        Uploaded image, video, or document above the body. Use either header or media_header, never both.

        - `kind: "image" or "video" or "document"`

          - `"image"`

          - `"video"`

          - `"document"`

        - `upload_ref: string`

          A durable handle returned by POST /v1/media.

    - `InteractiveCtaURL object { body, display_text, type, 3 more }`

      An interactive call-to-action message: body text plus one button that opens a URL.

      - `body: string`

        The message body.

      - `display_text: string`

        The button's visible label.

      - `type: "interactive_cta_url"`

        - `"interactive_cta_url"`

      - `url: string`

        The URL the button opens. Must be absolute, with an http or https scheme.

      - `footer: optional string`

        Footer text below the body.

      - `header: optional string`

        Header text above the body.

    - `LocationRequest object { body, type }`

      Asks the customer to share a location. The response arrives as a location part.

      - `body: string`

        Prompt shown above the send-location button.

      - `type: "location_request"`

        - `"location_request"`

    - `AddressRequest object { body, country, type }`

      Reserved for asking an eligible customer in India to submit a structured address. Sending this part is not available until business and customer eligibility can be verified at acceptance. Address responses already arrive as address_reply parts.

      - `body: string`

        Prompt shown above the address form.

      - `country: "IN"`

        ISO country code. Structured address requests are currently available only in India.

        - `"IN"`

      - `type: "address_request"`

        - `"address_request"`

    - `Contacts object { contacts, type }`

      One or more contact cards.

      - `contacts: array of object { name, addresses, birthday, 4 more }`

        The contact cards to send. The channel permits far more; this API caps a message at five, because a message carrying hundreds of cards is a mistake rather than a use case.

        - `name: object { formatted_name, first_name, last_name, 3 more }`

          - `formatted_name: string`

            The contact's full display name.

          - `first_name: optional string`

          - `last_name: optional string`

          - `middle_name: optional string`

          - `prefix: optional string`

          - `suffix: optional string`

        - `addresses: optional array of object { city, country, country_code, 4 more }`

          - `city: optional string`

          - `country: optional string`

          - `country_code: optional string`

          - `kind: optional string`

            A label for the address, e.g. WORK, HOME.

          - `state: optional string`

          - `street: optional string`

          - `zip: optional string`

        - `birthday: optional string`

          The contact's birthday as YYYY-MM-DD.

        - `emails: optional array of object { email, kind }`

          - `email: string`

          - `kind: optional string`

            A label for the address, e.g. WORK, HOME.

        - `org: optional object { company, department, title }`

          - `company: optional string`

          - `department: optional string`

          - `title: optional string`

        - `phones: optional array of object { phone, kind, messaging_id }`

          - `phone: string`

            The phone number, ideally in +E.164 form.

          - `kind: optional string`

            A label for the number, e.g. CELL, MAIN, WORK, HOME.

          - `messaging_id: optional string`

            The contact's messaging-account identifier on this channel, when known — makes the card openable in the messaging app.

        - `urls: optional array of object { url, kind }`

          - `url: string`

          - `kind: optional string`

            A label for the URL, e.g. WORK, HOME.

      - `type: "contacts"`

        - `"contacts"`

    - `Location object { latitude, longitude, type, 2 more }`

      A location pin.

      - `latitude: number`

        Latitude in decimal degrees.

      - `longitude: number`

        Longitude in decimal degrees.

      - `type: "location"`

        - `"location"`

      - `address: optional string`

        The place's address, shown under the name.

      - `name: optional string`

        The place's name, shown on the pin.

    - `Reaction object { emoji, type, channel_message_id, message_id }`

      An emoji reaction to an earlier message in the chat. The two identifiers are distinct namespaces: inbound reactions carry the channel's opaque channel_message_id; outbound reactions will carry this API's message_id once sending them becomes available.

      - `emoji: string`

        A single emoji. Send an empty string to remove a previous reaction to the same message.

      - `type: "reaction"`

        - `"reaction"`

      - `channel_message_id: optional string`

        Inbound only: the channel's opaque identifier for the message being reacted to. Match it literally to Message.channel_message_id in the chat transcript; never parse it or compare it with Message.id.

      - `message_id: optional string`

        Outbound only: this API's Message.id for the message being reacted to. Outbound reactions are not available yet; when they land, the API resolves this identifier into the channel namespace before sending.

    - `InteractiveReply object { id, kind, title, 2 more }`

      Inbound only — never sendable. The customer's selection from an interactive_list (kind list_reply) or interactive_buttons (kind button_reply) message, carrying the id you assigned to the chosen row or button.

      - `id: string`

        The id you assigned to the chosen row or button.

      - `kind: "list_reply" or "button_reply"`

        Which interactive message kind was answered.

        - `"list_reply"`

        - `"button_reply"`

      - `title: string`

        The chosen row's or button's visible title.

      - `type: "interactive_reply"`

        - `"interactive_reply"`

      - `description: optional string`

        The chosen list row's secondary text, when it had one.

    - `AddressReply object { type, values, saved_address_id }`

      Inbound only: the structured values submitted in response to an address request.

      - `type: "address_reply"`

        - `"address_reply"`

      - `values: object { address, building_name, city, 8 more }`

        - `address: optional string`

        - `building_name: optional string`

        - `city: optional string`

        - `floor_number: optional string`

        - `house_number: optional string`

        - `landmark_area: optional string`

        - `name: optional string`

        - `phone_number: optional string`

        - `pin_code: optional string`

        - `state: optional string`

        - `tower_number: optional string`

      - `saved_address_id: optional string`

        Identifier of the selected saved address, when one was selected.

    - `Order object { catalog_id, items, type, text }`

      Inbound only — never sendable. An order the customer placed from a product catalog.

      - `catalog_id: string`

        The catalog the ordered items belong to.

      - `items: array of object { currency, price, product_retailer_id, quantity }`

        The ordered items.

        - `currency: string`

          ISO 4217 currency code for price.

        - `price: number`

          The per-item price at order time.

        - `product_retailer_id: string`

          Your identifier for the product, as registered in the catalog.

        - `quantity: number`

      - `type: "order"`

        - `"order"`

      - `text: optional string`

        Free text the customer attached to the order, when any.

    - `Referral object { type, body, click_id, 7 more }`

      Inbound only — never sendable. The ad or post context a customer's first message arrived from (for example an ad whose call to action opens a chat). A referral also opens a free-entry-point customer window — see the chat's customer_window.

      - `type: "referral"`

        - `"referral"`

      - `body: optional string`

        The ad's body text at click time.

      - `click_id: optional string`

        The click identifier assigned by the ad platform, for attribution.

      - `headline: optional string`

        The ad's headline at click time.

      - `image_url: optional string`

        URL of the ad's image creative, when media_kind is image.

      - `media_kind: optional string`

        The ad creative's media kind, e.g. image or video.

      - `source_id: optional string`

        The ad or post id.

      - `source_kind: optional string`

        What the source was, e.g. ad or post.

      - `source_url: optional string`

        The URL of the ad or post the customer came from.

      - `video_url: optional string`

        URL of the ad's video creative, when media_kind is video.

    - `System object { body, type, event }`

      Inbound only — never sendable. A system event in the chat, such as the customer changing their number. New event kinds appear over time; body is always present and human-readable.

      - `body: string`

        Human-readable description of the system event.

      - `type: "system"`

        - `"system"`

      - `event: optional string`

        The system event's kind, when the channel identifies one. New kinds appear over time — treat unknown values as informational.

    - `Unsupported object { raw, type, kind }`

      Inbound only — never sendable. A message kind this API does not yet type natively, carried as a typed passthrough: raw holds the channel payload, so a new message kind is never a black box or a silent drop. Native part types for popular kinds are added over time; this part is the compatibility guarantee in the meantime.

      - `raw: unknown`

        The channel payload — any JSON value: object, array, string, number, boolean, or null. Deliberately unconstrained, because the whole point of this part is to carry a shape this API does not yet know. For rows written by API version 1.3.0 or later, object member order, number formatting and duplicated members survive storage and read-back. The canonical encoder may compact insignificant whitespace before storage. Rows written before API version 1.3.0 retain normalized JSON only: member order and number formatting may differ, and only the last duplicated member survives.

      - `type: "unsupported"`

        - `"unsupported"`

      - `kind: optional string`

        The channel's name for the message kind, when it declares one.

  - `status: string`

    The message's delivery state as last reported.

    Inbound messages read `received`: they arrived, and no delivery of ours
    ran. A message you sent starts `accepted` and moves through `sent`,
    `delivered` and `read` as the channel reports them, with `failed` as the
    definitive negative outcome.

    `unknown` means exactly that: the send is INDETERMINATE and we decline
    to guess. It is NOT terminal — an indeterminate send is never re-sent,
    and it resolves to `sent`, `delivered`, `read` or `failed` when the
    channel's own report arrives — so keep observing rather than treating it
    as an outcome.

    States are reported asynchronously on the chat's event sequence, and the
    set grows additively: treat a value you do not recognise as "no
    information" rather than failing on it.

    Retention of this published status follows the chat transcript policy:
    there is no scheduled pruning during beta, but there is no fixed minimum
    availability guarantee. The present absence of a scheduled age-based
    sweep is not a promise of indefinite availability.

    UNDER A `sk_test_` KEY THESE ARE SIMULATED. A test-key send is reported
    `sent` and then `delivered` within milliseconds, every time; `delivered`
    there means a simulator accepted it, not that a device received it. Live
    delivery can lag by hours, can never report `delivered` at all, and can
    fail after the channel accepted the message — so do not calibrate
    timeouts or "delivered means it arrived" logic against a test key.

  - `channel_message_id: optional string`

    The channel's opaque identifier for this message, when the channel has assigned one. Match an inbound reaction's `channel_message_id` to this field literally; never parse it or compare it with `id`. It is absent while an accepted outbound message has not yet received a channel identifier.

  - `failure: optional object { code, message }`

    Why a failed message failed, when we have a reason worth publishing.

    Present only on `status` `failed`, and not on every one of those: not every
    channel refusal has a reason in the published vocabulary, so a message
    that failed on the wire may carry no `failure` at all. Its absence means
    "no published reason", never "no reason".

    `status` stays the thing to branch on. This is additive detail beside it,
    so an integration written before this field existed still sees a terminal
    `failed` and behaves exactly as it did.

    - `code: string`

      The specific reason.

      `sender_deregistered` — the number this message was going out from is no
      longer a registered sending number, and the message never left. This is
      terminal: it is not a pause and it does not clear, so retrying the same
      message cannot succeed and that conversation is over. Reach this customer
      by starting a new one on another of your numbers with a template, exactly
      as you would any customer whose 24-hour window has closed; `GET /v1/chats`
      shows which number each conversation uses. You are not billed for a
      message that failed this way.

      `quality_hold_expired` — this marketing message remained held by an
      automatic safety control on its sending line for ten minutes and was not
      sent. This is terminal: retrying the same message cannot succeed on that
      conversation. Send marketing from another of your numbers with a template,
      or contact support about the sending line. You are not billed for a message
      that failed this way.

    - `message: string`

      Human-readable, written for a person reading it. Do not branch on it.

  - `from: optional string`

    The number this message left by, or arrived on, in E.164 (leading `+`).
    Every message in one conversation carries the same value — a
    conversation never moves to another number. Absent only if the number is
    no longer one of yours.

  - `from_selection: optional object { reason }`

    Present only when this service chose the sending number for you — that
    is, when you omitted `from`. A send that named `from` omits this rather
    than reporting a choice nobody made.

    - `reason: string`

      Why this number was used. Exactly one of:

      - `reused_active_chat` — this customer already had a conversation and it
        continues on the same number.
      - `new_best_number` — there was no existing conversation, so the best
        available number was chosen.

      Like every other vocabulary here it is a plain string that may grow
      additively; treat a value you do not recognise as "chosen for you".

### Example

```http
curl https://whatsapp.messages.api.linqapp.com/v1/chats/$CHAT/messages \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $LINQ_WHATSAPP_API_KEY" \
    -d '{
          "parts": [
            {
              "body": "body",
              "type": "text"
            }
          ]
        }'
```

#### Response

```json
{
  "id": "id",
  "chat_id": "chat_id",
  "created_at": "2019-12-27T18:11:19.117Z",
  "direction": "inbound",
  "parts": [
    {
      "body": "body",
      "type": "text",
      "preview_url": true
    }
  ],
  "status": "status",
  "channel_message_id": "channel_message_id",
  "failure": {
    "code": "code",
    "message": "message"
  },
  "from": "from",
  "from_selection": {
    "reason": "reason"
  }
}
```
