> ## Documentation Index
> Fetch the complete documentation index at: https://rakumux.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# API version and daemon reachability.

> The only route without authentication. Never starts the daemon. On the remote listener, without the remote token, `daemon.error` is a generic "the daemon is not reachable".




## OpenAPI

````yaml /api-reference/openapi.yaml get /v1/health
openapi: 3.1.0
info:
  title: Rakumux external API
  version: '1'
  summary: Sessions and folders of the local Rakumux daemon, over HTTP.
  description: >
    `rakumux-api` exposes a subset of the session operations of the running

    Rakumux daemon (`rakumux-ptyd`). It listens on **127.0.0.1** and, with

    remote access on, on a **remote listener** too (see below). It is a thin

    adapter: the daemon decides permissions and folder confinement.


    **Discovery.** While it runs, the API writes

    `<RAKUMUX_HOME or ~/.rakumux>/api.json` (mode 0600):

    `{"url": "http://127.0.0.1:<port>", "token": "<64 hex>", "pid": <int>,
    "version": "<x.y.z>", "remote_urls": ["http://<addr>:<port>"]}`

    (`remote_urls` only while a remote listener runs). A file whose `pid` no

    longer exists is stale.


    **Authentication.** Every route except `GET /v1/health` needs

    `Authorization: Bearer <token>`. On the loopback listener the token is

    api.json's; requests whose `Host` is not a loopback name (`127.0.0.1`,

    `localhost`, `[::1]`, any port) and requests carrying an `Origin` or

    `Sec-Fetch-Site` header (browsers) are refused with 403. No CORS headers

    are ever sent.


    **Remote access.** `rakumux remote on` writes

    `<home>/remote.json` (mode 0600):

    `{"enabled": true, "port": 7337, "token": "<26 chars a-z2-7>", "listen":
    []}`.

    While it is enabled the API adds a remote listener on every Tailscale

    address of the machine (IPv4 in `100.64.0.0/10`, IPv6 in

    `fd7a:115c:a1e0::/48`) at `port`, or on `remote.json`'s `listen` /

    `--remote-listen ADDR:PORT` addresses instead. There the bearer is the

    remote token (constant-time compared); `Host` isn't checked and `Origin`

    is allowed; the caller is always the user, so the identity headers below

    are refused (403 `permission_denied`). The loopback listener keeps its

    rules. Same routes on both.


    **Streams.** `GET /v1/events` and `GET /v1/sessions/{id}/attach` are

    WebSockets (RFC 6455, version 13) on the same port, with the same checks;

    errors before the upgrade are ordinary JSON answers, and a request

    without the upgrade headers gets 426 `upgrade_required`. Their messages

    are the `EventMessage`, `AttachMessage` and `AttachCommand` schemas. The

    server pings every 30 s and drops a client that didn't answer the

    previous ping; it closes the socket when the stream ends.


    **Identity.** Without identity headers the API acts as the user. With both

    `X-Rakumux-Session-Id` and `X-Rakumux-Session-Token` (the

    `RAKUMUX_SESSION_ID` / `RAKUMUX_SESSION_TOKEN` of a process running in

    a Rakumux session) it acts as that session: the daemon confines it to

    its own folder and applies its agent policy (today: read anything in the

    folder, create sessions in it within limits, rename only itself). With

    both `X-Rakumux-Agent` and `X-Rakumux-Agent-Conversation` instead

    (for agents whose tool calls don't carry the session's environment, such

    as OpenCode 2.x) it acts as the running session that bound that

    conversation with `rakumux session bind`; 401 if none did. That needs

    the daemon's `auth.delegated` capability (501 without it).


    **Folders.** A session's folder is the canonical directory it was started

    in (the daemon's protocol calls it `scope`, and its folder operations

    `project_*`). Wherever a `folder` is accepted it may be an absolute

    directory (`~/` is expanded) or the name of a known folder; names and

    listing every folder need the daemon's `projects` capability (see

    `GET /v1/health`), and answer 501 / 400 until it has it.


    **Deprecated `project` names.** Earlier builds said "project": they are

    still accepted and returned. `GET /v1/projects` is an alias of

    `GET /v1/folders`; the `project` query parameter and body field are

    aliases of `folder` (`folder` wins; both given and naming different

    folders is a 400); responses carry `project` next to `folder` and

    `projects` next to `folders`, with the same values.


    **Errors** use one envelope, `{"error": {"code", "message", "details"?}}`.

    Daemon error codes map to statuses: `not_found` 404, `invalid_argument`

    400, `unauthenticated` 401, `out_of_scope` and `permission_denied` 403,

    `session_not_live` and `session_in_use` 409, `limit_exceeded` 429,

    `timeout` 504,

    `daemon_unavailable` 503, `unsupported` 501, anything else 500. The API's

    own codes: `method_not_allowed` 405, `payload_too_large` 413,

    `unsupported_media_type` 415, `upgrade_required` 426.


    **Compatibility.** Fields may be added to responses; clients must ignore

    unknown fields. Request bodies reject unknown fields, and routes reject

    unknown query parameters (400), so typos never pass silently.
servers:
  - url: http://127.0.0.1:{port}
    variables:
      port:
        default: '0'
        description: The port in api.json.
  - url: http://{host}:{port}
    description: The remote listener (remote access on); see api.json `remote_urls`.
    variables:
      host:
        default: machine.tailnet.ts.net
        description: The machine's MagicDNS name or Tailscale address.
      port:
        default: '7337'
        description: remote.json `port`.
security:
  - bearer: []
tags:
  - name: health
  - name: folders
  - name: sessions
  - name: streams
paths:
  /v1/health:
    get:
      tags:
        - health
      summary: API version and daemon reachability.
      description: >
        The only route without authentication. Never starts the daemon. On the
        remote listener, without the remote token, `daemon.error` is a generic
        "the daemon is not reachable".
      operationId: getHealth
      responses:
        '200':
          description: The API answers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Health'
        '403':
          $ref: '#/components/responses/Forbidden'
      security: []
components:
  schemas:
    Health:
      type: object
      required:
        - status
        - version
        - pid
        - daemon
      properties:
        status:
          type: string
          const: ok
        version:
          type: string
          description: The API's version.
        pid:
          type: integer
          description: The API process.
        daemon:
          type: object
          required:
            - reachable
            - capabilities
          properties:
            reachable:
              type: boolean
            version:
              type: string
            capabilities:
              type: array
              items:
                type: string
              description: >-
                Optional daemon features, e.g. `projects`, `session.pin`,
                `session.git`.
            error:
              type: string
              description: Why the daemon is not reachable.
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              examples:
                - not_found
                - invalid_argument
                - unauthenticated
                - out_of_scope
                - unsupported
            message:
              type: string
            details: {}
  responses:
    Forbidden:
      description: >
        `permission_denied` (non-loopback Host, browser request, or the daemon's
        policy) or `out_of_scope` (a session acting outside its folder).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      description: >
        The `token` from api.json on the loopback listener; the remote token
        from remote.json (`rakumux remote token`) on the remote listener.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.