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

# Incoming Webhooks

> Post messages to a MeepaChat channel via HTTP POST

Incoming webhooks let any service post messages to a MeepaChat channel with a single HTTP request. No OAuth, no bot account — just a URL and a JSON body.

## Create a webhook

**Via the Developer Portal:**

1. Go to `/developer` on your MeepaChat instance
2. Select **Webhooks** → **New Webhook**
3. Choose a server and channel
4. Copy the webhook URL

**Via API:**

```bash theme={null}
curl -X POST https://chat.example.com/api/webhooks \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"channel_id": "CHANNEL_ID", "name": "My Webhook"}'
```

The response includes the webhook `token`. The full URL is:

```
https://chat.example.com/api/webhooks/{token}
```

<Warning>
  Treat webhook tokens like passwords. Anyone with the URL can post to that channel.
</Warning>

## Post a message

```bash theme={null}
curl -X POST https://chat.example.com/api/webhooks/YOUR_TOKEN \
  -H "Content-Type: application/json" \
  -d '{"content": "Hello from my integration!"}'
```

A `200 OK` response confirms delivery. The message appears in the channel attributed to the webhook name.

## Message format

```json theme={null}
{
  "content": "Plain text message",
  "embeds": [...],
  "thread_key": "optional-grouping-key"
}
```

All fields are optional, but at least one of `content` or `embeds` must be present.

### `content`

Plain text displayed as the message body. Supports the same formatting as regular messages (bold, code blocks, etc.).

### `thread_key`

A string that groups related messages into a thread. Messages with the same `thread_key` are collapsed under a single thread in the channel. Useful for grouping all notifications from the same PR, issue, or deployment.

```json theme={null}
{
  "content": "Build failed",
  "thread_key": "build-pr-42"
}
```

### `embeds`

Rich cards attached to the message. Up to 10 embeds per message.

```json theme={null}
{
  "embeds": [
    {
      "title": "Pull Request #42 merged",
      "description": "Add support for dark mode",
      "url": "https://github.com/org/repo/pull/42",
      "color": "#6e40c9",
      "author": {
        "name": "alice",
        "icon_url": "https://github.com/alice.png",
        "url": "https://github.com/alice"
      },
      "fields": [
        { "name": "Repository", "value": "org/repo", "inline": true },
        { "name": "Branch", "value": "main", "inline": true }
      ],
      "footer": {
        "text": "GitHub",
        "icon_url": "https://github.com/favicon.ico"
      }
    }
  ]
}
```

#### Embed fields

| Field             | Type   | Description                                    |
| ----------------- | ------ | ---------------------------------------------- |
| `title`           | string | Bold title text                                |
| `description`     | string | Body text, supports markdown                   |
| `url`             | string | Makes the title a clickable link               |
| `color`           | string | Left border color as hex, e.g. `"#2ea44f"`     |
| `author.name`     | string | Author name shown above title                  |
| `author.icon_url` | string | Author avatar URL                              |
| `author.url`      | string | Author name link                               |
| `fields`          | array  | List of `{name, value, inline}` key-value rows |
| `footer.text`     | string | Footer text shown below fields                 |
| `footer.icon_url` | string | Footer icon URL                                |
| `thumbnail.url`   | string | Small image shown top-right                    |
| `image.url`       | string | Large image shown below fields                 |
| `timestamp`       | string | ISO 8601 timestamp shown in footer             |

## Examples

<CodeGroup>
  ```bash Success notification theme={null}
  curl -X POST https://chat.example.com/api/webhooks/TOKEN \
    -H "Content-Type: application/json" \
    -d '{
      "embeds": [{
        "title": "Deployment succeeded",
        "description": "v2.4.1 is live on production",
        "color": "#2ea44f",
        "fields": [
          { "name": "Environment", "value": "production", "inline": true },
          { "name": "Duration", "value": "2m 14s", "inline": true }
        ]
      }]
    }'
  ```

  ```bash Failure alert theme={null}
  curl -X POST https://chat.example.com/api/webhooks/TOKEN \
    -H "Content-Type: application/json" \
    -d '{
      "content": "Build failed on main",
      "embeds": [{
        "title": "Test suite failed",
        "description": "23 tests failed in `auth` package",
        "color": "#d73a49",
        "url": "https://ci.example.com/builds/1234",
        "footer": { "text": "CI Pipeline" }
      }],
      "thread_key": "build-main-1234"
    }'
  ```

  ```bash Simple ping theme={null}
  curl -X POST https://chat.example.com/api/webhooks/TOKEN \
    -H "Content-Type: application/json" \
    -d '{"content": "Server is back online"}'
  ```
</CodeGroup>

## Rate limiting

Webhooks are subject to per-token rate limits. Exceeding the limit returns `429 Too Many Requests` with a `Retry-After` header indicating how many seconds to wait.

See [Rate Limiting](/meepachat/rate-limiting) for full details.

## Security

If you control both ends (e.g., a GitHub webhook posting to MeepaChat via your own relay), verify the incoming signature before forwarding. The [Worker template](/meepachat/integrations/apps#starter-template) includes HMAC-SHA256 signature verification out of the box.
