Responses and errors

.md

Every status code and error message an AbabilX flock webhook can return, what each one means, and whether to retry.

Last updated

Every answer from the server is JSON with a success field. On success it also has data or duplicate; on failure it has error, a short English string that is stable enough to match on. The one exception is 404, which is plain text.

Success

StatusBodyMeaning
201 Created{"success":true,"data":{"id":"<uuid>","created_at":"<RFC 3339>"}}The message is stored and on its way to members.
200 OK{"success":true,"duplicate":true}This event_id was already posted to this flock in the last 7 days. Nothing new was stored; treat it as success.

Every error

StatuserrorCauseRetry?
400invalid request bodyBody is not one JSON object; a field is not a string; JSON over 64 KB; multipart over 351 MB or malformed; payload_json missing, empty, repeated or not JSON; an HTML form post.No. Fix the request.
400content or file is requiredNo message, no content and no files (a Slack-style {"text":…} body lands here).No.
400content exceeds 6000 charactersText over 6,000 bytes of UTF-8.No. Shorten or split it.
400content exceeds 1000 wordsText over 1,000 words.No.
400event_id too longevent_id over 200 bytes.No.
400max 10 attachments allowedMore than 10 files.No.
400invalid file sizeAn empty file, or one over 350 MB.No.
400invalid file nameA file part with no usable name, or a name over 255 bytes.No.
400attachments exceed 350 MB total limitFiles add up to more than 350 MB.No.
401unauthorizedMalformed, unknown or replaced URL; wrong secret; the flock was deleted.No. Get the current URL from the flock's owner.
404404 page not found (plain text)Wrong path, or a method other than POST.No.
429rate_limit_exceededOver 60 messages a minute for this flock, or 120 requests a minute from your IP.Yes, after Retry-After seconds.
429too many requests, slow downOver the API-wide limit for your IP.Yes, after Retry-After (1 second).
500failed to store attachmentA file could not be saved. Nothing was posted.Yes, with backoff.
500(other text)A server fault. Nothing was posted.Yes, with backoff and the same event_id.
502 / 504(proxy page)The host could not reach the server in time.Yes, with backoff and the same event_id.
503file uploads are not configuredFile storage is down. Text-only posts still work.Later, or send without files.

Checks run in this order: URL shape → IP rate limit → URL lookup → secret → flock rate limit → body. So a wrong URL can still answer 429 if it is hammered, and a bad body is only reported for a valid URL.

Example of every response

Exact bodies as the server sends them. Match on the status first, then on error.

201 Created
{
  "success": true,
  "data": {
    "id": "6f1c2a9e-5b7d-4c1e-9a43-0d2f8b7e1c55",
    "created_at": "2026-10-19T09:30:00.123456Z"
  }
}
200 OK (duplicate event_id)
{
  "success": true,
  "duplicate": true
}
400 Bad Request: body is not a JSON object
{"success":false,"error":"invalid request body"}
400 Bad Request: nothing to post
{"success":false,"error":"content or file is required"}
400 Bad Request: text too long
{"success":false,"error":"content exceeds 6000 characters"}
400 Bad Request: too many words
{"success":false,"error":"content exceeds 1000 words"}
400 Bad Request: event_id too long
{"success":false,"error":"event_id too long"}
400 Bad Request: more than 10 files
{"success":false,"error":"max 10 attachments allowed"}
400 Bad Request: empty or oversized file
{"success":false,"error":"invalid file size"}
400 Bad Request: bad file name
{"success":false,"error":"invalid file name"}
400 Bad Request: files over 350 MB together
{"success":false,"error":"attachments exceed 350 MB total limit"}
401 Unauthorized: wrong, replaced or deleted URL
{"success":false,"error":"unauthorized"}
404 Not Found (text/plain): wrong path or method
404 page not found
429 Too Many Requests: flock or IP limit
HTTP/1.1 429 Too Many Requests
Content-Type: application/json; charset=utf-8
Retry-After: 23

{"success":false,"error":"rate_limit_exceeded"}
429 Too Many Requests: API-wide limit
HTTP/1.1 429 Too Many Requests
Retry-After: 1

{"success":false,"error":"too many requests, slow down"}
500 Internal Server Error: file could not be stored
{"success":false,"error":"failed to store attachment"}
503 Service Unavailable: file storage down
{"success":false,"error":"file uploads are not configured"}

What to do with an answer

Your app

POST with an event_id

Make the id unique per real event, such as a run number or an order id.

200 or 201

Your app

Done

Both mean the message is in the flock.

429

Your app

Wait Retry-After seconds

Then send the same request again.

500, 502, 503, 504, timeout

Your app

Back off and resend

1 s, 2 s, 4 s … up to about 5 tries, same event_id, so a retry can never post twice.

400, 401, 404

Your app

Stop and alert a person

Resending will fail the same way.

Response headers

HeaderWhenValue
Content-TypeAlwaysapplication/json; charset=utf-8 (text/plain for 404)
Retry-After429Whole seconds to wait
Access-Control-Allow-OriginWhen the request has an Origin*
Access-Control-Expose-HeadersWhen the request has an OriginRetry-After

Browsers and CORS

Any website may call a flock URL. A JSON POST from a browser first sends an OPTIONS preflight, which answers 204 with Access-Control-Allow-Origin: *, Access-Control-Allow-Methods: POST, OPTIONS and any requested headers. No cookies are sent or needed, so do not set credentials: "include".

Preflight
OPTIONS /hooks/chat/<flock-id>/<secret>
Origin: https://shop.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST,OPTIONS
Access-Control-Allow-Headers: *,Content-Type,X-Webhook-Event-Id
Access-Control-Max-Age: 43200