For AI agents: markdown of this page — /docs-content-en/applications/app-secrets.md documentation index — /llms.txt

Application secrets

Secrets store an application's tokens and passwords: the value is set on the application card, and the platform passes it to the running application as an environment variable.

A value set on the card never passes through a conversation with an AI agent and is not sent in a deploy call. If the feature is not enabled for the Bitrix24 account, the card has no "Secrets" block and the methods below return 404 APPLICATION_NOT_FOUND.

Authorization: X-Api-Key. The methods can be called by the application owner with any of their keys, by the application's own key, and by members of the linked server's development team. Through the API and MCP you can list names, create names and delete them. Only the owner and a Bitrix24 account administrator set and replace values, on the /applications card. The API and MCP never accept or return a value. The dashboard does not show it after saving either: a value can only be replaced. The card's secrets history records when and by whom a name was created or a value was set, replaced or deleted, and the outcome of applying the change. The history contains no values.

The MCP tool manage_app_secrets accepts applicationId, action — list, create or delete — and name for create and delete. It does not accept a value.

Typical scenario

  1. Create the name: POST /v1/applications/:id/secrets with the body { "name": "PAYMENT_TOKEN" }. The response has hasValue set to false.
  2. The owner or a Bitrix24 account administrator opens the application card /applications?app=<id> and sets the value. The platform applies it without a deploy.
  3. Check the result: GET /v1/applications/:id/secrets. The name has hasValue set to true, and state.status is APPLIED once the application has received the set.

Secret value

A value is set only on the application card. It is a single line of up to 16 KiB, counted in UTF-8 bytes. LF and CR line breaks and the NUL character are not allowed. Encode multiline data, such as a PEM key, as base64 first and decode it in the application: the platform does not do this. The limit applies to the encoded string.

Author secrets and system secrets

The kind field in responses tells two kinds of secrets apart. user is a secret of the application author: the methods below create and delete its name. system is a platform system secret: VIBE_AUTH_SECRET, VIBE_AUTH_SECRET_PREVIOUS and VIBE_AUTH_SECRET_REVOKED. The platform manages system secrets itself.

System secrets come first in the list and do not count toward the 100-name limit: the limit counts author secrets only. A system secret name cannot be created or deleted through the API — the answer is 409 SECRET_SYSTEM, even if the application has no such secret.

How secrets reach the application

The application receives secrets as environment variables of its process and reads them the same way as variables from env: moving a value from env to a secret needs no change to the application code. A name without a value is not passed to the application.

On a standalone server, the platform writes the values to /var/lib/vibe/app-secrets/<service>.env and attaches the file to the application's systemd service. In Galaxy, the values are added to the container's environment when the container starts, not when the image is built. Details, including systemd: false, are in the "Application secrets" section of Full application deploy.

On deploy

Every deploy passes the current set of secrets to the application.

  • A secret with a value takes precedence over a variable with the same name in the deploy's env. The application receives the secret's value, and warnings in the deploy response reports that the env value was not applied.
  • A name without a value does not override env: if the variable is passed in env, the application receives it. warnings asks for the value to be set, with a link to the card.
  • The platform sets PORT. The names PORT, VIBE_* and HERMES_EVENT_INGEST_* cannot be secrets.
  • The install and preStart commands, and in Galaxy the image build, do not receive secrets: the values exist only in the running application's environment. If a migration needs a secret, run it from the application itself at startup.
  • In Galaxy, a name that was previously delivered as a secret and then deleted reaches the container empty, even if the deploy's env passes it. This keeps the old value from coming back from an image. To pass that variable through env again, create the name without a value.

Without a deploy

Saving a value on the card and deleting a secret take effect on their own, with no deploy. After "Save" or a deletion, the platform restarts the running application in the background with the new environment. On a standalone server the application's service restarts. In Galaxy, the container is recreated from the current image. The application does not respond while it restarts. Creating a name without a value applies nothing.

On a standalone server, the platform records the application's service on every successful deploy, even if the application has no secrets yet. An application last deployed before the feature was enabled for the Bitrix24 account does not receive the first change: the card shows "Could not apply: the application needs to be redeployed" with a hint. Deploy once: the change applies during that deploy, and later changes apply without one.

Sleeping machine

A change does not wake the machine. While it sleeps, the card shows "Will apply when the machine wakes up", and status in the API is PENDING. After the machine wakes up, the platform applies the current set on its own. In Galaxy, the container is recreated with the new environment on wake. A standalone server first starts the application with the old values and restarts it once the server is back in contact with the platform.

Failure and retry

