# Poll

## Get a poll's current tally

`messages.poll.retrieve(strmessage_id)  -> PollEnvelope`

**get** `/v3/messages/{messageId}/poll`

Return a poll's current results — its options, each option's voters, and the distinct
total number of voters — by the poll-definition message's ID.

### Parameters

- `message_id: str`

### Returns

- `class PollEnvelope: …`

  Message-level envelope returned by every poll endpoint.

  - `chat_id: str`

  - `created_at: datetime`

  - `message_id: str`

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

  - `poll: Poll`

    Poll content — options and the aggregate voter count.

    - `options: List[Option]`

      - `can_be_edited: bool`

      - `creator_handle: ChatHandle`

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

        - `id: str`

          Unique identifier for this handle

        - `handle: str`

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

        - `joined_at: datetime`

          When this participant joined the chat

        - `service: ServiceType`

          Messaging service type

          - `"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)

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

          Participant status

          - `"active"`

          - `"left"`

          - `"removed"`

      - `option_id: str`

      - `text: str`

      - `voters: List[OptionVoter]`

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

        - `handle: str`

        - `voted_at: datetime`

    - `total_voters: int`

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

  - `reactions: List[Reaction]`

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

    - `handle: ChatHandle`

    - `is_me: bool`

      Whether this reaction is from the current user

    - `type: ReactionType`

      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.

      - `"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).

      - `width: Optional[int]`

        Sticker image width in pixels

  - `updated_at: datetime`

### Example

```python
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
)
poll_envelope = client.messages.poll.retrieve(
    "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
)
print(poll_envelope.chat_id)
```

#### Response

```json
{
  "chat_id": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2019-12-27T18:11:19.117Z",
  "message_id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
  "poll": {
    "options": [
      {
        "can_be_edited": true,
        "creator_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"
        },
        "option_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
        "text": "Tacos",
        "voters": [
          {
            "handle": "+14155559876",
            "voted_at": "2019-12-27T18:11:19.117Z"
          }
        ]
      }
    ],
    "total_voters": 0
  },
  "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
      }
    }
  ],
  "updated_at": "2019-12-27T18:11:19.117Z"
}
```

# Options

## Add options to a poll

`messages.poll.options.create(strmessage_id, OptionCreateParams**kwargs)  -> PollEnvelope`

**post** `/v3/messages/{messageId}/poll/options`

Add one or more options to an existing poll. Options are **add-only and immutable** — you
can append options but never edit or remove them (Apple constraint). Returns the full poll.

### Parameters

- `message_id: str`

- `options: Iterable[Option]`

  - `text: str`

### Returns

- `class PollEnvelope: …`

  Message-level envelope returned by every poll endpoint.

  - `chat_id: str`

  - `created_at: datetime`

  - `message_id: str`

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

  - `poll: Poll`

    Poll content — options and the aggregate voter count.

    - `options: List[Option]`

      - `can_be_edited: bool`

      - `creator_handle: ChatHandle`

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

        - `id: str`

          Unique identifier for this handle

        - `handle: str`

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

        - `joined_at: datetime`

          When this participant joined the chat

        - `service: ServiceType`

          Messaging service type

          - `"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)

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

          Participant status

          - `"active"`

          - `"left"`

          - `"removed"`

      - `option_id: str`

      - `text: str`

      - `voters: List[OptionVoter]`

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

        - `handle: str`

        - `voted_at: datetime`

    - `total_voters: int`

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

  - `reactions: List[Reaction]`

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

    - `handle: ChatHandle`

    - `is_me: bool`

      Whether this reaction is from the current user

    - `type: ReactionType`

      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.

      - `"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).

      - `width: Optional[int]`

        Sticker image width in pixels

  - `updated_at: datetime`

### Example

```python
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
)
poll_envelope = client.messages.poll.options.create(
    message_id="69a37c7d-af4f-4b5e-af42-e28e98ce873a",
    options=[{
        "text": "Pizza"
    }],
)
print(poll_envelope.chat_id)
```

#### Response

```json
{
  "chat_id": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2019-12-27T18:11:19.117Z",
  "message_id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
  "poll": {
    "options": [
      {
        "can_be_edited": true,
        "creator_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"
        },
        "option_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
        "text": "Tacos",
        "voters": [
          {
            "handle": "+14155559876",
            "voted_at": "2019-12-27T18:11:19.117Z"
          }
        ]
      }
    ],
    "total_voters": 0
  },
  "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
      }
    }
  ],
  "updated_at": "2019-12-27T18:11:19.117Z"
}
```

# Votes

## Toggle a vote on a poll option

`messages.poll.votes.create(strmessage_id, VoteCreateParams**kwargs)  -> PollEnvelope`

**post** `/v3/messages/{messageId}/poll/votes`

Add or remove your line's vote on **one** poll option (per-option toggle — iMessage polls
are toggled one option at a time). Returns the poll reflecting the toggle.

### Parameters

- `message_id: str`

- `operation: Literal["add", "remove"]`

  Add or remove your line's vote on the option.

  - `"add"`

  - `"remove"`

- `option_id: str`

  The option to toggle a vote on.

### Returns

- `class PollEnvelope: …`

  Message-level envelope returned by every poll endpoint.

  - `chat_id: str`

  - `created_at: datetime`

  - `message_id: str`

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

  - `poll: Poll`

    Poll content — options and the aggregate voter count.

    - `options: List[Option]`

      - `can_be_edited: bool`

      - `creator_handle: ChatHandle`

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

        - `id: str`

          Unique identifier for this handle

        - `handle: str`

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

        - `joined_at: datetime`

          When this participant joined the chat

        - `service: ServiceType`

          Messaging service type

          - `"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)

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

          Participant status

          - `"active"`

          - `"left"`

          - `"removed"`

      - `option_id: str`

      - `text: str`

      - `voters: List[OptionVoter]`

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

        - `handle: str`

        - `voted_at: datetime`

    - `total_voters: int`

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

  - `reactions: List[Reaction]`

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

    - `handle: ChatHandle`

    - `is_me: bool`

      Whether this reaction is from the current user

    - `type: ReactionType`

      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.

      - `"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).

      - `width: Optional[int]`

        Sticker image width in pixels

  - `updated_at: datetime`

### Example

```python
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
)
poll_envelope = client.messages.poll.votes.create(
    message_id="69a37c7d-af4f-4b5e-af42-e28e98ce873a",
    operation="add",
    option_id="97ce8c17-7ef6-4bbc-a89a-6b93d189712f",
)
print(poll_envelope.chat_id)
```

#### Response

```json
{
  "chat_id": "550e8400-e29b-41d4-a716-446655440000",
  "created_at": "2019-12-27T18:11:19.117Z",
  "message_id": "69a37c7d-af4f-4b5e-af42-e28e98ce873a",
  "poll": {
    "options": [
      {
        "can_be_edited": true,
        "creator_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"
        },
        "option_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
        "text": "Tacos",
        "voters": [
          {
            "handle": "+14155559876",
            "voted_at": "2019-12-27T18:11:19.117Z"
          }
        ]
      }
    ],
    "total_voters": 0
  },
  "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
      }
    }
  ],
  "updated_at": "2019-12-27T18:11:19.117Z"
}
```
