For AI agents: markdown of this page — /docs-content-en/entities/timelines/file-download.md documentation index — /llms.txt
Download a timeline comment attachment
GET /v1/timelines/:commentId/files/:fileRef/download
Downloads a file attached to a timeline comment. The response is a binary stream with a Content-Disposition header.
The endpoint accepts two different identifiers in fileRef, because a client may hold either one:
- Attachment ID. The account interface shows it, and file user-fields return it. This path computes access through the carrier entity — the comment itself — rather than through personal Disk permissions, so it reaches attachments that Disk file download refuses to serve;
- Disk object ID. This is the object key in the
filesfield of theGET /v1/timelines/:idresponse. The path goes through personal Disk permissions, so it can be refused where the attachment-ID path would have succeeded.
The comment itself is read first, then the Disk object ID is tried, and the attachment ID only when the comment does not list that reference among its files. You do not have to state which identifier you are passing. This order is cheaper: the documented case costs two Bitrix24 calls instead of three.
Parameters
| Parameter | In | Type | Req. | Description |
|---|---|---|---|---|
commentId |
path | number | yes | Timeline comment ID. Get it from GET /v1/timelines |
fileRef |
path | number | yes | Attachment ID or Disk object ID. The latter is the object key in the files field of the GET /v1/timelines/:id response |
The request body is empty.
Examples
curl — personal key
# By Disk object ID — the key from the files field of the comment response
curl -OJ -H "X-Api-Key: YOUR_API_KEY" \
https://vibecode.bitrix24.com/v1/timelines/67689/files/9747/download
# By attachment ID — when you have one
curl -OJ -H "X-Api-Key: YOUR_API_KEY" \
https://vibecode.bitrix24.com/v1/timelines/67689/files/551/download
curl — OAuth application
curl -OJ \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
https://vibecode.bitrix24.com/v1/timelines/67689/files/9747/download
JavaScript — personal key
// Take the attachment identifiers from the comment response
const comment = await fetch(
'https://vibecode.bitrix24.com/v1/timelines/67689',
{ headers: { 'X-Api-Key': 'YOUR_API_KEY' } },
).then(r => r.json())
for (const objectId of Object.keys(comment.data.files ?? {})) {
const res = await fetch(
`https://vibecode.bitrix24.com/v1/timelines/67689/files/${objectId}/download`,
{ headers: { 'X-Api-Key': 'YOUR_API_KEY' } },
)
if (!res.ok) {
const { error } = await res.json()
console.warn(`${objectId}: ${error.code}`)
continue
}
console.log(objectId, 'bytes:', (await res.arrayBuffer()).byteLength)
}
JavaScript — OAuth application
const res = await fetch(
'https://vibecode.bitrix24.com/v1/timelines/67689/files/9747/download',
{
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
},
)
const bytes = await res.arrayBuffer()
Response headers
On success the binary file content is returned (HTTP 200). There is no ## Response fields section — the response body is not JSON.
| Header | Example value | Description |
|---|---|---|
Content-Type |
image/gif |
Content type exactly as Bitrix24 returned it |
Content-Disposition |
attachment; filename="scan.pdf" |
File name to save under |
Content-Length |
43 |
Size in bytes when Bitrix24 reported it |
Error response example
404 — the attachment belongs to a different comment:
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Attachment 551 does not belong to comment 11111"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_PARAMS |
commentId or fileRef is not a positive integer |
| 401 | TOKEN_MISSING |
The key has no configured Bitrix24 tokens |
| 403 | SCOPE_DENIED |
The key lacks the crm scope |
| 404 | NOT_FOUND |
The comment does not exist, the attachment belongs to another comment or to a different kind of record (a task, a quote), or its membership in the comment could not be confirmed, the file is not among its files, or the file has no download address |
| 502 | DOWNLOAD_FAILED |
Bitrix24 did not return the file, or named an address outside the account domain — no request is sent to such an address |
The full list of common API errors — Errors.
Known specifics
- The attachment must belong to the named comment. Otherwise
404. Without that check the endpoint would allow enumerating the account's attachments. - The address is never returned. The download address contains an authorization code, so the endpoint returns bytes only.
- The
urlDownloadfield from the comment response does not work directly. That address points at a Disk page rather than at REST and cannot be authorized with a key: requesting it redirects to the sign-in page. Download through this endpoint instead. - The two paths grant different access. If the Disk object ID is refused on permissions and you have the attachment ID, try it: it computes access through the comment rather than through personal storage.
- The download address is verified, redirects included. It arrives in the Bitrix24 response, so the endpoint checks it against the account domain and sends no request to a foreign address — an authorization code would otherwise go there. The endpoint walks redirects itself, checking every hop: the chain is bounded in length and in time, and a redirect to an internal address is not followed and answers
502. - A temporary failure is not disguised as
404. When Bitrix24 answers with a request limit, is unavailable, or the repeated-error guard trips, that is what comes back —429or502/503with aRetry-Afterheader, not «the file does not belong to the comment». So a404here always means the reference itself is wrong: retrying it is pointless, whereas a429/5xxshould be retried with a delay.