## List of sticker packs

`GET /v1/chats/stickers/packs`

Returns the current user's sticker packs page by page: user packs (`custom`) first, then built-in ones (`vendor`). The first page comes from the messenger v2 method `im.v2.Sticker.Pack.load` and also carries the user's recent stickers. Subsequent pages come from `im.v2.Sticker.Pack.tail`: to get them, pass the `id` and `type` of the last pack of the previous page.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|----------|
| `limit` | number | no | Packs per page: 10 by default, from 1 to 200. An out-of-range value is clamped to the nearest bound; the requested and applied values are returned in `meta` |
| `lastId` | number | no | Cursor: `id` of the last pack of the previous page. Passed only together with `lastType` |
| `lastType` | string | no | Cursor: `type` of the last pack of the previous page — `vendor` or `custom`. Passed only together with `lastId` |

Without a cursor the first page is returned. Other parameters, a repeated parameter or only one half of the cursor are rejected with `400 INVALID_PARAMS` before the Bitrix24 call.

## Examples

### curl — personal key

```bash
curl "https://vibecode.bitrix24.com/v1/chats/stickers/packs?limit=20" \
  -H "X-Api-Key: YOUR_API_KEY"
```

### curl — OAuth application

```bash
curl "https://vibecode.bitrix24.com/v1/chats/stickers/packs?limit=20&lastId=14&lastType=vendor" \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN"
```

### JavaScript — personal key

```javascript
// All packs: keep paging while hasNextPage; the cursor is the last pack of the page
const packs = new Map()
let cursor = ''
for (;;) {
  const res = await fetch(`https://vibecode.bitrix24.com/v1/chats/stickers/packs?limit=50${cursor}`, {
    headers: { 'X-Api-Key': 'YOUR_API_KEY' },
  })
  const { data } = await res.json()
  for (const pack of data.packs) packs.set(`${pack.type}:${pack.id}`, pack)
  const last = data.packs.at(-1)
  if (!data.hasNextPage || !last) break
  cursor = `&lastId=${last.id}&lastType=${last.type}`
}
console.log('Packs:', packs.size)
```

### JavaScript — OAuth application

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

const { data } = await res.json()
console.log('Recent stickers:', data.recentStickers.length)
```

## Response fields

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | Always `true` on success |
| `data.packs` | array | Packs of the page |
| `data.packs[].id` | number | Pack ID. Unique only together with `type` |
| `data.packs[].type` | string | `custom` — a user pack, `vendor` — a built-in pack |
| `data.packs[].name` | string | Pack name |
| `data.packs[].authorId` | number \| null | ID of the author of a user pack; `null` for a built-in pack |
| `data.packs[].isAdded` | boolean | The pack is in the user's list |
| `data.stickers` | array | Stickers of the page's packs and, on the first page, also the recent stickers |
| `data.stickers[].id` | number | Sticker ID |
| `data.stickers[].packId` | number | ID of the sticker's pack |
| `data.stickers[].packType` | string | Kind of the sticker's pack |
| `data.stickers[].uri` | string | Path to the image in the Bitrix24 account — relative, without the domain |
| `data.stickers[].type` | string | Sticker type (`image`) |
| `data.stickers[].width` | number | Image width in pixels |
| `data.stickers[].height` | number | Image height in pixels |
| `data.stickers[].sort` | number | Sticker order in the pack |
| `data.recentStickers` | array | First page only: stickers the user sent recently, at most 12, newest first — `{ id, packId, packType }` |
| `data.hasNextPage` | boolean | There is a next page |
| `meta.requestedLimit` | number | The `limit` passed — only if it was clamped to a bound |
| `meta.appliedLimit` | number | The `limit` applied — only if it was clamped to a bound |

## Response example

```json
{
  "success": true,
  "data": {
    "stickers": [
      { "id": 1, "uri": "/upload/im/stickers/3/1.png", "type": "image", "width": 512, "height": 512, "packId": 3, "packType": "custom", "sort": 1 },
      { "id": 2, "uri": "/bitrix/images/im/stickers/aiHelp/2.png?v1", "type": "image", "width": 512, "height": 512, "packId": 14, "packType": "vendor", "sort": 2 }
    ],
    "packs": [
      { "id": 3, "name": "Work stickers", "type": "custom", "authorId": 7, "isAdded": true },
      { "id": 14, "name": "AI, help", "type": "vendor", "authorId": null, "isAdded": true }
    ],
    "recentStickers": [
      { "id": 2, "packId": 14, "packType": "vendor" }
    ],
    "hasNextPage": true
  }
}
```

## Error response example

400 — only one half of the cursor was passed:

```json
{
  "success": false,
  "error": {
    "code": "INVALID_PARAMS",
    "message": "`lastId` needs `lastType`: pass the `id` and the `type` of the last pack of the previous page together."
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `INVALID_PARAMS` | An unknown or repeated parameter, an invalid `limit`, `lastId` without `lastType` or the other way round, `lastId` is not a positive integer, `lastType` is neither `vendor` nor `custom` |
| 401 | `TOKEN_MISSING` | The key has no configured Bitrix24 tokens |
| 403 | `SCOPE_DENIED` | The key lacks the `im` scope |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | The first page (`Pack.load`) requires a write-capable key; cursor pages remain readable |
| 404 | `ENTITY_NOT_FOUND` | Bitrix24 did not find the object; the portal code is in `error.b24Code` if supplied |
| 422 | `BITRIX_ERROR` | Bitrix24 returned an error; the Bitrix24 code is in `error.b24Code` |
| 502 | `BITRIX_UNAVAILABLE` | Bitrix24 is unavailable or returned a server error |

Full list of common API errors — [Errors](/docs/errors).

## Known specifics

- The last page may be empty, with `hasNextPage: false`.
- If the cursor pack was deleted or removed from the list between requests, the list of user packs starts over from the beginning. Deduplicate packs by the `type` and `id` pair.
- `recentStickers` arrives on the first page only. The first request deletes recent-sticker rows beyond 12, so it is classified as a write: a read-only key receives `403 WRITE_BLOCKED_READONLY_KEY` before any Bitrix24 call. Cursor pages (`Pack.tail`) remain reads.
- `uri` is a path in the Bitrix24 account. The full image address is the Bitrix24 account domain plus `uri`.
- Response keys are converted to camelCase; values arrive as is.

## See also

- [Sticker pack](/docs/chats/stickers/pack)
- [Recent stickers](/docs/chats/stickers/recent)
- [Stickers](/docs/chats/stickers)
