For AI agents: markdown of this page — /docs-content-en/chats/events/poll.md documentation index — /llms.txt

Get events

GET /v1/chats/events

Returns accumulated messenger user events starting from the specified position. The offset parameter is required — pass 0 on the first call, then nextOffset from each response.

Requires a prior subscription. Without an active subscription events are not accumulated and the response will be empty.

Parameters

Parameter Type Required Default Description
offset (query) number yes Starting position. First call: 0. Subsequent calls: the nextOffset value from the previous response
limit (query) number no 100 Maximum number of events per call (1–1000)

Examples

curl — personal key

Terminal
curl "https://vibecode.bitrix24.com/v1/chats/events?offset=0&limit=50" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl "https://vibecode.bitrix24.com/v1/chats/events?offset=0&limit=50" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"

JavaScript — personal key

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/events?offset=0&limit=50', {
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { success, data } = await res.json()
console.log('Events:', data.events.length, 'Next offset:', data.nextOffset)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/events?offset=0&limit=50', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { success, data } = await res.json()

Response fields

Field Type Description
success boolean Always true on success
data object Result container
data.events array Array of events
data.events[].eventId number Event identifier. Used as offset in the next request
data.events[].type string Event type (ONIMV2MESSAGEADD, ONIMV2JOINCHAT, etc.)
data.events[].date string Event date and time (ISO 8601)
data.events[].data object Event data. Structure depends on the type, fields in camelCase
data.nextOffset number Value for the offset parameter in the next request
data.hasMore boolean true — there are more events beyond the current response

Response example

There are new events:

JSON
{
  "success": true,
  "data": {
    "events": [
      {
        "eventId": 101,
        "type": "ONIMV2JOINCHAT",
        "date": "2026-06-05T10:00:00+00:00",
        "data": {
          "dialogId": "chat100",
          "chat": {
            "id": 100,
            "name": "Project chat",
            "type": "open"
          },
          "user": {
            "id": 42,
            "name": "John Smith"
          }
        }
      },
      {
        "eventId": 103,
        "type": "ONIMV2MESSAGEADD",
        "date": "2026-06-05T10:01:30+00:00",
        "data": {
          "message": {
            "id": 500,
            "chatId": 100,
            "text": "Hi everyone!"
          },
          "chat": {
            "id": 100,
            "name": "Project chat"
          },
          "user": {
            "id": 42,
            "name": "John Smith"
          }
        }
      }
    ],
    "nextOffset": 104,
    "hasMore": false
  }
}

Empty response (no new events):

JSON
{
  "success": true,
  "data": {
    "events": [],
    "nextOffset": 104,
    "hasMore": false
  }
}

Error response example

400 — the required offset parameter was not provided:

JSON
{
  "success": false,
  "error": {
    "code": "MISSING_PARAMS",
    "message": "Query parameter `offset` is required. Pass `0` for the first call, then `nextOffset` from each response to advance the cursor."
  }
}

Errors

HTTP Code Description
400 MISSING_PARAMS The offset parameter is missing or empty
400 INVALID_OFFSET The offset value is not a non-negative integer (fractional, negative, leading zeros, extraneous characters)
400 INVALID_LIMIT The limit value is outside the range 1–1000 or is not an integer
403 SCOPE_DENIED The API key does not have the im scope
401 TOKEN_MISSING The API key has no configured tokens
422 BITRIX_ERROR Bitrix24 returned an error (error text in message)
502 BITRIX_UNAVAILABLE Bitrix24 is unavailable or returned a server error

Full list of common API errors — Errors.

Event types

The type field of each event is one of the codes:

Event Description
ONIMV2MESSAGEADD New message in a subscribed chat
ONIMV2MESSAGEUPDATE Message edited
ONIMV2MESSAGEDELETE Message deleted
ONIMV2JOINCHAT A participant joined the chat
ONIMV2REACTIONCHANGE A message reaction changed

Known specifics

Token is required. For a personal key vibe_api_… the X-Api-Key header is enough. For an OAuth key vibe_app_… you must also add Authorization: Bearer <session_token> — without it the request returns 401 TOKEN_MISSING. Obtaining a token for an OAuth application — see Keys and authorization.

Cursor on the client side. Unlike bot event polling, this endpoint does not store the offset position in the database — cursor management is on the calling code's side. On the first call pass offset=0, on subsequent calls — the nextOffset value from the previous response.

Request chain:

GET /v1/chats/events?offset=0   → { nextOffset: 104, hasMore: true }
GET /v1/chats/events?offset=104 → { nextOffset: 112, hasMore: false }
GET /v1/chats/events?offset=112 → { events: [], hasMore: false }

Recommended polling interval: 2–5 seconds between requests. On an empty response do not increase the frequency — events will be delivered on the next call. More about limits — Limits and optimization.

Polling loop (ready-to-use example):

javascript
const API_KEY = 'YOUR_API_KEY'
const BASE = 'https://vibecode.bitrix24.com/v1'

async function pollChatEvents() {
  // Subscribe first — without a subscription events are not accumulated
  await fetch(`${BASE}/chats/events/subscribe`, {
    method: 'POST',
    headers: { 'X-Api-Key': API_KEY },
  })

  let offset = 0

  while (true) {
    try {
      const res = await fetch(`${BASE}/chats/events?offset=${offset}`, {
        headers: { 'X-Api-Key': API_KEY },
      })
      const { data } = await res.json()

      for (const event of data.events ?? []) {
        await handleEvent(event)
      }

      if (data.nextOffset !== undefined) {
        offset = data.nextOffset
      }

      if (!data.hasMore) {
        await new Promise(r => setTimeout(r, 3000))
      }
    } catch (err) {
      console.error('Polling error:', err.message)
      await new Promise(r => setTimeout(r, 5000))
    }
  }
}

async function handleEvent(event) {
  switch (event.type) {
    case 'ONIMV2MESSAGEADD':
      console.log('New message:', event.data.message?.text)
      break
    case 'ONIMV2JOINCHAT':
      console.log('Participant joined the chat:', event.data.chat?.name)
      break
    case 'ONIMV2MESSAGEDELETE':
      console.log('Message deleted:', event.data.message?.id)
      break
    default:
      console.log('Event:', event.type)
  }
}

pollChatEvents()

See also