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

Pinned messages

GET /v1/chats/:dialogId/pins · POST /v1/chats/messages/:messageId/pin · DELETE /v1/chats/messages/:messageId/pin · GET /v1/chats/:dialogId/pins/count

Four endpoints work with the pinned messages of a chat: the list of pins, pinning, unpinning and the number of pins. They run the v2 messenger methods im.v2.Chat.Pin.tail, im.v2.Chat.Message.pin, im.v2.Chat.Message.unpin and im.v2.Chat.Pin.count. Pinning and unpinning resolve the chat from the message, so they need no dialogId.

List pins

GET /v1/chats/:dialogId/pins

Returns the pins of a chat, latest first by default. The pinned messages themselves come alongside, in data.additionalMessages. The me alias as dialogId addresses the current user's personal dialog — see more in the Chats overview.

Parameters

Parameter Type Required Default Description
dialogId (path) string yes — Dialog ID: numeric user ID for personal messages, chatXXX for group chats. The special me alias — the current user's personal dialog
lastId (query) number no — Cursor: the id of the last pin of the previous page — a pin ID, not a message ID. The boundary itself is not included
order (query) string no desc desc — latest pins first, asc — earliest first
limit (query) number no 50 Pins per page, from 1 to 200: a value outside the range is clamped and echoed in meta.requestedLimit and meta.appliedLimit

Any other parameter or a repeated parameter is rejected with 400 INVALID_PARAMS.

Examples

curl — personal key

Terminal
curl -X GET "https://vibecode.bitrix24.com/v1/chats/chat42/pins" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl -X GET "https://vibecode.bitrix24.com/v1/chats/chat42/pins" \
  -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/chat42/pins', {
  method: 'GET',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { data } = await res.json()
const byId = new Map((data.additionalMessages ?? []).map((m) => [m.id, m]))
console.log('Pinned:', data.pins.map((p) => byId.get(p.messageId)?.text))

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/chat42/pins', {
  method: 'GET',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { data } = await res.json()
const byId = new Map((data.additionalMessages ?? []).map((m) => [m.id, m]))
console.log('Pinned:', data.pins.map((p) => byId.get(p.messageId)?.text))

Response fields

Field Type Description
success boolean Always true on success
data.pins array Pins on the page
data.pins[].id number Pin ID. The list is paged by it
data.pins[].messageId number ID of the pinned message
data.pins[].chatId number Chat ID
data.pins[].authorId number ID of the user who pinned the message
data.pins[].dateCreate string When the message was pinned (ISO 8601)
data.additionalMessages array The pinned messages: id, chatId, authorId, date, text, params and other v2 message fields
data.users array Users referenced by the pins and the pinned messages
data.files array Files of the pinned messages
data.reactions array Reactions to the pinned messages
data.tariffRestrictions object Plan restrictions on the history: isHistoryLimitExceeded
meta.requestedLimit number The limit passed, when it was outside the range from 1 to 200
meta.appliedLimit number The limit value applied

The response also includes stickers, forwardSource and copilot — collections of the v2 message history common to all responses that carry messages.

Response example

JSON
{
  "success": true,
  "data": {
    "pins": [
      {
        "id": 17,
        "messageId": 1001,
        "chatId": 42,
        "authorId": 5,
        "dateCreate": "2026-09-20T10:06:00+00:00"
      }
    ],
    "additionalMessages": [
      {
        "id": 1001,
        "chatId": 42,
        "authorId": 5,
        "date": "2026-09-20T10:00:00+00:00",
        "text": "Please review the mockup",
        "params": { "isPinned": "Y" }
      }
    ],
    "users": [],
    "files": [],
    "reactions": [],
    "stickers": [],
    "forwardSource": null,
    "copilot": null,
    "tariffRestrictions": { "isHistoryLimitExceeded": false }
  }
}

Pin a message

POST /v1/chats/messages/:messageId/pin

Pins a message in its chat. No body and no query parameters are accepted.

Examples

curl — personal key

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/chats/messages/1001/pin" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/chats/messages/1001/pin" \
  -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/messages/1001/pin', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { data } = await res.json()
