---
title: "Get Runtime Log"
method: POST
path: "/apps/{app_id}/channels/{channel_id}/runtime/log"
---

# Get Runtime Log

`POST /apps/{app_id}/channels/{channel_id}/runtime/log`

## Request

- Base URL: `https://api.xhostd.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.xhostd.com/apps/{app_id}/channels/{channel_id}/runtime/log`
- Auth: none declared

Read a channel container's stdout/stderr, live or archived.

The runtime counterpart of ``get_deploy_log``, which only covers the
build/boot window: this reads a RUNNING app's ongoing output, and —
once the container is gone (a blue-green redeploy removes it) — the
archive the cell wrote at removal, so a crash is still diagnosable
afterwards (RUNTIME.md). The status facts (status, exit code, OOM
flag, restart count) ride on every reply, so omitting ``command`` is
the "just tell me how it died" query.

**POST, not GET**, because ``command`` is a shell pipeline: URL-
encoding one is hostile, and a query string lands in Caddy's access
log (and thus xhost_stats), where a ``grep <secret>`` must never go.

Auth mirrors ``get_deploy_log`` deliberately: bearer + channel
ownership + the ``deploy:*`` scope both deploy-plane reads carry.
The command grants the caller no authority they lack — a read-only
copy of their own log inside a networkless disposable container —
so resource abuse is answered by the cell's caps, not by a
permission bit, and an owner-only gate would break sharing
asymmetrically against ``get_deploy_log``.

## Path parameters

- `app_id` string, uuid, required
- `channel_id` string, uuid, required

## Headers

- `authorization` string, nullable

## Request body

- RuntimeLogRequest: One runtime-log read. ``command`` is a shell command run against the log inside a disposable sandbox on the cell; omitting it returns the status facts alone. There is deliberately no server-side default command — an implicit one would be exactly the magic this surface removes.
  - `container_index` integer, nullable
  - `command` string, nullable

## Response `200`

Successful Response

- RuntimeLogResponse: Status facts + the command's own output. ``exit_code`` is the LOGGED CONTAINER's; ``command_exit_code`` is the query command's (``None`` when no command ran, or when the sandbox was killed at the timeout). ``running_index`` is the index of the running container, whatever index this reply shows, and is ``None`` when nothing runs.
  - `container_index` integer, required
  - `container_id` string, required
  - `container_name` string, required
  - `running` boolean, required
  - `source` 'live' | 'archive', required
  - `status` string, required
  - `exit_code` integer, nullable, required
  - `oom_killed` boolean, nullable, required
  - `restart_count` integer, nullable, required
  - `started_at` string, nullable, required
  - `finished_at` string, nullable, required
  - `available_indices` integer[], required
  - `running_index` integer, nullable, required
  - `log_bytes` integer, required
  - `output` string, required
  - `command_exit_code` integer, nullable, required
  - `timed_out` boolean, required
  - `truncated` boolean, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/xhostd/apis/xhostd-public.md) · [All operations](https://skmtc.dev/xhostd/apis/xhostd-public/llms.txt) · [OpenAPI document](https://skmtc.dev/xhostd/apis/xhostd-public/revisions/bf439c4d1789?raw)
