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

# API overview

> Common request and response behavior for the bisibility REST API.

Use REST API v1 to complete four common tasks:

1. [Create a project](/docs/docs/api/projects).
2. [Add keywords](/docs/docs/api/keywords).
3. [Start a rank check](/docs/docs/api/checks).
4. [Retrieve ranking history](/docs/docs/api/rank-history).

## Client libraries

| Library                             | Install                        |
| ----------------------------------- | ------------------------------ |
| [Python](/docs/docs/sdks/python)         | `pip install bisibility`       |
| [TypeScript](/docs/docs/sdks/typescript) | `npm install @bisibility/sdk`  |
| [Go](/docs/docs/sdks/go)                 | `go get bisibility.com/sdk-go` |
| [MCP server](/docs/docs/sdks/mcp)        | `npm install @bisibility/mcp`  |

Start with those task guides if you are building an integration. Use the route
inventory below as a reference after the first request works.

The REST API is served from:

```text theme={null}
/api/v1
```

Hosted:

```text theme={null}
https://bisibility.com/api/v1
```

Self-hosted:

```text theme={null}
https://your-host.example/api/v1
```

## Core resource routes

These core routes are handled by `lib/api/router.ts`. See
[`/openapi.json`](/docs/api/v1/openapi.json) for the full generated inventory.

| Method   | Path                              | Auth                    |
| -------- | --------------------------------- | ----------------------- |
| `GET`    | `/health`                         | No                      |
| `GET`    | `/openapi.json`                   | No                      |
| `GET`    | `/capabilities`                   | No                      |
| `GET`    | `/llms.txt`                       | No                      |
| `GET`    | `/provider-rates`                 | No                      |
| `GET`    | `/cost-estimate`                  | No                      |
| `GET`    | `/projects`                       | Yes                     |
| `POST`   | `/projects`                       | Yes                     |
| `GET`    | `/me`                             | Personal token          |
| `PATCH`  | `/me`                             | Personal token          |
| `GET`    | `/me/tokens`                      | Personal token          |
| `POST`   | `/me/tokens`                      | Personal or OAuth token |
| `DELETE` | `/me/tokens/{token_id}`           | Personal token          |
| `GET`    | `/projects/{project_id}`          | Yes                     |
| `PATCH`  | `/projects/{project_id}`          | Yes                     |
| `DELETE` | `/projects/{project_id}`          | Yes                     |
| `GET`    | `/projects/{project_id}/keywords` | Yes                     |
| `POST`   | `/projects/{project_id}/keywords` | Yes                     |
| `GET`    | `/keywords/{id}`                  | Yes                     |
| `PATCH`  | `/keywords/{id}`                  | Yes                     |
| `DELETE` | `/keywords/{id}`                  | Yes                     |
| `POST`   | `/keywords/bulk`                  | Yes                     |
| `POST`   | `/keywords/{id}/checks`           | Yes                     |
| `GET`    | `/keywords/{id}/rank-checks`      | Yes                     |
| `GET`    | `/rank-checks/{check_id}`         | Yes                     |
| `GET`    | `/api-keys`                       | Yes                     |
| `POST`   | `/api-keys`                       | Yes                     |
| `DELETE` | `/api-keys/{key_id}`              | Yes                     |
| `GET`    | `/projects/{project_id}/api-keys` | Yes                     |
| `POST`   | `/projects/{project_id}/api-keys` | Yes                     |
| `GET`    | `/projects/{project_id}/webhooks` | Yes                     |
| `POST`   | `/projects/{project_id}/webhooks` | Yes                     |
| `POST`   | `/cloud/import`                   | Migration token         |

Cloud import is also mounted at `/api/cloud/import` outside the `/api/v1` base
path for the in-app cloud migration handoff. The `/api/v1/cloud/import` path
re-exports the same handler. It is not currently listed in `/openapi.json`.

Inbound deploy hooks are also mounted outside `/api/v1` at
`POST /api/ingest/deploy`. See [Deploy webhooks](/docs/docs/api/deploy-webhooks).

[Alert rules](/docs/docs/api/alert-rules), [competitors](/docs/docs/api/competitors),
[provider connections](/docs/docs/api/providers), [saved views](/docs/docs/api/saved-views),
[signals](/docs/docs/api/signals), [personal access tokens](/docs/docs/api/personal-access-tokens),
[webhooks](/docs/docs/api/webhooks),
[notification preferences](/docs/docs/api/notification-preferences), and
[team](/docs/docs/api/team) routes have dedicated pages. Migration tokens are
covered in [Cloud import](/docs/docs/api/cloud-import).

`PUT`, `OPTIONS`, and other methods return `405 Method Not Allowed`.

## Response shapes

List routes return:

```json theme={null}
{
  "data": [],
  "meta": { "next_cursor": null }
}
```

Resource and mutation routes return the resource object directly. They are not
wrapped in `data`.

Discovery routes are mixed:

| Route           | Shape                |
| --------------- | -------------------- |
| `/health`       | Raw JSON object      |
| `/openapi.json` | Raw OpenAPI document |
| `/capabilities` | `{ "data": [...] }`  |
| `/llms.txt`     | Plain text           |

## Pagination

List routes accept:

| Query    | Description                                             |
| -------- | ------------------------------------------------------- |
| `limit`  | Page size. Defaults to `50`, maximum `200`.             |
| `cursor` | Cursor from the previous response's `meta.next_cursor`. |

The cursor is an opaque base64url value. Do not parse it in clients.

## Errors

Errors use `application/problem+json`.

```json theme={null}
{
  "type": "https://bisibility.com/problems/not_found",
  "title": "Not found",
  "status": 404,
  "detail": "Keyword not found.",
  "instance": "urn:bisibility:api:v1:/api/v1/keywords/kw_missing",
  "docs_url": "https://bisibility.com/docs/api/errors"
}
```

See [API errors](/docs/docs/api/errors).