console.log('Result:', data)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/messages/1001/pin', {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { data } = await res.json()
console.log('Result:', data)

Response on success: { "success": true, "data": [] }.

Unpin a message

DELETE /v1/chats/messages/:messageId/pin

Removes the pin from a message. No body and no query parameters are accepted.

Examples

curl — personal key

Terminal
curl -X DELETE "https://vibecode.bitrix24.com/v1/chats/messages/1001/pin" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl -X DELETE "https://vibecode.bitrix24.com/v1/chats/messages/1001/pin" \
  -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/messages/1001/pin', {
  method: 'DELETE',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
  },
})

const { data } = await res.json()
console.log('Result:', data)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/messages/1001/pin', {
  method: 'DELETE',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { data } = await res.json()
console.log('Result:', data)

Response on success: { "success": true, "data": [] }.

Number of pins

GET /v1/chats/:dialogId/pins/count

Returns how many messages are pinned in the chat. dialogId works the same as for the pins list, including the me alias. Query parameters are rejected with 400 INVALID_PARAMS.

Examples

curl — personal key

Terminal
curl "https://vibecode.bitrix24.com/v1/chats/chat42/pins/count" \
  -H "X-Api-Key: YOUR_API_KEY"

curl — OAuth application

Terminal
curl "https://vibecode.bitrix24.com/v1/chats/chat42/pins/count" \
  -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/chat42/pins/count', {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})

const { data } = await res.json()
console.log('Pinned:', data.counter)

JavaScript — OAuth application

javascript
const res = await fetch('https://vibecode.bitrix24.com/v1/chats/chat42/pins/count', {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})

const { data } = await res.json()
console.log('Pinned:', data.counter)

Response fields

Field Type Description
success boolean Always true on success
data.counter number Number of pinned messages

Response example

JSON
{
  "success": true,
  "data": { "counter": 2 }
}

Error response example

422 — the message is already pinned:

JSON
{
  "success": false,
  "error": {
    "code": "BITRIX_ERROR",
    "message": "MESSAGE_IS_ALREADY_PIN",
    "b24Code": "MESSAGE_IS_ALREADY_PIN"
  }
}

Errors

HTTP Code Description
400 INVALID_PARAMS messageId is not a positive integer; for the list — a parameter other than lastId, order, limit, a repeated parameter or an invalid value; for pinning and unpinning — any body field or query parameter; for the number of pins — any query parameter. Checked before any call to Bitrix24
404 ENTITY_NOT_FOUND Bitrix24 reported "not found"; the portal code is in error.b24Code
422 BITRIX_ERROR Bitrix24 returned an error; the code is in error.b24Code: MESSAGE_IS_ALREADY_PIN — the message is already pinned, MESSAGE_NOT_FOUND — there is no such message, CHAT_NOT_FOUND — there is no such chat
403 SCOPE_DENIED The API key does not have the im scope
403 WRITE_BLOCKED_READONLY_KEY A read-only key cannot add or remove pins; the list and count are allowed reads — see access rights
401 TOKEN_MISSING The API key has no Bitrix24 tokens configured
502 ME_ALIAS_RESOLUTION_FAILED The me alias could not be resolved: Bitrix24 returned no ID of the current user

Full list of common API errors — Errors.

Known specifics

The pins list and count may make you a member. When the chat allows auto-join, either read may add the current user as a member, as loading a chat does. A READONLY key may use both audited reads; neither marks messages read.

There is no next-page flag. Bitrix24 returns no hasNextPage for pins. To get the next page, pass lastId equal to the id of the last pin on the page; a page shorter than limit is the last one.

The response for an empty list is shorter. For a chat without pins, only pins, users and tariffRestrictions are returned. The other collections appear with the first pin, so read them with a fallback value.

Pinning shows in the chat. Bitrix24 posts a system message about the pin to the chat, quoting the pinned text. Pinning again is refused with MESSAGE_IS_ALREADY_PIN; unpinning again succeeds.

The number of pins covers only the visible history. If you can see the chat history only from a certain point on — for example, you were added later without access to older messages — pins before that point are not counted.

See also