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

# Overview

> The message format, the shortcuts we accept, and the markdown we support.

Block Kit is the JSON format for every message your bot sends. It is the same format on all three paths: [webhook response](/sending-messages/webhook-response), [response URL](/sending-messages/response-url), and [API key](/sending-messages/api-key).

## The standard shape

```json theme={null}
{
  "block_kit_version": "1",
  "messages": [
    {
      "mid": "reply-1",
      "metadata": { "order_id": "4821" },
      "blocks": [
        { "type": "text", "text": "Your order **#4821** has shipped!" },
        {
          "type": "button_group",
          "buttons": [
            { "action_id": "track", "label": "Track package", "value": "4821" }
          ]
        }
      ]
    }
  ]
}
```

<ResponseField name="block_kit_version" type="string">
  Currently `"1"`. Optional — leave it out and you get `"1"`. Any other value is rejected with `BLOCK_KIT_VERSION_UNSUPPORTED`.
</ResponseField>

<ResponseField name="messages" type="array" required>
  1–10 messages. Each one becomes its own chat bubble group. That lets one reply arrive as a few short bubbles instead of one wall of text.

  <Expandable title="message">
    <ResponseField name="blocks" type="array" required>
      1–25 blocks, drawn top to bottom. See [Block types](#block-types).
    </ResponseField>

    <ResponseField name="mid" type="string">
      Your own id for this message. Must match `^[a-zA-Z0-9_.:-]{1,64}$`. Send it again to [update the message](/sending-messages/updating-messages) instead of posting a copy.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      Any JSON you like, up to 2 KB. Never shown to anyone — but sent back word for word in every [interaction event](/block-kit/interactions) from this message. Use it to carry state through a button click without a database.
    </ResponseField>
  </Expandable>
</ResponseField>

Every block can also have a `block_id` (same character rules as `mid`). Leave it out and we make one, like `blk_a1b2c3d4e5f6`.

## Block types

Ten block types, each with its own page.

| Type                                             | Purpose                                  |
| ------------------------------------------------ | ---------------------------------------- |
| [`text`](/block-kit/blocks/text)                 | Markdown text                            |
| [`image`](/block-kit/blocks/image)               | A picture                                |
| [`file`](/block-kit/blocks/file)                 | A download card                          |
| [`button_group`](/block-kit/blocks/button-group) | Up to 5 buttons                          |
| [`form`](/block-kit/blocks/form)                 | Up to 10 input fields                    |
| [`card`](/block-kit/blocks/card)                 | Image, title, text, and buttons together |
| [`divider`](/block-kit/blocks/divider)           | A horizontal line                        |
| [`status`](/block-kit/blocks/status)             | Progress and state                       |
| [`page_preview`](/block-kit/blocks/page-preview) | A link card to a hosted Page             |
| [`page`](/block-kit/blocks/page)                 | Publish HTML as a Page (write-only)      |

## Shortcuts

You rarely need the full shape. We accept all of these and convert them into the standard shape for you. Your first try usually just works.

<CodeGroup>
  ```json A plain string theme={null}
  "Order refunded."
  ```

  ```json Text only theme={null}
  { "text": "Order refunded." }
  ```

  ```json Text and buttons theme={null}
  {
    "text": "Anything else?",
    "buttons": ["Yes please", "No thanks"]
  }
  ```

  ```json Just blocks theme={null}
  {
    "blocks": [{ "type": "text", "text": "Order refunded." }]
  }
  ```

  ```json A bare block theme={null}
  { "type": "text", "text": "Order refunded." }
  ```

  ```json An array of messages theme={null}
  [
    { "text": "First bubble" },
    { "text": "Second bubble" }
  ]
  ```
</CodeGroup>

### What we clean up for you

| You send                               | We store                                                                      |
| -------------------------------------- | ----------------------------------------------------------------------------- |
| A plain string where a block should be | A `text` block                                                                |
| `markdown` instead of `text`           | `text` (they mean the same; `text` wins if you send both)                     |
| `"Yes please"` in `buttons`            | `{ "action_id": "yes_please", "label": "Yes please", "value": "Yes please" }` |
| `"Billing"` in a select's `options`    | `{ "label": "Billing", "value": "Billing" }`                                  |
| A button with no `action_id`           | An `action_id` made from its label. Repeats get `_2`, `_3`                    |
| A number or true/false in a text field | The same value as a string (`42` becomes `"42"`)                              |
| `null` in an optional field            | The field is removed                                                          |
| A `status` block's `progress` of `140` | `100` — pulled back into range                                                |
| Unknown fields                         | Removed, and noted in your delivery log                                       |

We trim spaces from the ends of `label`, `title`, `name`, `action_id`, and `submit_label`. Spaces inside `text` are kept, because markdown needs them.

<Tip>
  Empty replies are fine too. An empty body or `{}` from a webhook means "got it, no message" — the typing dots stay on while you finish the work. But posting an empty body to a `response_url` is an error (`422 EMPTY_BODY`).
</Tip>

## Markdown

Markdown works in `text` blocks, `card.text`, `status.detail`, and form `help`.

**Supported:** bold, italic, strikethrough, inline code, code blocks, links, autolinks, ordered and unordered lists, quotes, headings, tables, and line breaks.

A single newline makes a line break — Slack-style, not strict CommonMark. That is what most people expect.

**Not supported:**

* **Raw HTML.** It is stripped before drawing, never run.
* **Image syntax** `![alt](url)`. It shows as a plain link — use the [`image` block](/block-kit/blocks/image) instead.
* Footnotes and task-list checkboxes.

Links can only use `https:` or `mailto:`. Anything else — including `javascript:` and `data:` — shows as plain text. Every link opens in a new tab.

<Note>
  Unicode emoji pass through untouched. `:shortcode:` emoji are not translated.
</Note>

## Versions

`block_kit_version` is a string. New things are added inside `"1"` — new block types, new optional fields, higher limits. They will not break you.

Unknown block types do not crash anything. They show as a placeholder in the app and are skipped on public pages. An old widget will not break when a new block ships.

## Next

<CardGroup cols={2}>
  <Card title="Every block type" icon="layout-grid" href="/block-kit/blocks/text">
    All ten, with full schemas.
  </Card>

  <Card title="Limits and errors" icon="triangle-alert" href="/block-kit/limits-and-errors">
    Every limit, and what happens when you cross one.
  </Card>
</CardGroup>
