Post to a flock

.md

Webhook API reference for AbabilX flocks: endpoint, request formats (JSON, text/plain, multipart with files), every field, and every limit.

Last updated

Quick reference
EndpointPOST https://<host>/hooks/chat/<flock-id>/<secret>
AuthThe secret in the URL. No header, token or cookie.
BodyJSON object, or multipart/form-data when sending files
Success201 Created, or 200 when event_id repeats
CORSAny origin, no credentials; preflight allowed
Rate60 messages a minute per flock, 120 requests a minute per IP
Machine-readable spec/openapi/flock-webhook.json (OpenAPI 3.1)

Quick start

  1. 1Create a flock and copy its webhook URL (see Flocks).
  2. 2Save it as the environment variable ABABILX_WEBHOOK_URL.
  3. 3Send one request:
curl
curl -sS -X POST "$ABABILX_WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d '{"message":"Deployment of v2.4.1 finished"}'

Response, status 201:

json
{"success":true,"data":{"id":"6f1c2a9e-5b7d-4c1e-9a43-0d2f8b7e1c55","created_at":"2026-10-19T09:30:00.123456Z"}}

The URL

Use the URL exactly as the app showed it. Its shape is https://<host>/hooks/chat/<flock-id>/<secret>. The host may be chat.ababilx.com, workspace.ababilx.com or api.ababilx.com: all three reach the same server, so a URL keeps working whichever one it names.

  • flock-id is a UUID.
  • secret is 64 hex characters. Anyone with it can post, so keep it out of logs, screenshots and public repositories.
  • Only POST is served. Any other method, or any other path, answers 404.

Send text (JSON)

The body must be one JSON object. Every field is a string. Unknown fields are ignored.

FieldTypeRequiredNotes
messagestringYes, unless files are attachedThe text. Markdown is rendered: **bold**, _italic_, `code`, code blocks, lists, links, headings. Leading and trailing whitespace is trimmed.
contentstringNoUsed only when message is empty or missing.
event_idstringNoUp to 200 bytes. The same id within 7 days stores nothing new (see Responses). The X-Webhook-Event-ID header works too; the body wins if both are set.
Full body
{
  "message": "**Build failed** on `main`\n\n- job: test\n- commit: a1b0fbe\n\n[Open the run](https://ci.example.com/runs/812)",
  "event_id": "ci-run-812"
}

Slack-style bodies do not work as they are. A body with only a text field ({"text":"…"}) has no message, so it answers 400 content or file is required. Rename text to message.

Request examples

Smallest body
{"message": "Deployment finished"}
With an event_id (safe to retry)
{
  "message": "Order #1042 paid: 2,450 BDT",
  "event_id": "order-1042-paid"
}
Markdown
{
  "message": "## Build failed\n\n**Branch:** `main`\n**Commit:** a1b0fbe\n\n- test: 3 failed\n- lint: ok\n\n[Open the run](https://ci.example.com/runs/812)"
}
Code block inside the message
{
  "message": "Error in checkout:\n\n```\nTypeError: cannot read 'total' of undefined\n    at pay (cart.js:41)\n```"
}
content instead of message (same result)
{"content": "Disk on db-1 is 91% full"}
payload_json for a files-only post (multipart field)
{}
event_id as a header instead of a field
curl -sS -X POST "$ABABILX_WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -H 'X-Webhook-Event-ID: backup-2026-10-19' \
  -d '{"message":"Backup finished"}'
These do NOT work
{"text": "hi"}            → 400 content or file is required (use "message")
{"message": 42}            → 400 invalid request body (must be a string)
["hello"]                  → 400 invalid request body (must be an object)
message=hello (form post)  → 400 invalid request body (send JSON)

Content-Type

Content-Type sentHow the body is read
application/jsonJSON object. The normal choice.
text/plain (or none)Also read as JSON. Useful in a browser: a text/plain POST needs no CORS preflight.
multipart/form-datapayload_json field holds the JSON; files[n] fields hold files.
application/x-www-form-urlencodedNot supported: the body is read as JSON and fails with 400 invalid request body.

Send files (multipart)

Send multipart/form-data. Put the JSON body, as text, in a field named payload_json (exactly one). Put each file in its own field named files[0], files[1] … files[9]. A message may be files only: send payload_json as {}.

curl
curl -sS -X POST "$ABABILX_WEBHOOK_URL" \
  -F 'payload_json={"message":"Nightly report","event_id":"report-2026-10-19"}' \
  -F 'files[0]=@report.pdf' \
  -F 'files[1]=@chart.png;type=image/png'
  • Up to 10 files per message, 350 MB in total, and no empty files.
  • Any file type. Send the right Content-Type on each part so pictures and videos are shown inline; unknown types arrive as downloadable files.
  • File names: up to 255 bytes; any folder part of the name is dropped.
  • Files show in the order of their field names, so use files[0] to files[9].
  • Fields not named payload_json or files[n] are ignored.

All limits

WhatLimitOver the limit
Text length6,000 bytes of UTF-8 (about 6,000 English letters or 2,000 Bangla letters)400 content exceeds 6000 characters
Words1,000400 content exceeds 1000 words
JSON body64 KB400 invalid request body
Multipart body351 MB400 invalid request body
Files per message10400 max 10 attachments allowed
File size1 byte to 350 MB each, 350 MB together400 invalid file size / attachments exceed 350 MB total limit
event_id200 bytes400 event_id too long
Messages per flock60 in any 60 seconds429 rate_limit_exceeded
Requests per IP to flock URLs120 in any 60 seconds (wrong URLs count too)429 rate_limit_exceeded
Requests per IP to the whole API100 at once, then 50 a second429 too many requests, slow down