# The local API

> The HTTP API of the Graspable agent on your computer. Access tokens and their levels, and the requests for projects, files and runs.

Source: https://graspable.dev/docs/api

The Graspable app talks to its agent over an HTTP API on your computer. Scripts and other programs can use the same API. It listens on `127.0.0.1` only.

For most uses [the grasp command](https://graspable.dev/docs/cli.md) or [the MCP server](https://graspable.dev/docs/mcp-server.md) is simpler. Use the API when you want to build your own tool.

## Address and access

```bash
grasp api
# http://127.0.0.1:51877
```

The port changes each time the agent starts, so ask for the address each time, or read it from `~/.graspable/agent/api.json`.

Every request needs `Authorization: Bearer <token>`. Create a token in **Settings → Plugins and connectors → Access tokens**, or:

```bash
grasp token create "my script" --scope run
```

The token is shown once. Graspable stores only a hash of it.

| Level | May |
|---|---|
| `read` | Look at projects, files, runs and usage |
| `run` | Also create projects, edit files, start and steer runs, answer approvals, start previews, use memory |
| `admin` | Also change plugins, skills, components, sign-ins and tokens, move projects to the cloud, delete projects |

A request above the token's level is answered with `403`.

## Projects and files

| Request | Does |
|---|---|
| `GET /projects` | List projects |
| `POST /projects` `{ "name", "template" }` | Create a project. Packages install in the background; `install` becomes `done` |
| `GET /projects/:id` | One project |
| `GET /projects/:id/files` | File paths |
| `GET /projects/:id/file?path=App.jsx` | `{ "path", "content" }` |
| `PUT /projects/:id/file` `{ "path", "content" }` | Write a file |
| `POST /projects/:id/preview` | Start the preview: `{ "url", "port" }` |
| `DELETE /projects/:id/preview` | Stop the preview |
| `POST /projects/:id/check` | Build and load in a headless browser: `{ "pass", "build", "browser" }` |

Paths are relative to the project. Paths that leave the project are refused.

## Runs

`POST /runs` starts a run and returns `{ "runId" }`:

```json
{
  "projectId": "3f9a12bc",
  "prompt": "Add a floor that reflects the planets.",
  "engine": "claude-code",
  "approvalPolicy": "guarded"
}
```

| Field | Meaning |
|---|---|
| `engine` | `claude-code` or `codex` (their own sign-in on this computer), or `pi` (the Graspable agent) |
| `provider` | For `pi`: `{ "provider": "anthropic", "modelId": "…", "apiKey": "…" }`. For the others, optionally `{ "provider": "<engine>", "modelId": "…" }` |
| `approvalPolicy` | `auto`, `guarded` (default) or `strict` |
| `budget` | `{ "maxCostUsd", "maxTokens" }`: the run stops when either is passed |
| `plugins` | Secret fields of switched-on plugins: `{ "<plugin>": { "<FIELD>": "…" } }` |

| Request | Does |
|---|---|
| `GET /runs?projectId=:id` | Runs of a project |
| `GET /runs/:id` | `{ "state", "events" }` |
| `GET /runs/:id/events?since=<seq>` | The same events as a stream (server-sent events) until the run is finished |
| `POST /runs/:id/approve` `{ "toolCallId", "approved" }` | Answer an approval request |
| `POST /runs/:id/steer` `{ "text" }` | Send the agent a message while it works |
| `POST /runs/:id/cancel` | Stop the run |
| `POST /runs/:id/revert` | Undo the run's file changes |

A run's `state` is `running`, `waiting_user`, `completed`, `failed` or `cancelled`.

## Events

Each event is `{ "runId", "seq", "ts", "event" }`. The kinds you will use most:

| `event.type` | Meaning |
|---|---|
| `text` | The agent said something |
| `tool_call`, `tool_result` | A step and its result |
| `approval_required` | The run waits for an answer. Send `toolCallId` to `/approve` |
| `fragment_update` | A file was written: `filePath`, `code` |
| `verification` | A check finished: `kind` (`build`, `smoke`, `xr`), `pass`, `summary` |
| `completion` | The end: `status` (`success`, `failure`, `cancelled`) and `summary` |

## An example

```bash
API=$(grasp api | head -1)
TOKEN=<your token>
curl -s -X POST "$API/runs" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"projectId":"3f9a12bc","prompt":"Make the sun pulse slowly.","engine":"codex"}'
```
