
## Application card

`GET /v1/applications/:id`

Returns a single application from the Bitrix24 account, together with a summary of its server, saved source versions, and any operation in progress. The card is available to the owner and anyone the application has been shared with, either directly or through the server's access policy. Being a Bitrix24 account administrator does not grant access: an administrator who neither owns the application nor has been granted access receives `403 FORBIDDEN`, just like any other viewer.

## Parameters

| Parameter | Type | Required | Description |
|-----------|------|:----:|-------------|
| `id` (path) | string | yes | Application ID. List: [`GET /v1/applications`](./list.md) |

## Examples

### curl — personal key

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

### curl — OAuth application

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

### JavaScript — personal key

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

console.log(application.name, application.server?.status ?? 'no server')
if (application.sources.hasVersions) {
  console.log('Latest version:', application.sources.latestVersionId)
}
```

### JavaScript — OAuth application

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

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Always `true` on success |
| `data.id` | string | Application ID |
| `data.name` | string | Application name |
| `data.description` | string \| null | Description. `null` when none was set |
| `data.type` | string | How the application was initially configured: `SHARED` — created with a server and/or an authorization key, `PERSONAL` — created without either. The value is set at creation and is not recalculated later, so a `PERSONAL` application may also have a server |
| `data.iconUrl` | string \| null | A relative path to the icon, with no host, for example `/api/app-icons/7f3…?v=1755500000000`. The icon endpoint is publicly accessible: no key, signature, or expiration time is required. Combine the path with the API base URL and use the result in `<img src>`. The endpoint returns a 256×256 PNG with `Cache-Control: public, max-age=300, must-revalidate` and an ETag. `null` if the card has no icon |
| `data.createdAt` | string | When the application was created, ISO 8601 |
| `data.updatedAt` | string | Timestamp of the last update to the card, ISO 8601. Deploying the application does not update the card; use `sources.latestSavedAt` to check how recently the code was saved |
| `data.viewerState` | string | The viewer's relationship to the application: `owner` — the owner, `shared` — access granted directly, through the server's access policy, or through membership in that server's development team, `usable` — the application has no server and is available to the entire Bitrix24 account, `requestable` — no access. For an application with a server, access is governed by the server's policy, and an application available to everyone is still returned as `shared` |
| `data.pinned` | boolean | Whether this viewer has pinned the application |
| `data.author.name` | string | Display name of the application owner |
| `data.openUrl` | string \| null | The URL used to open the application. When present, it is the application server URL. `null` means no URL is available; this is an expected value |
| `data.openTarget` | string \| null | Identifies what `openUrl` points to. The only current value is `app`, meaning the application server URL. It is `null` whenever `openUrl` is `null`. Treat an unfamiliar value as "no supported way to open the application", not as a malformed response: the set is closed but may be extended |
| `data.isEmbedded` | boolean | Whether the application is embedded in the Bitrix24 interface — that is, whether at least one [placement](/docs/apps/placements) is bound to it. This is the only field that distinguishes an application that is embedded and opens inside Bitrix24 from one that has not yet been published: both have `openUrl` and `openTarget` set to `null`. The flag is independent of the server; an embedded application without its own server is a normal state. Returned to every viewer who can see the card |
| `data.server` | object \| null | Summary of the application server. `null` when there is no server, or it was deleted or torn down |
| `data.server.id` | string | Server ID — the same ID used in the [Servers](/docs/infra/servers) paths |
| `data.server.status` | string | Server state: `PROVISIONING`, `RUNNING`, `STOPPED`, `SLEEPING`, `ERROR`. **Uppercase here** — [`GET /v1/infra/servers`](/docs/infra/servers/list) reports the same value for the same server in lowercase, so normalize the case before comparing strings from the two sections. A torn-down server never appears here at all: its `server` is `null`. Read an unfamiliar value as "a state your client does not know", not as a malformed response |
| `data.server.url` | string \| null | Application URL. `null` until a subdomain is issued — there is no separate "has an address" flag, so checking for `null` is the only way to determine whether an address exists. Moving the container between galaxies does not change the address: it is derived from the subdomain, and the move does not change the subdomain |
| `data.server.kind` | string | Resource type: `STANDALONE` — a dedicated virtual machine, `GALAXY_APP` — an application on a shared galaxy host |
| `data.server.reachable` | boolean | Whether the server is running and reachable over the network. This is distinct from `status`: a container can be running even if its tunnel has never come up. The flag already includes the condition `status === "RUNNING"`; it is never `true` for any other status, so do not combine the two checks. **Important:** for `kind: "GALAXY_APP"`, network reachability is determined from the galaxy host rather than the container itself; see "Known specifics" |
| `data.server.lastDeployedAt` | string \| null | Timestamp of the last SUCCESSFUL deployment, ISO 8601. This is the only field in this section that shows whether the application has actually been deployed, rather than merely having a running server. It is distinct from `updatedAt` (changed by card edits, not deployments) and `sources.latestSavedAt` (code was saved, not deployed; returned only to the owner). **Important:** `null` does not mean "never deployed": for servers created before 2026-08-18, the field remains empty until the next deployment because historical values were deliberately not reconstructed; see "Known specifics" |
| `data.sources` | object | Summary of the saved source versions. Populated only for users who manage the application |
| `data.sources.hasVersions` | boolean | Whether at least one saved version exists |
| `data.sources.latestVersionId` | string \| null | Latest version identifier in the form `v<N>`, exactly as accepted by [`GET /v1/infra/servers/:id/sources/:versionId/download`](/docs/source-storage). It is not the record's primary key, and no separate call for the version list is needed. `null` when there are no versions |
| `data.sources.latestSavedAt` | string \| null | When the latest version was saved, ISO 8601 |
| `data.activeOperation` | object \| null | Operation in progress on the server. Populated only for users who manage the application. The `null` case is covered in "Known specifics" |
| `data.activeOperation.kind` | string | Operation kind: `deploy` — deployment, `repair` — repair, `resize` — server plan change, `migrate` — moving a container between galaxies |
| `data.activeOperation.status` | string | `running` — the operation is in progress. `unknown` — the operation started, but its outcome is not known |
| `data.activeOperation.step` | string \| null | The step the operation is on. A free-form string, not an enumeration |
| `data.activeOperation.startedAt` | string | When the operation started, ISO 8601 |

## Response example

```json
{
  "success": true,
  "data": {
    "id": "cmsw806qi0000tdskiw2aegii",
    "name": "Deal report",
    "description": "Pipeline summary for the period",
    "type": "PERSONAL",
    "iconUrl": null,
    "createdAt": "2026-08-16T19:51:18.810Z",
    "updatedAt": "2026-08-16T19:51:18.810Z",
    "viewerState": "owner",
    "pinned": false,
    "author": { "name": "Application author" },
    "isEmbedded": false,
    "openUrl": "https://app-05b67cf7.vibecode.bitrix24.com",
    "openTarget": "app",
    "server": {
      "id": "5cbb50f9-f95f-4ddf-ba3b-b771209cb6fb",
      "status": "RUNNING",
      "url": "https://app-05b67cf7.vibecode.bitrix24.com",
      "kind": "STANDALONE",
      "reachable": true,
      "lastDeployedAt": "2026-08-16T19:50:41.302Z"
    },
    "sources": {
      "hasVersions": true,
      "latestVersionId": "v2",
      "latestSavedAt": "2026-08-16T19:41:18.818Z"
    },
    "activeOperation": {
      "kind": "deploy",
      "status": "running",
      "step": "build",
      "startedAt": "2026-08-16T19:50:33.822Z"
    }
  }
}
```

An application with no server returns `server: null`, an empty `sources` summary, and `activeOperation: null`. There is no URL to open it, so `openUrl` and `openTarget` are also `null`. The example below shows exactly this case: the application is embedded in Bitrix24.

```json
{
  "success": true,
  "data": {
    "id": "cmsw806qp0001tdskzf6mitka",
    "name": "Draft with no server",
    "description": null,
    "type": "PERSONAL",
    "iconUrl": null,
    "createdAt": "2026-08-16T19:51:18.817Z",
    "updatedAt": "2026-08-16T19:51:18.817Z",
    "viewerState": "owner",
    "pinned": false,
    "author": { "name": "Application author" },
    "isEmbedded": true,
    "openUrl": null,
    "openTarget": null,
    "server": null,
    "sources": { "hasVersions": false, "latestVersionId": null, "latestSavedAt": null },
    "activeOperation": null
  }
}
```

## Error response example

404 — no application with that ID on the Bitrix24 account:

```json
{
  "success": false,
  "error": {
    "code": "APPLICATION_NOT_FOUND",
    "message": "Application not found"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|------|-------------|
| 404 | `APPLICATION_NOT_FOUND` | No application with that `id` on the key's portal. The same response is returned for an ID from another portal or a deleted application |
| 403 | `FORBIDDEN` | The application exists, but the viewer has no access to it |
| 401 | `NO_PORTAL` | The key is not bound to a portal — the actual response in this case |
| 403 | `MANAGEMENT_KEY_NO_ENTITY_ACCESS` | A management key was used; an API key or an authorization key is required |
| 403 | `PORTAL_KEY_REQUIRED` | A safeguard for a corrupted key record with no owner. The usual "key with no portal" case returns `401 NO_PORTAL` above |
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header is missing |
| 401 | `INVALID_API_KEY` | The key is not recognized — no such key exists on the platform |
| 429 | `RATE_LIMITED` | Rate limit exceeded. The platform-wide limit is 120 requests per minute. The effective limit for your key is returned in the `x-ratelimit-limit` header. This endpoint has its own counter, with a noticeably higher limit than the list endpoint. The `Retry-After` header specifies the delay in whole seconds |
| 429 | `QUOTA_EXCEEDED` | The key's daily free-call quota is exhausted. Same status, different cause: waiting does not help |

The `error.message` text is always in English and intended for logs, not for display to users. Build user-facing messages from `error.code`. See [Errors](/docs/errors) for the full list of common API errors.

## Known specifics

- **The card is available to more than just the owner.** An application shared with you directly, through the server's access policy, or through membership in its development team can be retrieved via a direct link. The response contains one of the `owner`, `shared`, or `usable` states. A viewer without access receives `403 FORBIDDEN`, so `requestable` never appears in a card.
- **An embedded application has no URL to open, so both fields are `null`.** The platform does not yet provide the URL used to open an embedded application inside the Bitrix24 account. An empty value is expected, not an error: inventing a URL could send the user to the wrong place while appearing to work.
- **The server URL is not substituted into `openUrl`, and you must not substitute it yourself.** For an embedded application, `server.url` is returned as usual, but it is not a valid way to open the application: an unauthenticated navigation receives the Gateway authentication flow instead of the app. An in-place HTML refusal uses HTTP `401`; a document `GET`/`HEAD` may first receive an HTTP `302` to OAuth login when the private server is `RUNNING` without a connected tunnel. A client that fills an empty `openUrl` with `server.url` therefore sends the user to authentication, not to the embedded application.
- **`openUrl` is not suppressed when the server is unreachable.** The URL is returned even with `server.reachable: false`. Users cannot diagnose a disabled button, but they can diagnose a visible error.
- **Only `isEmbedded` distinguishes why both open fields are `null`.** Both an application that is embedded and opens inside Bitrix24 and one that has not yet been published return `openUrl: null` and `openTarget: null`, but the UI must represent them differently. Do not infer embedding from the presence of a server: an embedded application with no server of its own is normal because it may have been embedded before its code was deployed. Conversely, an embedded application with a server still returns `server.url`, but that is not the URL used to open it.
- **For an application in a galaxy, the second component of `reachable` describes the host, not the container.** With `server.kind: "GALAXY_APP"`, connectivity comes from the shared galaxy host; the container has no tunnel of its own. Therefore, `true` means that the container is running, the host is running, and the host's tunnel is up. The flag implies `status === "RUNNING"` and is never true otherwise. Conversely, a newly created container that has not yet reached `RUNNING` (which happens only after its first source upload) returns `reachable: false` even when the host is healthy. This means "the container is not running yet", not "the host is unreachable". The flag alone cannot distinguish those cases, so check `status`. `STANDALONE` has no such split; both parts describe the same machine.
- **`lastDeployedAt` records deployments going forward; it does not backfill history.** A successful deployment writes the timestamp at the same time it records success, so a failed deployment does not change it. Servers that existed before 2026-08-18 have no backfilled value; the field remains empty until their next deployment. The operations journal could reconstruct only one of the three deployment paths. Backfilling from it would give applications on dedicated machines a date but leave applications in galaxies empty, misleading readers into thinking that galaxy applications were inactive. A consistent "no deployments since tracking began" is more accurate. Therefore, `null` during the first few weeks is expected and does not mean the application is abandoned.
- **A torn-down server is returned as `server: null`, not as a separate status.** You will not see values such as `deleted`, `terminated`, `destroyed`, or `archived` in `server.status`, but for different reasons: `terminated`, `destroyed`, and `archived` do not exist in the platform, while the torn-down state does exist but is not exposed by this endpoint. Once a server is torn down, the card returns `server: null` together with `openUrl: null`. If you normalize statuses returned by [`GET /v1/infra/servers`](/docs/infra/servers/list), note that its value set is different: that endpoint returns lowercase statuses and, when `includeDeleted` is set, includes deleted servers. The application card has no equivalent parameter.
- **An application belonging to another Bitrix24 account is indistinguishable from a missing one.** An ID from another account produces `404 APPLICATION_NOT_FOUND` rather than `403`: the endpoint does not even confirm that such a record exists.
- **The source summary and the operation in progress are returned only to users who manage the application.** A viewer who was merely granted access to the application receives an empty `sources` summary and `activeOperation: null`, without any change to the response shape. An empty summary alone therefore does not mean "there are no versions": the application may have no server, may genuinely have no versions, or may belong to someone else whose data is not disclosed to you. A client that renders "no code" from an empty `sources` summary will be wrong for every application belonging to someone else.
- **`activeOperation: null` does not mean "nothing is happening to this application".** The field is reliable only for operations with a stored record — deployment, repair, a server plan change, and moving a container between galaxies. Other actions are not recorded by the platform and therefore never appear in this field. The value `unknown` in `status` represents a third state: the operation started, but its outcome is unknown. Waiting for it to finish is pointless; read the current state from the server itself.
- **Server state is returned in uppercase.** In the card, `server.status` for a running server is `RUNNING`, while [`GET /v1/infra/servers`](/docs/infra/servers/list) returns `running` for the same server at the same time. A client comparing strings from both endpoints must normalize the case.

## See also

- [List applications](./list.md)
- [Application catalog](/docs/applications)
- [Servers](/docs/infra/servers)
- [Source storage](/docs/source-storage)
- [Keys and authorization](/docs/keys-auth)
- [Errors](/docs/errors)
