لوكلاء AI: ملف markdown لهذه الصفحة — /docs-content-en/source-storage.md فهرس التوثيق — /llms.txt

مقالات التوثيق متاحة حاليًا باللغة الإنجليزية فقط.

Source code storage

Source code storage automatically saves snapshots of your application's code on every deploy. If someone else or a new AI session starts working on the application, they can download the latest version and continue from the same point — the code is not lost.

Documentation sections

Why it matters

When you are refining an application, it is important not to lose the working version of the code. Source code storage does that automatically: on every successful deploy the platform saves a snapshot of the sources. If someone else or a new AI session starts working on the application later, they download the latest version and continue from the same point, without manually passing archives around.

A snapshot belongs to the application rather than to a particular developer: the code stays with the application even when the team changes.

How it differs from Git and GitHub

This is not a version control system and not a replacement for Git. Source code storage covers a narrower need — a safety net and project handoff.

Source code storage Git / GitHub
What it stores Source code storagewhole archive snapshots of the code Git / GitHubchange history line by line
When it saves Source code storageautomatically on every deploy Git / GitHubmanually, on a developer's command
Git skills required Source code storageno Git / GitHubyes
Branches, merges, version comparison Source code storageno Git / GitHubyes

If you need team development with branches and history, use Git. If you just need to avoid losing working code and to be able to return to a previous version, storage is enough.

How it works

  1. You refine the application and start a deploy.
  2. The platform saves a source snapshot on its own — the next version: v1, v2, v3, …
  3. At any time you can list the versions and download the one you need.
  4. Before the application is published, the platform checks that a snapshot has been saved.
edit code  →  deploy  →  snapshot vN saved automatically
                                      ↓
        list versions  →  download any  →  continue work

Core concepts

  • Snapshot — an archived copy of the application's source code at the moment of saving.
  • Version vN — the sequence number of a snapshot (v1, v2, …). The newest one is considered current.
  • Tag — a manual or published label: marks a version as important so automatic cleanup does not delete it.
  • Deduplication — if the code has not changed, no new snapshot is created and the existing version is returned. Applies within a single owner — a server or an application.

Access

Base URL: https://vibecode.bitrix24.com/v1
Authorization: the X-Api-Key header. Snapshots can be managed by the application authorization key (vibe_app_*), the application author's personal key (vibe_api_*), or a Bitrix24 account administrator.
Allowed archive formats: application/gzip, application/x-tar, application/zip, application/octet-stream.
Body limit: 500 MB per request.

Save contract

The body of POST …/sources is the raw archive bytes, not multipart/form-data. Metadata travels in headers, not as form fields and not as query parameters.

Header Required Description
HeaderContent-Type Requiredyes DescriptionAn archive format from the list above. Any other value → 400 INVALID_CONTENT_TYPE
HeaderContent-Length Requiredyes DescriptionBody size in bytes. Without it (Transfer-Encoding: chunked) → 411 MISSING_CONTENT_LENGTH
HeaderX-Filename Requiredno DescriptionDisplay filename. If it is not provided, the name is derived from Content-Type. Characters outside a-zA-Z0-9._- → 400 INVALID_FILENAME
HeaderX-Tags Requiredno DescriptionComma-separated tags. manual and published are recognized — they protect the version from automatic cleanup
HeaderX-Note Requiredno DescriptionA note stored with the version record
HeaderX-AI-Session-Id Requiredno DescriptionAI session identifier — groups snapshots in the manifest
Terminal
curl -X POST https://vibecode.bitrix24.com/v1/apps/<APP_ID>/sources \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Content-Type: application/gzip" \
  -H "X-Tags: manual" \
  -H "X-Note: Added OAuth flow" \
  --data-binary @app-sources.tar.gz

The code source for a deploy — the source field of POST /v1/infra/servers/:id/deploy accepts three mutually exclusive forms:

Form What it is
Formsource.content What it isAn inline base64 archive — always works, including on a Galaxy app
Formsource.url What it isA signed link from Vibecode storage. On a Galaxy app this must be enabled for you separately
Formsource.versionId What it isAn already saved version of the form vN. On a Galaxy app this must be enabled for you separately

The full walkthrough of saving — Save a snapshot. Auto-save and deploying from a version — Automatic save on deploy.

Quick start

Handing the project over to another developer or a new AI session takes three calls:

Terminal
# 1. What is already saved for this application
curl -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/apps/<APP_ID>/sources

# 2. A link to the archive of the version you need (valid for 30 minutes)
curl -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/apps/<APP_ID>/sources/v1/download

# 3. Download the archive using that link — no additional headers
curl -o source-v1.tar.gz "<url from the response above>"

Full example

One continuous scenario: save a snapshot, list the versions, download the archive from its link and verify the checksum, then delete the version. The code runs in Node.js 18 or later: save it in an .mjs file, place the app-sources.tar.gz archive next to it, replace <APP_ID> with your application ID, and pass the key in the VIBE_KEY environment variable.

javascript
import { readFile } from 'node:fs/promises'
import { createHash } from 'node:crypto'

const VIBE_KEY = process.env.VIBE_KEY
const SOURCES = 'https://vibecode.bitrix24.com/v1/apps/<APP_ID>/sources'

async function api(method, path = '', init = {}) {
  const res = await fetch(`${SOURCES}${path}`, {
    ...init,
    method,
    headers: { 'X-Api-Key': VIBE_KEY, ...init.headers },
  })
  const json = await res.json()
  if (!json.success) {
    throw new Error(`${method} ${path} → ${res.status} ${json.error.code}`)
  }
  return json.data
}

