Anten
Türkçe

Developers

Webhooks

Post into a room in Anten with a single HTTP request; for example when a build finishes or a service goes down.

For
Room managers and developers
Time
5 minutes
You need
The Manage webhooks permission
You get
Your program posts into a room

A webhook is a secret address: a program that sends an HTTP request to it posts a message into a room in Anten. Your build server can say “build finished”, your monitoring tool can report an outage. The program needs no Anten account.

What it is for

A webhook works one way: the program writes into the room, but cannot read it or answer anyone. The message shows under the name you gave the webhook, with a BOT tag.

If the program has to read messages, answer commands or join a voice room, use a bot account instead (see the bots guide).

Make a webhook

  1. Open the room’s settings. Right-click the room in the room list and choose Room settings, or press the settings icon in the room’s header.
  2. Under Integrations, choose Webhooks. Only those with the Manage webhooks permission in that room see this part. Administrators have it.
  3. Enter a name and press Make a webhook. The name may be 1–32 characters. The program’s messages show under it; for example “Builds”.
  4. Copy the address shown and keep it somewhere safe. The address is shown only this once. Right below it there is a ready curl command with that address.

The address has this form:

https://anten.example.org/api/v1/webhooks/<id>/<token>

The token at the end is the webhook’s password. Anyone who knows the whole address can write into that room.

Send a first message

  1. Put the address in an environment variable. All the examples read it from ANTEN_WEBHOOK, so the address is never written into code.

    export ANTEN_WEBHOOK='https://anten.example.org/api/v1/webhooks/<id>/<token>'
    
  2. Send a message. The request is JSON with a single field, content.

    curl -H "Content-Type: application/json" -d '{"content":"Build finished"}' "$ANTEN_WEBHOOK"
    
  3. Look at the room. The message shows under the webhook’s name with a BOT tag. On success the server answers 200 with the new message.

Send from a program

Both examples use only the language’s own libraries and print the status and the error’s code if something goes wrong.

Node.js (18 or later)

const res = await fetch(process.env.ANTEN_WEBHOOK, {
	method: 'POST',
	headers: { 'Content-Type': 'application/json' },
	body: JSON.stringify({ content: 'Build finished' })
});
if (!res.ok) {
	const err = await res.json().catch(() => ({}));
	console.error('Webhook error:', res.status, err.code);
}

Python

import json, os, urllib.error, urllib.request

req = urllib.request.Request(
    os.environ["ANTEN_WEBHOOK"],
    data=json.dumps({"content": "Build finished"}).encode(),
    headers={"Content-Type": "application/json"},
)
try:
    urllib.request.urlopen(req)
except urllib.error.HTTPError as e:
    print("Webhook error:", e.code, e.read().decode())

Messages and limits

What can be sent

  • Text only: 1–4000 characters. Spaces at the start and end are dropped.
  • Formatting such as bold, italic, code and quotes shows as in other messages. HTML is never rendered.
  • Files, buttons and cards cannot be sent. A request with any field other than content is refused.

The name

Messages always show under the webhook’s name; a request cannot change it. If you give the webhook a new name with Rename, it shows only on messages from then on. Earlier messages keep the name they were posted under.

Limits

  • A webhook may send 10 messages in a row, then one a second.
  • All webhook requests from one IP address are limited too: 30 in a row, then 5 a second. Requests with a wrong token count as well.
  • A request over the limit gets 429. Wait as many seconds as the Retry-After header says, then try again.
  • A room can have up to 10 webhooks. A request body may be at most 16 KB.

What happens to the messages

A webhook’s messages cannot be edited. Those with the Manage messages permission in the room can delete them. When a webhook is deleted, the messages it sent stay in the room. The Webhooks list also shows when each webhook was last used.

Security

Keep the address like a password

Anyone who knows the address can write into that room without an account. Do not put it in a code repository, a chat or an error log. Give it to the program through an environment variable or the secret settings of the system you use.

The server keeps only a digest (SHA-256) of the token, not the token itself. That is why the address cannot be shown again later. The token is not written to the server’s logs either.

Renew or delete the address

If you lost the address or suspect it has leaked, press Renew address next to the webhook. The old address stops working at once, and the new one is shown once. Give the program the new address.

If you no longer need the webhook, press Delete. Making, renaming, renewing and deleting are recorded in the audit log.

Why not in encrypted rooms

In an end-to-end encrypted room, only the devices of the people in it encrypt and open messages; the server does not hold the room’s key. A webhook’s message is written by the server, so it cannot encrypt it. An unencrypted message is not let into an encrypted room either.

So a webhook cannot be made in an encrypted room. If a room is made encrypted later, its webhooks get 409 room_sealed, and the room’s Webhooks part says so with a notice.

Reference

Request

POST /api/v1/webhooks/<id>/<token>
Content-Type: application/json

{ "content": "Build finished" }

No session or other header is needed. A successful request answers 200 with the new message as JSON (id, room_id, content, webhook, created_at and other fields).

Error responses

An error response carries a code field and a short explanation (message).

Status code Meaning
400 invalid_content The message is empty or longer than 4000 characters
400 invalid_json The body is not valid JSON, or has a field other than content
401 invalid_webhook The address is wrong or was renewed, or the webhook was deleted
409 room_sealed The room is end-to-end encrypted
409 text_disabled Text chat is off in the room
413 body_too_large The body is larger than 16 KB
415 unsupported_media_type The Content-Type header is not application/json
429 rate_limited Too many requests; wait as Retry-After says