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

# REST API server

> Expose local buttons over HTTP with buttons serve.

`buttons serve` runs a local HTTP API that exposes the same press path as the CLI.

```bash theme={null}
buttons serve
```

By default it binds to `127.0.0.1:8080`.

## Endpoints

| Method | Path | Auth | Purpose |
| - | - | - | - |
| `GET` | `/api/health` | No | Liveness check. |
| `GET` | `/api/buttons` | Yes | List buttons. |
| `GET` | `/api/buttons/{name}` | Yes | Read a button spec. |
| `POST` | `/api/buttons/{name}/press` | Yes | Press a button. |
| `GET` | `/api/buttons/{name}/runs` | Yes | Recent run history. |

## Press a button

```bash theme={null}
curl -sS http://127.0.0.1:8080/api/buttons/weather/press \
  -H "Content-Type: application/json" \
  -d '{"args":{"city":"Miami"},"timeout":30}'
```

The response uses the same envelope as CLI JSON output:

```json theme={null}
{
  "ok": true,
  "data": {
    "button": "weather",
    "status": "ok"
  }
}
```

## Auth

Every endpoint except `/api/health` requires a bearer token when an API key is configured.

The key comes from the first available source:

1. `--api-key`
2. `API_KEY` battery
3. `BUTTONS_API_KEY` environment variable

```bash theme={null}
export BUTTONS_API_KEY="$(openssl rand -hex 16)"
buttons batteries set API_KEY "$BUTTONS_API_KEY" --global
buttons serve
```

Call with:

```bash theme={null}
curl -H "Authorization: Bearer $BUTTONS_API_KEY" \
  http://127.0.0.1:8080/api/buttons
```

## Binding rules

Without an API key, `buttons serve` only allows loopback binding. Binding `0.0.0.0` without auth is refused.

```bash theme={null}
buttons serve --host 0.0.0.0 --api-key "$(openssl rand -hex 16)"
```

## HTTP buttons are gated

Pressing HTTP buttons through the REST API is disabled by default because an exposed API can otherwise trigger outbound requests.

Enable it explicitly:

```bash theme={null}
buttons serve --allow-http-buttons
```

Code and prompt buttons are pressable without this flag.

## Trigger engine

`buttons serve` also runs the in-process button trigger engine and mounts webhook trigger routes alongside the API. Button triggers (`buttons trigger add`) fire here:

* `cron` triggers run on their schedule.
* `watch` triggers poll their watched file (mtime/size, 500ms).
* `webhook` triggers mount a `POST <path>` route on the same listener, gated by the optional shared `--token` (`X-Buttons-Token` header or `?token=`).

Disable the engine to run the API alone:

```bash theme={null}
buttons serve --no-triggers
```

This is the button-trigger layer (single shared token, no tunnel). Drawer webhook triggers — n8n-style auth behind a Cloudflare tunnel — are a separate layer served by [`buttons webhook listen`](/cli/buttons_webhook).

## Related

* [buttons serve](/cli/buttons_serve)
* [JSON output](/concepts/json-output)
* [Batteries](/cli/buttons_batteries)


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