# Webhooks

> Post into a channel from your own service with a secret URL.

A webhook is a secret URL that posts messages into one server text channel, without signing in and without a bot. It suits alerts, build results, game scores and anything else your own service wants to announce. The request body follows Discord's "Execute Webhook" for the parts Lamma supports, so a script written for a Discord webhook usually works once you swap the URL.

## Making a webhook

People with the **Manage webhooks** permission in a channel make its webhooks in **Server settings › Integrations**. Apps can't create webhooks.

The URL looks like this:

```
https://lammapp.sa/api/webhooks/{webhook_id}/{secret}
```

It is shown once, when the webhook is made or given a new URL. Lamma keeps only a hash of the secret, so it can't show the URL again.

> [!WARNING]
> The URL is the only credential. Anyone who has it can post until someone makes a new URL. Keep it out of public code and logs.

A webhook can post only as far as the person who made its current URL could. If they leave the server, the webhook stops for good (`403`, `webhook_paused`, `paused_reason: "maker_left"`) until someone makes a new URL. While they are timed out or can't send messages in the channel, it is paused (`paused_reason: "maker_cannot_send"`) and works again as soon as they can.

## Executing a webhook

`POST /api/webhooks/{webhook_id}/{secret}`

Send JSON with `Content-Type: application/json`. No cookie or token is needed.

```bash
curl -X POST "https://lammapp.sa/api/webhooks/<id>/<secret>?wait=true" \
  -H "Content-Type: application/json" \
  -d '{"content": "Build 42 passed", "embeds": [{"title": "Release", "description": "Version 2.1 is live", "color": 5164938}]}'
```

Answers `204 No Content`. With `?wait=true` it answers `200` with the message: `id`, `channel_id`, `guild_id`, `content`, `author`, `embeds`, `timestamp` and `webhook_id`.

| Field | Notes |
| --- | --- |
| `content` | Up to 2,000 characters. Mentions use `<@user id>`, `<@&role id>`, `@username` and `@everyone`. `<#channel id>` links a channel |
| `username` | Overrides the webhook's name for this post |
| `embeds` | Up to 10, with Discord's limits: `title` 256, `description` 4,096, `url`, `color` (a number), `timestamp`, `author.name` and `author.url`, `footer.text`, up to 25 `fields`, 6,000 characters in total |
| `cards` | Up to 5 [link cards](https://lammapp.sa/developers/link-cards), a Lamma feature. Pictures in webhook cards aren't supported yet |
| `allowed_mentions` | `parse` (`users`, `roles`, `everyone`), `users`, `roles`. Without it, mentions notify as far as the webhook's maker could mention in that channel |

### Accepted but not shown

`avatar_url`, embed `image`, `thumbnail`, `video`, `provider`, `author.icon_url` and `footer.icon_url`. Lamma never loads pictures from other sites into people's browsers, so the webhook's own picture is used instead.

### Ignored

`tts`, `flags`, `thread_id`, `thread_name`, `components`, `poll` and `applied_tags`.

### Not supported

File uploads (`multipart/form-data`) answer `415`. Editing or deleting messages through the URL, changing the webhook through the URL, and the `/slack` and `/github` variants answer `404` or `405`.

## Getting a webhook

`GET /api/webhooks/{webhook_id}/{secret}`

Returns the webhook's id, name, channel and server. Never the secret or who made it.

## Errors

| Status | Code | Meaning |
| --- | --- | --- |
| `400` | `50035` | The body is invalid |
| `400` | `50006` | The message is empty |
| `403` | `200000` | AutoMod blocked the post |
| `403` | | `webhook_paused`, see above |
| `404` | `10015` | Unknown webhook. Also for a wrong secret or a deleted channel, so the URL never says which part was wrong |
| `415` | `50109` | The body isn't JSON |
| `429` | | Rate limited. See [Rate limits](https://lammapp.sa/developers/rate-limits#webhooks) |

## How posts appear

A post shows the webhook's name (or the `username` you sent) and picture with a **Webhook** tag. Nobody can edit it, and deleting it needs Manage messages. AutoMod checks webhook posts, including the text of embeds and cards, unless a rule skips webhooks.
