CollabOps

Reading a Channel

How to read a channel's messages with an incoming webhook's URL and secret — enabling, request, response, paging, errors

A tool that posts through an incoming webhook can also read that channel's messages with the same URL and secret. For example, a deploy script can check for an approval reply in the channel, or an agent can read and summarize recent conversation. Reading must be allowed per webhook. Posting is covered in Incoming Webhooks.

Allowing reads

Turn on Allow reading channel messages when you create the webhook, or for an existing webhook turn it on from the ⋯ menu in Manage webhooks. Only channel admins can change it. Turning it off blocks reads immediately. Posting and the URL and secret are unaffected.

Once reads are allowed, the secret alone can read that channel's conversation. Do not turn it on for tools that only send notifications. If the secret leaks, delete the webhook and create a new one.

Request format

ItemValueRequired
MethodGETYes
URLhttps://collabops.ai/api/v2/integration/webhook/<token>/messagesYes
Authorization headerBearer <secret> (the same value used for posting)Yes

Query

NameRequiredDescription
sinceYesRead from this time (inclusive). An ISO 8601 time with a time zone, or unix seconds.
untilNoRead up to this time (exclusive). Defaults to now. At most 7 days after since.
limitNoMessages per call. 1 to 100.
afterNoFor the next page, the next_after_cursor value from the previous response.
curl -G "https://collabops.ai/api/v2/integration/webhook/<token>/messages" \
  -H "Authorization: Bearer <secret>" \
  --data-urlencode "since=2026-10-12T09:00:00+09:00" \
  --data-urlencode "limit=50"

The + in +09:00 is read as a space in a query string. Send it with --data-urlencode as above or write it as %2B. Unix seconds avoid the problem.

Response

You get 200 with the channel's messages. Thread replies are not listed; the parent's reply_count shows how many there are. Reading does not mark anything as read.

{
  "messages": [
    {
      "id": "01a12efa-1da6-75f1-b4e2-6d3349b44b8e",
      "parent_message_id": null,
      "type": "user",
      "created_at": "2026-10-12T07:18:25.958881Z",
      "edited_at": null,
      "deleted_at": null,
      "reply_count": 1,
      "blocks": [
        {
          "id": "054968bf-26fa-490e-968e-49f29f85bb44",
          "type": "paragraph",
          "parentId": null,
          "attrs": null,
          "children": [{"text": "Nightly batch started", "marks": [{"type": "bold"}]}]
        }
      ],
      "author": {
        "user_id": "37b6a1ef-35c3-454b-b610-929e5fc99384",
        "full_name": "Deploy alerts",
        "email": "37b6a1ef-35c3-454b-b610-929e5fc99384@hooks.collabops.bot"
      }
    }
  ],
  "has_more": true,
  "next_after_cursor": "01a12efa-1da6-75f1-b4e2-6d3349b44b8e"
}
FieldDescription
messagesArray of messages. Pages advance from the oldest part of the range, but the order within a page is not defined, so sort by created_at.
has_moretrue if the same range has more messages.
next_after_cursorThe value to pass as after for the next page. null when there is none.

A message

FieldDescription
idMessage ID.
parent_message_idFor a thread reply, the parent's message ID. Replies are not listed today, so this is always null.
typeuser for messages written by people and bots, system for notices such as members being added. system messages have null blocks. More values may be added, so skip values you do not recognize.
created_at · edited_atWhen it was written and last edited (UTC).
deleted_atWhen it was deleted, for deleted messages. blocks is then null.
reply_countNumber of thread replies.
blocksThe body, in the same shape as the incoming webhook blocks format, with empty fields sent as null. You can send it back as is. See the Message Format Reference.
authorThe author's user_id · full_name · email. For messages posted by a webhook you get the webhook name and a bot-only address. null if not found.

Reactions and attachments are not included.

Getting the next page

When has_more is true, call again with the same since and until plus next_after_cursor as after. If you leave out until, "now" moves with every call, so when reading several pages set until from the first request to fix the range.

# First page — fix the range
SINCE="2026-10-12T09:00:00+09:00"
UNTIL="2026-10-12T18:00:00+09:00"
curl -sS -G "https://collabops.ai/api/v2/integration/webhook/<token>/messages" -H "Authorization: Bearer <secret>" \
  --data-urlencode "since=$SINCE" --data-urlencode "until=$UNTIL" > page1.json

# Next page — same since and until, plus after
AFTER=$(sed -n 's/.*"next_after_cursor":"\([^"]*\)".*/\1/p' page1.json)
curl -sS -G "https://collabops.ai/api/v2/integration/webhook/<token>/messages" -H "Authorization: Bearer <secret>" \
  --data-urlencode "since=$SINCE" --data-urlencode "until=$UNTIL" \
  --data-urlencode "after=$AFTER" > page2.json

For periods longer than 7 days, read in consecutive 7-day windows.

Error responses

Error bodies have the same shape as for posting (Incoming Webhooks — Error responses). Use the reason in error.title to tell causes apart.

StatusWhenWhat to do
401The secret is wrong, the webhook is turned off, or reads are not allowed. When reads are not allowed, error.title ends with read not allowed.Fix the secret, or turn on the webhook or reads.
403The webhook's channel cannot be read (for example, it was deleted)Check the channel.
404No webhook matches the token in the URLUse the URL of a newly created webhook.
422since is missing or malformed, since is later than until, the range is longer than 7 days, or limit is outside 1 to 100Fix the query.
429More than 10 calls per minute for one webhook. Counted separately from the posting limit (60 per minute).Wait the number of seconds in the Retry-After header, then call again.
503 · 502 · 504A temporary internal error or a slow responseCall again after a short wait.

Read requests are not recorded in Delivery history.

Table of Contents