## Create a secret name

`POST /v1/applications/:id/secrets`

Creates a secret name without a value: the owner or the Bitrix24 account administrator then sets the value on the application card. The call applies nothing and does not restart the application.

## Parameters

| Parameter | Type | Required | Description |
|----------|-----|:-----:|---------|
| `id` (path) | string | yes | Application card ID. This is not the ID of an OAuth application or a server. List: [`GET /v1/applications`](/docs/applications/list) |

## Request fields (body)

| Field | Type | Required | Description |
|------|-----|:-----:|---------|
| `name` | string | yes | Secret name, up to 128 characters, `^[A-Za-z_][A-Za-z0-9_]*$`. `PORT` and the prefixes `VIBE_` and `HERMES_EVENT_INGEST_` are not allowed. An application has at most 100 author names; system secrets do not count toward this limit |

## Examples

### curl — personal key

```bash
curl -X POST https://vibecode.bitrix24.com/v1/applications/cmsw806qi0000tdskiw2aegii/secrets \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "PAYMENT_TOKEN"}'
```

### curl — OAuth application

```bash
curl -X POST https://vibecode.bitrix24.com/v1/applications/cmsw806qi0000tdskiw2aegii/secrets \
  -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "PAYMENT_TOKEN"}'
```

### JavaScript — personal key

```javascript
const id = 'cmsw806qi0000tdskiw2aegii'
const res = await fetch(`https://vibecode.bitrix24.com/v1/applications/${id}/secrets`, {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'PAYMENT_TOKEN' }),
})
const { data } = await res.json()

console.log(data.secret.name, data.secret.hasValue)
```

### JavaScript — OAuth application

```javascript
const id = 'cmsw806qi0000tdskiw2aegii'
const res = await fetch(`https://vibecode.bitrix24.com/v1/applications/${id}/secrets`, {
  method: 'POST',
  headers: {
    'X-Api-Key': 'YOUR_APP_KEY',
    'Authorization': 'Bearer USER_SESSION_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ name: 'PAYMENT_TOKEN' }),
})
const { data } = await res.json()
```

## Response fields

Success — HTTP `201`.

| Field | Type | Description |
|------|-----|---------|
| `success` | boolean | `true` on success |
| `data.secret.name` | string | Secret name |
| `data.secret.kind` | string | Always `user`: this method creates only secrets of the application author |
| `data.secret.hasValue` | boolean | Always `false`: the value is set on the application card |
| `data.secret.createdAt` | string | When the name was created, ISO 8601 |
| `data.secret.createdBy` | string | ID of the user who created the name |
| `data.secret.updatedAt` | string | Time of the last change, ISO 8601 |
| `data.secret.updatedBy` | string | ID of the author of the last change |
| `data.secret.updatedByName` | string | Name of the author of the last change |
| `data.state` | object | State of applying the set |
| `data.state.desiredRevision` | number | Number of the current set. Creating a name does not change it |
| `data.state.appliedRevision` | number | Number of the set the application has confirmed receiving |
| `data.state.appliedServerId` | string \| null | ID of the server where the set is applied. Matches `server.id` in [`GET /v1/applications/:id`](/docs/applications/get) |
| `data.state.status` | string | `PENDING`, `APPLYING`, `APPLIED` or `FAILED`. The values are described under `state.status` on the [List application secrets](/docs/applications/app-secrets/list) page |
| `data.state.failureCode` | string \| null | Failure reason when `FAILED`. The codes are in the "Failure and retry" section of [Application secrets](/docs/applications/app-secrets) |
| `data.state.deliveredNames` | array | Names the platform has already passed to the application, including deleted ones |
| `data.state.serviceName` | string \| null | The application's service on a standalone machine, recorded by the platform on deploy. `null` in Galaxy and before such a deploy |
| `data.state.updatedAt` | string | Time of the last state change, ISO 8601 |

## Response example

```json
{
  "success": true,
  "data": {
    "secret": {
      "name": "PAYMENT_TOKEN",
      "kind": "user",
      "hasValue": false,
      "createdAt": "2026-10-22T12:45:13.146Z",
      "updatedAt": "2026-10-22T12:45:13.187Z",
      "createdBy": "3f6c1a52-8b1e-4c7a-9d2f-5e0b7a4c1d93",
      "updatedBy": "3f6c1a52-8b1e-4c7a-9d2f-5e0b7a4c1d93",
      "updatedByName": "Anna Smith"
    },
    "state": {
      "desiredRevision": 0,
      "appliedRevision": 0,
      "appliedServerId": null,
      "status": "PENDING",
      "failureCode": null,
      "deliveredNames": [],
      "serviceName": null,
      "updatedAt": "2026-10-22T12:45:13.206Z"
    }
  }
}
```

## Error response example

400 — the body contains a value:

```json
{
  "success": false,
  "error": {
    "code": "SECRET_VALUE_NOT_ACCEPTED",
    "message": "Set secret values in the application card.",
    "applicationUrl": "/applications?app=cmsw806qi0000tdskiw2aegii"
  }
}
```

`error.applicationUrl` points to the application card, where the owner sets the value.

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `SECRET_VALUE_NOT_ACCEPTED` | The body has a `value` field, even an empty one. Set the value on the application card |
| 400 | `SECRET_INVALID_NAME` | Invalid or reserved name, other than a system secret name |
| 400 | `SECRET_INVALID_REQUEST` | Invalid request body: not JSON, no `name`, `name` is not a string, or there are extra fields |
| 400 | `SECRET_LIMIT_REACHED` | The application already has 100 author names. System secrets are not counted |
| 404 | `APPLICATION_NOT_FOUND` | The 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 |
| 409 | `SECRET_ALREADY_EXISTS` | The name already exists. Its value and data stay unchanged |
| 409 | `SECRET_SYSTEM` | A platform system secret name — `VIBE_AUTH_SECRET`, `VIBE_AUTH_SECRET_PREVIOUS` or `VIBE_AUTH_SECRET_REVOKED`. Only the platform creates these secrets. The answer is the same even if the application has no such secret |
| 413 | `SECRET_BODY_TOO_LARGE` | The request body exceeds 128 KiB |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `INVALID_API_KEY` | Key not found |
| 403 | `WRITE_BLOCKED_READONLY_KEY` | A read-only key cannot create names |
| 403 | `INFRA_FORBIDDEN_FOR_COWORK_KEY` | A Cowork subscription key with the `vibe:cowork` scope cannot create names |
| 403 | `EXTERNAL_COLLABORATOR_KEY_SERVER_MISMATCH` | The external development member's key is not linked to a machine, and the application has no machine either |
| 403 | `EXTERNAL_COLLABORATOR_NOT_A_MEMBER` | Key of an external development member whose membership on the machine was revoked or has expired |
| 403 | `PORTAL_COLLABORATOR_NOT_A_MEMBER` | Key of a development team member who is no longer in the machine's team or is not linked to it |
| 429 | `RATE_LIMIT_EXCEEDED` | The 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 |
| 500 | `SECRET_OPERATION_FAILED` | The operation failed. The response does not include the original error |

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

## See also

- [Application secrets](/docs/applications/app-secrets)
- [List application secrets](/docs/applications/app-secrets/list)
- [Delete a secret](/docs/applications/app-secrets/delete)
- [Application catalog](/docs/applications)
