---
title: Polls | API Docs
description: Send a poll into a chat, add options, vote, and read the tally.
---

Polls let a chat vote on a set of options inline, without leaving the conversation. They are an iMessage feature — see [Protocol Selection](/guides/messaging/protocol-selection/index.md) for what each protocol supports.

Two things shape everything below:

- **The chat must already exist.** A poll cannot be the first message of a new chat — create the chat with [`POST /v3/chats`](/api/resources/chats/methods/create/index.md) first.
- **Options are add-only.** Once an option exists it can never be edited or removed. You can append new ones for the life of the poll.

## Create a poll

- [cURL](#tab-panel-110)

Terminal window

```
curl -X POST https://api.linqapp.com/api/partner/v3/chats/{chatId}/polls \
  -H "Authorization: Bearer $LINQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "poll": {
        "options": [
          {
            "text": "Tacos"
          },
          {
            "text": "Sushi"
          }
        ],
        "idempotency_key": "poll-abc123"
      }
    }'
```

| Field  | Required | Type     | Description |
| ------ | -------- | -------- | ----------- |
| `poll` | Yes      | `object` | —           |

A poll needs **at least two options**, and has no title or question field — send the question as a normal text message before the poll if you need one. Pass `idempotency_key` to make retries safe.

The response is a poll envelope. Its `message_id` is the poll-definition message, and it is how you reference this poll from every other endpoint — hold on to it. See the [Create Poll API reference](/api/resources/chats/subresources/polls/methods/create/index.md).

202, not 201

Every write here returns `202` — the poll is accepted for delivery, not confirmed delivered. The terminal outcome arrives on the [webhooks](#webhooks) below.

## Add options

- [cURL](#tab-panel-109)

Terminal window

```
curl -X POST https://api.linqapp.com/api/partner/v3/messages/{messageId}/poll/options \
  -H "Authorization: Bearer $LINQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "options": [
        {
          "text": "Pizza"
        }
      ]
    }'
```

Appends options and returns the full poll. Anyone in the chat can add options, not just the creator — an inbound add arrives as a `poll.updated` webhook carrying only the new options. See the [Add Options API reference](/api/resources/messages/subresources/poll/methods/add_options/index.md).

## Vote

- [cURL](#tab-panel-108)

Terminal window

```
curl -X POST https://api.linqapp.com/api/partner/v3/messages/{messageId}/poll/votes \
  -H "Authorization: Bearer $LINQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "option_id": "97ce8c17-7ef6-4bbc-a89a-6b93d189712f",
      "operation": "add"
    }'
```

Votes are a **per-option toggle**: one call changes one option, with `operation` set to `add` or `remove`. A voter picking three options is three calls, and three separate `poll.vote.added` webhooks. See the [Vote API reference](/api/resources/messages/subresources/poll/methods/vote/index.md).

## Read the tally

- [cURL](#tab-panel-107)

Terminal window

```
curl https://api.linqapp.com/api/partner/v3/messages/{messageId}/poll \
  -H "Authorization: Bearer $LINQ_API_KEY"
```

Returns the poll’s current state: every option, the voters on each, and `total_voters`. Note that `total_voters` counts **distinct participants** — someone who voted for two options counts once — so it will not match the sum of the per-option voter counts. See the [Get Poll API reference](/api/resources/messages/subresources/poll/methods/retrieve/index.md).

You do not have to poll `GET /v3/messages/{messageId}/poll` to stay current; the webhooks below carry each change as it happens.

## Webhooks

Nine events cover the poll lifecycle. See [Webhook Events](/guides/webhooks/events/index.md) for payload schemas and [Webhooks](/guides/webhooks/index.md) for setup.

| Event                 | Fires when                                     |
| --------------------- | ---------------------------------------------- |
| `poll.received`       | A participant sends a poll to your line        |
| `poll.sent`           | A poll you created leaves the device           |
| `poll.delivered`      | That poll reaches the recipient                |
| `poll.read`           | The recipient reads it                         |
| `poll.updated`        | Someone adds options to an existing poll       |
| `poll.failed`         | An outbound poll or poll action failed to send |
| `poll.vote.added`     | A participant votes for an option              |
| `poll.vote.removed`   | A participant takes a vote back                |
| `poll.reaction.added` | Someone reacts to the poll message             |

Poll reactions are stickers, which cannot be removed, so `poll.reaction.added` has no removal counterpart.

## Important notes

- **iMessage only** — polls are not available on RCS or SMS.
- **The chat must exist first** — a poll cannot open a new chat.
- **No question field** — send the question as a separate text message.
- **Two options minimum**, and options are add-only and immutable once created.
- **One option per vote call** — votes toggle per option, not as a set.
- **Reference the poll by `message_id`**, the poll-definition message returned by create.

## Related

- [Reactions](/guides/messaging/reactions/index.md) — tapbacks, including on a poll message
- [Sending Messages](/guides/messaging/sending-messages/index.md) — the text message that carries your question
- [Webhook Events](/guides/webhooks/events/index.md) — every poll payload shape
