# Getting started with the Plansmith API

The base URL, how to authenticate, and the one error rule worth knowing before you start.



The Plansmith API is a versioned JSON API. Every page in this section is generated from the same
OpenAPI document the server publishes at
[`/v1/openapi.json`](https://api.plansmith.co/v1/openapi.json), so what you read here is what the
API actually accepts and returns.

## Base URL [#base-url]

```text
https://api.plansmith.co/v1
```

<Callout>
  Pointing a local client at a dev server needs the `/api` segment:
  `http://localhost:3000/api/v1/me`. The `api.plansmith.co` host rewrites `/v1` onto it for you, and
  nothing else does.
</Callout>

## Authentication [#authentication]

Every request carries a bearer credential:

```bash
curl -H "Authorization: Bearer psk_read_…" https://api.plansmith.co/v1/me
```

Two kinds work on the same header: a **personal API key** (`psk_…`) minted in Settings → API keys
or with `plansmith keys create`, and an **OAuth access token** (`plan_at_…`) obtained by the CLI or
an MCP client.

Both act as the human they belong to. A credential reaches exactly the plans that person can reach,
and scope (`read` or `write`) is a ceiling on top of that, never a widening of it.

## Errors [#errors]

Errors come back in one envelope, on every endpoint:

```json
{
  "error": {
    "code": "not_found",
    "message": "No such plan."
  }
}
```

<Callout>
  **A plan you cannot read answers 404, exactly like a plan that does not exist.** That is
  deliberate: a 403 next to a 404 would tell you which private plans are real. The only 403 you will
  see on plan content is when you can read a plan but not edit it.
</Callout>

## Shapes worth knowing up front [#shapes-worth-knowing-up-front]

Collections are **named**, not wrapped in a generic envelope: `GET /v1/api-keys` answers
`{ "keys": [ … ] }`, `GET /v1/projects` answers `{ "projects": [ … ] }`.

Deletes answer **200 with a small acknowledgement**, not 204: `{ "deleted": true }`,
`{ "removed": true }`, or a count.

Plans and Specs are addressed by their **handles** (`PLAN-12`, `SPEC-3`) wherever a URL takes one,
and `needsFirst` comes back as handles too, so you can render "needs SPEC-3 first" without building
your own id map.

## Versioning [#versioning]

The path carries the version. `/v1` will not change shape underneath you: fields are added, never
removed or repurposed, and a breaking change would arrive as `/v2`.

## Trying a request [#trying-a-request]

Every endpoint page has a playground. Fill in a key and send a real request; without one you get a
real `401`, which is the fastest way to confirm you are reaching the right host.