If applying fails, the card shows "Could not apply" with the reason, status in the API is FAILED, and the reason is in failureCode. While the machine is running, the platform retries on its own, at most once a minute. The "Retry" button on the card starts an attempt right away. It is available to the owner and a Bitrix24 account administrator. The API has no separate retry method. The exception is the reason SECRET_SERVICE_UNKNOWN: a retry cannot fix it without a deploy, so the platform does not retry on its own and the card has no "Retry" button.

failureCode Card label What happened
failureCodeSECRET_SERVICE_UNKNOWN Card labelthe application needs to be redeployed What happenedStandalone server: the platform does not know the application's service yet because the application has not been deployed since secrets were enabled. Deploy the application, and the change applies during the deploy.
failureCodeSECRET_INVALID_SERVICE Card labelapplication service is not configured What happenedStandalone server: the stored service name is not valid. Deploy the application.
failureCodeSECRET_RESTART_FAILED Card labelapplication restart failed What happenedStandalone server: the service did not start with the new environment.
failureCodeSECRET_CONTAINER_UNAVAILABLE Card labelcontainer is unavailable What happenedGalaxy: the platform could not prepare to recreate the container.
failureCodeSECRET_RECREATE_FAILED Card labelapplication restart failed What happenedGalaxy: the new container did not start.
failureCodeSECRET_DELIVERY_FAILED Card labeldelivery failed What happenedThe values could not be delivered to the machine, including when the deploy that was delivering them failed.

Migration and restore

Secrets belong to the application card, not to the machine. A redeploy and a migration of the application to another galaxy keep them: the application receives the current set again.

A restore from a backup takes the current values from the card, not the values as of the backup date. A restored machine receives the set again. When a container is restored into a new application, secrets are copied from the source application's card if that application still exists and both applications have the same owner and the same Bitrix24 account. Otherwise, set the secrets on the new application's card.

Protection boundaries

The dashboard, the API and MCP never return a value. It is not in the secrets history, the audit log or the deploy step output. However, the running application's environment and the secrets file can be read by anyone who runs commands on the machine: a development team member, an AI agent calling POST /exec, the install and preStart commands. The application's own code sees its environment variables. Secrets keep a value out of conversations and out of the API, but they do not hide it from anyone with access to the machine. Grant that access only to people allowed to know the values.

A secret does not revoke access in the external system. If a value leaks, change it in the external system, then replace the secret on the card. A deleted value can remain in older backups of the machine or the container.

List application secrets

GET /v1/applications/:id/secrets

Returns the application's secret names and the state of applying them, so you can check which names are waiting for a value and whether the application has received the current set.

Parameters

Parameter Type Required Description
Parameterid (path) Typestring Requiredyes DescriptionApplication card ID. This is not the ID of an OAuth application or a server. List: GET /v1/applications

Examples

curl — personal key

Terminal
curl -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/applications/cmsw806qi0000tdskiw2aegii/secrets

curl — OAuth application

Terminal
curl -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  https://vibecode.bitrix24.com/v1/applications/cmsw806qi0000tdskiw2aegii/secrets

JavaScript — personal key

