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

# API v2

> Authentication, response codes, pagination, and the stability promise for the /v2 namespace

`/v2` is where new Sleekplan endpoints are built. It sits **alongside** `/v1` rather than replacing it: your existing integration keeps working unchanged, the same [API key](/docs/authentication/api-keys) authenticates both, and you can call either namespace from the same codebase.

## Authentication

`/v2` accepts **Bearer tokens only**. Unlike `/v1`, there is no Basic auth and no `?api_key=` query parameter.

```bash theme={"system"}
curl https://api.sleekplan.com/v2/groups \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Your key identifies the workspace, so **no workspace or product ID appears anywhere in a `/v2` URL**. Get your key from **Settings → Developer**.

A credential that is missing, malformed, or simply not an API key — an admin dashboard session token, for example — is rejected with `401`.

## Response envelope

Every response carries the same envelope as `/v1`: a `status` and a `data` object.

<CodeGroup>
  ```json Success theme={"system"}
  {
    "status": "success",
    "data": { "group_id": 17, "name": "Acme Corporation" }
  }
  ```

  ```json Error theme={"system"}
  {
    "status": "error",
    "data": { "key": "not_found", "message": "Group not found" }
  }
  ```
</CodeGroup>

Errors carry a machine-readable `data.key`. Branch on that rather than on the message, which is written for humans and may be reworded.

A validation error carries `data.errors` instead of a message, one entry per offending field:

```json 400 theme={"system"}
{
  "status": "error",
  "data": {
    "key": "validation_error",
    "errors": [
      { "field": "id", "message": "An id is required." }
    ]
  }
}
```

## Response codes

**Success**

| Status | When                                  | Body                            |
| ------ | ------------------------------------- | ------------------------------- |
| `200`  | A read, or an update that was applied | The resource, or a page of them |
| `201`  | A resource was created                | The created resource            |
| `204`  | A resource was deleted or unassigned  | **Empty** — do not parse it     |

**Errors**

| Status | `data.key`         | Meaning                                                                                    |
| ------ | ------------------ | ------------------------------------------------------------------------------------------ |
| `400`  | `validation_error` | A field is missing or malformed; `data.errors` lists them                                  |
| `401`  | `unauthorized`     | Missing, malformed, or non-API-key credential                                              |
| `403`  | `forbidden`        | The key's user lacks the permission for this action                                        |
| `404`  | `not_found`        | No such resource **in this workspace**                                                     |
| `409`  | `identifier_taken` | That identifier is already used in this workspace                                          |
| `429`  | `rate_limit`       | Over the rate limit                                                                        |
| `500`  | `write_failed`     | The write could not be completed — the resource is unchanged, so the call is safe to retry |
| `500`  | `internal_error`   | Something failed on our side that the endpoint does not name specifically                  |

<Note>
  `404` means "not in your workspace", which is the same answer you get for a resource that belongs to someone else. A `/v2` request can never reach another workspace's data, because the key decides which workspace it runs against.
</Note>

### The one that is not a normal error

<Warning>
  A feature your plan does not include answers with HTTP **`200`**, not `402` or `403` — and the key is in **`data.code`**, not `data.key`. Checking only the status code makes this read as a success.
</Warning>

```json 200 theme={"system"}
{
  "status": "error",
  "data": {
    "code": "upgrade_required",
    "message": "User groups is available on the Business plan and above.",
    "feature": "groups",
    "feature_name": "User groups",
    "required_plan": "business",
    "required_plan_name": "Business",
    "cta": "billing"
  }
}
```

Treat `status === "error"` as the reliable signal, then look at `data.key` or `data.code`.

## Pagination

List endpoints take `page` and `per_page` and return the page alongside the items.

| Parameter  | Default | Notes                                                          |
| ---------- | ------- | -------------------------------------------------------------- |
| `page`     | `0`     | **Zero-based.** The first page is `0`, not `1`                 |
| `per_page` | `30`    | Maximum `100`; anything higher is clamped rather than rejected |

```json theme={"system"}
{
  "status": "success",
  "data": {
    "items": [],
    "has_more": true,
    "page": 0
  }
}
```

`page` echoes the page you asked for. Keep requesting the next one while `has_more` is `true` — there is **no total count**, so do not compute a page count.

## Rate limits

**300 requests per 60 seconds per workspace**, independent of plan. Exceeding it returns `429` with `"key": "rate_limit"`.

## Stability

<Info>
  Changes to `/v2` are **additive**. We may add endpoints, optional parameters, and response fields, but we do not remove or rename existing ones, change a field's type, or change a status code.
</Info>

Write your integration to **ignore response fields it does not recognise**, and new fields will never break it. There is no version to pin and no upgrade to schedule — a breaking change would arrive as a new namespace, not as a change to this one.

## Endpoints

Every `/v2` endpoint, with its parameters, request bodies, and responses, is in the reference under **Endpoints (v2)**.

<CardGroup cols={3}>
  <Card title="Groups" icon="building" href="/api-reference/group/list-groups">
    Companies, accounts, and teams, and who belongs to them.
  </Card>

  <Card title="Documents" icon="file-lines" href="/api-reference/document/list-documents">
    Plans, specs, research — the thinking behind your feedback.
  </Card>

  <Card title="API keys" icon="key" href="/docs/authentication/api-keys">
    Create, use, and rotate your key.
  </Card>
</CardGroup>
