> ## Documentation Index
> Fetch the complete documentation index at: https://docs.keebai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /v1/messages/mark-read

> Mark an inbound message as read and optionally show the typing indicator.

Turns the recipient's single grey ticks into blue ones and, optionally, shows them a typing indicator while your integration composes a reply.

This is the one endpoint in the messaging surface that does not send anything, so it does not consume the 24-hour window and does not create a message.

## Endpoint

```
POST https://api.keebai.com/v1/messages/mark-read
```

## Required scope

`messages:send`

## Headers

| Header          | Required | Value                    |
| --------------- | -------- | ------------------------ |
| `Authorization` | Yes      | `Bearer kbai_pk_<token>` |
| `Content-Type`  | Yes      | `application/json`       |

## Body

| Field              | Type     | Required | Description                                                                                                        |
| ------------------ | -------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
| `channel_id`       | `string` | No       | Keebai channel id of the WhatsApp channel. Only needed when the project has more than one active WhatsApp channel. |
| `phone_number_id`  | `string` | No       | Alias for `channel_id`: the WhatsApp Business `phone_number_id` that received the message.                         |
| `message_id`       | `string` | Yes      | Meta `message_id` (`wamid.*`) to mark as read.                                                                     |
| `typing_indicator` | `string` | No       | `text` shows the typing bubble; `off` hides it.                                                                    |

There is no `to` — the message id already identifies the conversation.

## Example request

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.keebai.com/v1/messages/mark-read \
    -H "Authorization: Bearer kbai_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
    -H "Content-Type: application/json" \
    -d '{
      "phone_number_id": "109876543210987",
      "message_id": "wamid.HBgLNTQ5MTE1NTU1NTU1FQIAERgSN0EyRjc4",
      "typing_indicator": "text"
    }'
  ```

  ```js JavaScript theme={null}
  await fetch("https://api.keebai.com/v1/messages/mark-read", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.KEEBAI_API_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      phone_number_id: "109876543210987",
      message_id: inboundMessageId,
      typing_indicator: "text",
    }),
  });
  ```

  ```python Python theme={null}
  import os, requests

  resp = requests.post(
      "https://api.keebai.com/v1/messages/mark-read",
      headers={"Authorization": f"Bearer {os.environ['KEEBAI_API_TOKEN']}"},
      json={
          "phone_number_id": "109876543210987",
          "message_id": inbound_message_id,
          "typing_indicator": "text",
      },
      timeout=10,
  )
  resp.raise_for_status()
  ```
</CodeGroup>

## Response

### 200 OK

```json theme={null}
{
  "success": true
}
```

Note this returns `200`, not the `202` the send endpoints use — nothing is queued.

### 400 Bad Request

A missing `message_id`, a `typing_indicator` other than `text` or `off`, or an unknown property.

### 401 Unauthorized

Missing, invalid, revoked, or expired token.

### 403 Forbidden

The token does not have the `messages:send` scope.

## Operational notes

* **The typing indicator lasts about 25 seconds** or until you send a message, whichever comes first. Meta gives no way to extend it, so calling this immediately before a slow LLM round trip is the intended pattern.
* **Marking as read is not reversible.** There is no way to go back to grey ticks.
* **Read receipts respect the recipient's privacy settings.** If they have read receipts disabled, the call succeeds and nothing visible changes on their side.


## OpenAPI

````yaml POST /v1/messages/mark-read
openapi: 3.0.0
info:
  title: Keebai Public API
  description: Superficie pública REST autenticada con Personal Access Tokens (PAT).
  version: 1.0.0
  contact: {}
servers:
  - url: https://api.keebai.com
    description: Production
security: []
tags: []
paths:
  /v1/messages/mark-read:
    post:
      tags:
        - messages
      summary: Mark a received message as read (optionally show typing)
      description: WhatsApp Cloud API only.
      operationId: PublicMessagesController_markRead
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MarkReadDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarkReadResponse'
      security:
        - PAT: []
components:
  schemas:
    MarkReadDto:
      type: object
      properties:
        channel_id:
          type: string
          example: 665f1a2b3c4d5e6f70819234
          description: >-
            Keebai channel id. Optional when the tenant has exactly one active
            channel of the given type; required to disambiguate otherwise.
        phone_number_id:
          type: string
          example: '100000000000001'
          description: >-
            WhatsApp-only alias for channel_id: the Meta phone_number_id of the
            sending number. Ignored on other channels.
        message_id:
          type: string
          description: Meta message_id (wamid.*) to mark as read.
        typing_indicator:
          type: string
          enum:
            - text
            - 'off'
      required:
        - message_id
    MarkReadResponse:
      type: object
      properties:
        success:
          type: boolean
      required:
        - success
  securitySchemes:
    PAT:
      scheme: bearer
      bearerFormat: kbai_pk_<hex>
      type: http
      description: >-
        Personal Access Token con prefijo `kbai_pk_`. Generar desde el portal
        con permiso `developer.manage_tokens`.

````