# First API request

Create a personal token, choose a workspace, and write and read a file with curl.

Last updated 8 November 2026

This walkthrough creates `/api-example/hello.md` in a workspace and reads its text back. You need a Cabane account, access to a workspace, Bash and curl with `--fail-with-body` support.

## 1. Create a token

In Cabane, open your avatar menu, then **Your settings → API keys**. Under **New personal access token**, enter a label and choose an expiration, then choose **Create token**. Copy the value while it is visible; Cabane shows it once. See [Authentication](https://cabane.ai/docs/authentication) for the complete token choices.

Run these commands in Bash. The prompt keeps the token out of the command itself:

~~~bash
CABANE_BASE='https://app.cabane.ai'
read -r -s -p 'Personal access token: ' CABANE_TOKEN
printf '\n'
~~~

Keep this terminal open for the remaining steps.

## 2. Choose a workspace

~~~bash
curl --silent --show-error --fail-with-body \
  --connect-timeout 10 --max-time 30 \
  "$CABANE_BASE/api/workspaces" \
  --header "Authorization: Bearer $CABANE_TOKEN"
~~~

The response contains a `workspaces` array. Find the workspace you want by its `name` and copy its `id`, which is a UUID. Use that value at the next prompt:

~~~bash
read -r -p 'Workspace id: ' CABANE_WORKSPACE_ID
~~~

## 3. Write a file

~~~bash
curl --silent --show-error --fail-with-body \
  --connect-timeout 10 --max-time 30 \
  "$CABANE_BASE/api/workspaces/$CABANE_WORKSPACE_ID/ops/mutate" \
  --header "Authorization: Bearer $CABANE_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary '{
    "op": "files.write",
    "args": {
      "path": "/api-example/hello.md",
      "content": "# Hello\n\nCreated from the Cabane API.\n"
    }
  }'
~~~

On the first run, the response is:

~~~json
{
  "ok": true,
  "result": {
    "path": "/api-example/hello.md",
    "mime": "text/markdown",
    "size": 38,
    "sha256": "edb3a4c9af5d8b0e6e755719bae5ffeee15c6aaca2bb994ec08f678dc116f52e",
    "created": true
  }
}
~~~

`ok: true` means the operation succeeded. `created: true` means it created a new file; the parent folder is created automatically if needed. `sha256` identifies the stored content.

Always inspect `ok`. An operation can fail inside an HTTP 200 response, which curl's `--fail-with-body` does not treat as an error.

If you repeat this request, the existing path produces `ok: false` with `error.kind: "conflict"` and `error.code: "name_conflict"`. Continue to the read below to verify the file from your first run. If the path already contained someone else's content, change `hello.md` to an unused filename in both the write and read requests. For a deliberate update, follow [Safe writes and retries](https://cabane.ai/docs/safe-writes-and-retries).

## 4. Read the file

~~~bash
curl --silent --show-error --fail-with-body \
  --connect-timeout 10 --max-time 30 \
  "$CABANE_BASE/api/workspaces/$CABANE_WORKSPACE_ID/ops/query" \
  --header "Authorization: Bearer $CABANE_TOKEN" \
  --header 'Content-Type: application/json' \
  --data-binary '{
    "op": "files.read",
    "args": {
      "path": "/api-example/hello.md"
    }
  }'
~~~

Check for `ok: true`. The `result.content` value should be `"# Hello\n\nCreated from the Cabane API.\n"`, and `result.sha256` should match the write response. `result.more: null` means the whole requested text was returned.

You have now written and read workspace content. Use the [Operation reference](https://cabane.ai/docs/api) to choose your next action, or follow [Conversations and agents](https://cabane.ai/docs/conversations-and-agents) to send a request to an agent.

When you finish this terminal session, clear the token variable:

~~~bash
unset CABANE_TOKEN
~~~
