For AI agents: markdown of this page — /docs-content-en/entities/activities/file-download.md documentation index — /llms.txt

Download an activity file

GET /v1/activities/:activityId/files/:fileId/download

Downloads a file attached to a CRM activity, including a call recording. The response is a binary stream with a Content-Disposition header.

This endpoint exists because an activity file is not a Disk file. GET /v1/activities/:id returns each file as { id, url }, where the id lives in a separate identifier space that overlaps Disk object ids. Passing such an id to Disk file download is not safe: it may well return a different file. And the address in the url field arrives with an empty authorization parameter, so requesting it returns the sign-in page with code 200 — not a file. This endpoint adds the authorization itself and returns the content.

Parameters

Parameter In Type Req. Description
activityId path number yes Activity ID. Get it from GET /v1/activities
fileId path number yes File ID from the activity files array. Get it from GET /v1/activities/:id with files included in select

The request body is empty.

Examples

curl — personal key

Terminal
# Save under the original name from the Content-Disposition header
curl -OJ -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/activities/4257/files/5387/download

# Set the file name explicitly
curl -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/activities/4257/files/5387/download \
  -o call-record.mp3

curl — OAuth application

Terminal
curl -OJ \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  https://vibecode.bitrix24.com/v1/activities/4257/files/5387/download

JavaScript — personal key

javascript
const res = await fetch(
  'https://vibecode.bitrix24.com/v1/activities/4257/files/5387/download',
  { headers: { 'X-Api-Key': 'YOUR_API_KEY' } },
)

if (!res.ok) {
  const { error } = await res.json()
  throw new Error(`${error.code}: ${error.message}`)
}

const audio = await res.arrayBuffer()
console.log('bytes received:', audio.byteLength)

JavaScript — OAuth application

javascript
const res = await fetch(
  'https://vibecode.bitrix24.com/v1/activities/4257/files/5387/download',
  {
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  },
)

const audio = 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 audio/mpeg Content type exactly as Bitrix24 returned it
Content-Disposition attachment; filename="call-record.mp3" File name to save under
Content-Length 22509 Size in bytes when Bitrix24 reported it

Error response example

404 — the file does not belong to this activity:

JSON
{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "File 999999 does not belong to activity 4257"
  }
}

Errors

HTTP Code Description
400 INVALID_PARAMS activityId or fileId 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 activity does not exist, the file does not belong to it, or the file has no download address
502 DOWNLOAD_FAILED Bitrix24 named an address outside the account domain (no request is sent to such an address), or did not return the file. This includes answering with a page instead of the content, which means the key could not be authorized for that file

The full list of common API errors — Errors.

Known specifics

  • The file must belong to the named activity. Otherwise 404, even when the file exists. The check is not pedantry: Bitrix24 answers a foreign file with 200 and a sign-in page, so without it you would receive HTML posing as the file.
  • Permissions are not bypassed. Reading the activity IS the access check: a key without access to the activity gets a refusal. Bitrix24 additionally verifies the user's access to the activity on its side.
  • The address is never returned. The download address contains an authorization code, so the endpoint returns bytes only.
  • Files are not always present in the activity response. In the activity list the files field is returned only when named in select. For a single activity it arrives with no extra conditions.

See also