javascript
const id = 'cmsw806qi0000tdskiw2aegii'
const res = await fetch(`https://vibecode.bitrix24.com/v1/applications/${id}/secrets`, {
  headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { data } = await res.json()

const waiting = data.secrets.filter((secret) => !secret.hasValue).map((secret) => secret.name)
console.log('Waiting for a value:', waiting, 'apply status:', data.state?.status ?? 'no changes yet')

JavaScript — OAuth application

javascript
const id = 'cmsw806qi0000tdskiw2aegii'
const res = await fetch(`https://vibecode.bitrix24.com/v1/applications/${id}/secrets`, {
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
  },
})
const { data } = await res.json()

Response fields

Field Type Description
Fieldsuccess Typeboolean Descriptiontrue on success
Fielddata.secrets Typearray DescriptionSystem secrets first, then up to 100 author names, each group in alphabetical order. Values and ciphertext are not returned
Fielddata.secrets[].name Typestring DescriptionSecret name
Fielddata.secrets[].kind Typestring Descriptionuser for a secret of the application author, system for a platform system secret. See "Author secrets and system secrets" on Application secrets
Fielddata.secrets[].hasValue Typeboolean DescriptionWhether a value is set. false means the name is waiting for a value
Fielddata.secrets[].createdAt Typestring DescriptionWhen the name was created, ISO 8601
Fielddata.secrets[].createdBy Typestring DescriptionID of the user who created the name
Fielddata.secrets[].updatedAt Typestring DescriptionTime of the last change, ISO 8601
Fielddata.secrets[].updatedBy Typestring DescriptionID of the author of the last change
Fielddata.secrets[].updatedByName Typestring DescriptionName of the author of the last change
Fielddata.state Typeobject | null DescriptionState of applying the set. null until a secret is created, changed or deleted for the application, or the application is deployed to a standalone machine after the feature is enabled
Fielddata.state.desiredRevision Typenumber DescriptionNumber of the current set. Increases when a value is saved and when a secret is deleted. Creating a name does not change it
Fielddata.state.appliedRevision Typenumber DescriptionNumber of the set the application has confirmed receiving. Equals desiredRevision when everything is applied
Fielddata.state.appliedServerId Typestring | null DescriptionID of the server where the set is applied. Matches server.id in GET /v1/applications/:id
Fielddata.state.status Typestring DescriptionPENDING — waiting to be applied, including while the machine sleeps. APPLYING — being applied. APPLIED — applied. FAILED — failed, the reason is in failureCode
Fielddata.state.failureCode Typestring | null DescriptionFailure reason when FAILED. The codes are in the "Failure and retry" section of Application secrets
Fielddata.state.deliveredNames Typearray DescriptionNames the platform has already passed to the application, including deleted ones
Fielddata.state.serviceName Typestring | null DescriptionThe application's service on a standalone machine, recorded by the platform on deploy. In Galaxy and before such a deploy — null
Fielddata.state.updatedAt Typestring DescriptionTime of the last state change, ISO 8601

Response example

JSON
{
  "success": true,
  "data": {
    "secrets": [
      {
        "name": "PAYMENT_TOKEN",
        "kind": "user",
        "hasValue": false,
        "createdAt": "2026-10-22T13:05:39.970Z",
        "updatedAt": "2026-10-22T13:05:39.988Z",
        "createdBy": "3f6c1a52-8b1e-4c7a-9d2f-5e0b7a4c1d93",
        "updatedBy": "3f6c1a52-8b1e-4c7a-9d2f-5e0b7a4c1d93",
        "updatedByName": "Anna Smith"
      },
      {
        "name": "SMTP_PASSWORD",
        "kind": "user",
        "hasValue": false,
        "createdAt": "2026-10-22T13:05:41.810Z",
        "updatedAt": "2026-10-22T13:05:42.007Z",
        "createdBy": "3f6c1a52-8b1e-4c7a-9d2f-5e0b7a4c1d93",
        "updatedBy": "3f6c1a52-8b1e-4c7a-9d2f-5e0b7a4c1d93",
        "updatedByName": "Anna Smith"
      }
    ],
    "state": {
      "desiredRevision": 1,
      "appliedRevision": 0,
      "appliedServerId": null,
      "status": "PENDING",
      "failureCode": null,
      "deliveredNames": [],
      "serviceName": null,
      "updatedAt": "2026-10-22T12:46:24.093Z"
    }
  }
}

Error response example

404 — the application does not exist, there is no access to it, or secrets are not enabled for the Bitrix24 account:

JSON
{
  "success": false,
  "error": {
    "code": "APPLICATION_NOT_FOUND",
    "message": "APPLICATION_NOT_FOUND"
  }
}

Errors

HTTP Code Description
HTTP404 CodeAPPLICATION_NOT_FOUND DescriptionThe application does not exist or there is no access to it, including an application on a different machine than the one the development member's key is linked to. Or the feature is not enabled for the portal
HTTP401 CodeMISSING_API_KEY DescriptionThe X-Api-Key header is missing
HTTP401 CodeINVALID_API_KEY DescriptionKey not found
HTTP403 CodeEXTERNAL_COLLABORATOR_KEY_SERVER_MISMATCH DescriptionThe external development member's key is not linked to a machine, and the application has no machine either
HTTP403 CodeEXTERNAL_COLLABORATOR_NOT_A_MEMBER DescriptionKey of an external development member whose membership on the machine was revoked or has expired
HTTP403 CodePORTAL_COLLABORATOR_NOT_A_MEMBER DescriptionKey of a development team member who is no longer in the machine's team or is not linked to it
HTTP429 CodeRATE_LIMIT_EXCEEDED DescriptionThe secrets methods limit is 60 requests per minute per user within a portal, shared by the list, create and delete methods and split across replicas. A rejection by the general API request limit comes with the same code. x-ratelimit-limit reports the effective limit for the key
HTTP500 CodeSECRET_OPERATION_FAILED DescriptionThe operation failed. The response does not include the original error

Full list of common API errors — Errors.

Known specifics

Empty list and state. After the last name is deleted, data.state stays an object and its desiredRevision keeps growing, so an empty data.secrets does not mean the state has been reset.

Applying for an application without a machine. While the application has no machine to pass the set to, state.status stays PENDING and appliedRevision does not catch up with desiredRevision.

See also