// 1. Save a snapshot: the body is the raw archive bytes,
//    fetch sets the body length itself
const archive = await readFile(
  new URL('./app-sources.tar.gz', import.meta.url),
)
const saved = await api('POST', '', {
  headers: { 'Content-Type': 'application/gzip' },
  body: archive,
})
if (saved.skipped) {
  throw new Error(`Source storage is disabled: ${saved.reason}`)
}
console.log(
  'Version:', saved.versionId,
  '| deduplicated:', saved.deduplicated,
)

// 2. List the application's versions
const list = await api('GET')
console.log(
  'Total versions:', list.totalVersions,
  '| current:', list.currentVersionId,
)

// 3. Get a link to the archive and download it —
//    the link is valid for 30 minutes and needs no key
const { url } = await api('GET', `/${saved.versionId}/download`)
const bytes = Buffer.from(await (await fetch(url)).arrayBuffer())
const sha256 = createHash('sha256').update(bytes).digest('hex')
console.log('Archive matches the saved one:', sha256 === saved.sha256)

// 4. Delete the version if this run created it. With deduplicated: true
//    the save returned an existing version with the same bytes —
//    the example leaves it alone
if (!saved.deduplicated) {
  const deleted = await api('DELETE', `/${saved.versionId}`)
  console.log('Deleted version:', deleted.versionId)
}

Endpoint reference

Application snapshots:

Method Path Action
MethodPOST Path/v1/apps/:id/sources ActionSave a snapshot
MethodGET Path/v1/apps/:id/sources ActionList versions
MethodGET Path/v1/apps/:id/sources/:versionId ActionGet version metadata
MethodGET Path/v1/apps/:id/sources/:versionId/download ActionDownload the archive
MethodPATCH Path/v1/apps/:id/sources/:versionId ActionUpdate version metadata
MethodPOST Path/v1/apps/:id/sources/:versionId/tag ActionSet or remove a tag
MethodDELETE Path/v1/apps/:id/sources/:versionId ActionDelete a version
MethodPOST Path/v1/apps/:id/sources/cleanup ActionClear old versions

Server snapshots — the same family keyed by the server. The differences and the full list of paths are on the Server-keyed source endpoints page.

Aggregated registry: GET /v1/me/sources — every snapshot owner the key can reach, see Source registry.

Error codes

Refusals specific to source storage:

HTTP Code When returned
HTTP400 CodeINVALID_CONTENT_TYPE When returnedContent-Type is not in the list of allowed archive formats
HTTP400 CodeINVALID_SHA256 When returnedThe sha256 parameter is not exactly 64 hexadecimal characters
HTTP400 CodeINVALID_VERSION_ID When returnedThe versionId format does not match v<non-negative integer>
HTTP400 CodeINVALID_KEEP_LATEST When returnedThe keepLatest value is not a non-negative integer
HTTP400 CodeSOURCE_VERSION_REQUIRES_APP When returnedDeploy by versionId onto a server owned by another key, and the server's owner is not bound to an application
HTTP403 CodeNOT_AUTHORIZED When returnedThe key is neither an application key, the author's personal key, nor a Bitrix24 account administrator key
HTTP403 CodePORTAL_KEY_REQUIRED When returnedThe key is not bound to a portal — the aggregated registry is unavailable to such a key
HTTP403 CodeSOURCE_APP_ID_MISMATCH When returnedAn authorization key vibe_app_… targets snapshots of a different application
HTTP403 CodeINFRA_FORBIDDEN_FOR_COWORK_KEY When returnedA save, a metadata edit, or a delete was made with a Cowork/Code key — Project key for deploy
HTTP403 CodeEXTERNAL_COLLABORATOR_KEY_SERVER_MISMATCH When returnedThe call was made with an external-collaborator key, and the address names a server other than the one the key was issued for. Such a key is valid for exactly one server, and the response does not reveal whether the requested server exists. Working with another server requires the key issued for that external membership
HTTP403 CodeEXTERNAL_COLLABORATOR_NOT_A_MEMBER When returnedAn external-collaborator key addresses its own server, but access is not granted right now: the membership was removed, it expired, or external development collaborators are switched off for the Bitrix24 account that owns the server. The code does not tell these reasons apart and reveals nothing about the server. Membership is re-read on every request, so revoked access stops working immediately
HTTP404 CodeAPP_NOT_FOUND When returnedThe application does not exist, was deleted, or belongs to another portal
HTTP404 CodeVERSION_NOT_FOUND When returnedNo version with that versionId exists, or it was deleted
HTTP404 CodeSOURCE_VERSION_NOT_FOUND When returnedThe version was not found in either the server's context or the application's
HTTP409 CodeSNAPSHOT_REQUIRED When returnedPublishing without a saved snapshot, or a deploy from an external URL
HTTP409 CodePROTECTED_BY_TAG When returnedThe version is protected by the manual or published tag
HTTP410 CodeSOURCE_VERSION_BYTES_PURGED When returnedThe version record still exists, but the bytes have already been purged from storage
HTTP411 CodeMISSING_CONTENT_LENGTH When returnedThe save request arrived without Content-Length
HTTP415 CodeUNSUPPORTED_ARCHIVE_FORMAT When returnedThe first bytes of the archive contradict the declared Content-Type
HTTP502 CodeSOURCE_DOWNLOAD_URL_FAILED When returnedStorage is temporarily unavailable — retry the request

The full reference of API error codes — Error codes.

See also