# Read file

`read_file`

| Through | Form |
|---|---|
| HTTP | `GET https://api.markdownbrain.ai/v1/file` |
| MCP | tool `read_file` |
| CLI | `mdbrain call read_file` |

A file's content: markdown as text, or — for an image — a `url` you can fetch the bytes from. Name the file with `path` (its workspace-relative address, e.g. "specs/44-front-matter.md") or with `file_id` — exactly one of the two. Also returns `workspace_id`, so you know which workspace's AGENTS.md governs this file, and the file's own `path`, so a read that started from an id leaves you with an address. A markdown read also returns `version`, a fingerprint of exactly these bytes: pass it to [`apply_edits`](/docs/operations/apply_edits) as `base_version` and your edits are rejected — rather than applied somewhere you didn't intend — if the file changed since you read it. It also returns `front_matter`: the document's leading `---` metadata block already parsed, or null if it has none or the block is malformed. `content` still contains the block verbatim — edit it there if you mean to change it. The brain's root `brain-config.yaml`, which only the brain keeper can read, comes back as kind `brain-config`: its `content` and `version` as for markdown, no `front_matter`, and `problems` — what is wrong with it, each with its `line`, as the editor would show a person.

**Who may call it:** agents and people.

**Writes:** no, it only reads.

## Arguments

| Name | Type | Required | Travels in | Description |
|---|---|---|---|---|
| `file_id` | string | no | query string | file_node id of the file — or use `path` |
| `path` | string | no | query string | Workspace-relative path, e.g. "specs/44-front-matter.md" |
| `workspace_id` | string | no | query string | Only needed to disambiguate a `path` that exists in more than one workspace you can see |

## Success

`200` with `application/json`.

## Example request

```sh
curl 'https://api.markdownbrain.ai/v1/file?path=specs%2F12-onboarding.md&workspace_id=00000000-0000-4000-8000-000000000010' \
  -H "Authorization: Bearer $MDBRAIN_API_KEY"
```

```sh
mdbrain call read_file \
  --path specs/12-onboarding.md \
  --workspace-id 00000000-0000-4000-8000-000000000010
```

## Example response

> Written from the code rather than captured from a call.

```json
{
  "file_id": "00000000-0000-4000-8000-000000000102",
  "workspace_id": "00000000-0000-4000-8000-000000000010",
  "kind": "markdown",
  "content": "---\nstatus: draft\n---\n# Onboarding\n\nHow a new member goes from the invitation to their first edit.\n",
  "version": "Vn3kR8f1aQ2bC4dE5fG6hI",
  "front_matter": {
    "status": "draft"
  },
  "path": "specs/12-onboarding.md"
}
```

## Refusals

A refusal is a status code with `{ error: { code, message } }`. See [Errors](/docs/errors).
