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

# API access

> Keys, scopes, pagination and the two errors worth handling, for reading a workspace from your own systems.

This page is the prose half of the API: how a key authenticates, what it is
allowed to reach, and how to page and fail well. The
[API reference](/api-reference) is the generated half, listing every operation
with a runnable example.

## Authentication

Every request carries a key as a bearer token. Create one in
**Settings > Developer**.

```bash theme={null}
curl https://api.openpulse.cloud/v1/results \
  -H "Authorization: Bearer op_live_..."
```

<Note>
  A key acts as a **member** of your workspace and can never perform admin
  actions. It cannot create or run listeners, change billing, or create another
  key. That holds regardless of who created it.
</Note>

## Permissions

A key reaches only what its scopes allow, and anything not granted is refused.
There is no scope that grants admin access.

| Scope               | Allows                                                                                                                                  |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `signals:read`      | List and read signals, their scores and their reasoning.                                                                                |
| `accounts:read`     | List companies and what has been found about them.                                                                                      |
| `listeners:read`    | List listeners and read their configuration. Cannot change one.                                                                         |
| `listeners:analyse` | Turn a URL into a listener plan: keywords, exclusions and per-source queries. Rate limited, and counted against your monthly allowance. |
| `pipeline:read`     | List deals, their stages and the return figures.                                                                                        |
| `pipeline:write`    | Create deals and move them between stages.                                                                                              |
| `collections:write` | Save signals, and write notes against them.                                                                                             |
| `export:read`       | Download the CSV exports.                                                                                                               |

Every list endpoint is scoped to the workspace its key belongs to. You never
name an organisation: the key determines it.

| Endpoint                    | Scope               |
| --------------------------- | ------------------- |
| `GET /v1/results`           | `signals:read`      |
| `GET /v1/results/stats`     | `signals:read`      |
| `GET /v1/accounts`          | `accounts:read`     |
| `GET /v1/accounts/:key`     | `accounts:read`     |
| `GET /v1/pipeline`          | `pipeline:read`     |
| `GET /v1/pipeline/roi`      | `pipeline:read`     |
| `POST /v1/pipeline`         | `pipeline:write`    |
| `PATCH /v1/pipeline/:id`    | `pipeline:write`    |
| `POST /v1/collections`      | `collections:write` |
| `POST /v1/signals/:id/save` | `collections:write` |
| `POST /v1/notes`            | `collections:write` |
| `GET /v1/exports/*.csv`     | `export:read`       |

## Pagination

List endpoints return a page and a cursor. Pass the cursor back as `cursor` to
get the next one. A response with no `nextCursor` is the last page.

```json theme={null}
{
  "items": [ ... ],
  "nextCursor": "2026-09-01T10:00:00.000Z|sig_abc"
}
```

## Errors

Two status codes are worth handling apart from the rest, because they look
similar and want opposite responses.

A **402** means the workspace's plan does not include something, and the answer
is to upgrade. A **429** means it does, but not yet: those carry a `readyAt`
telling you when to retry. Retrying a 402 will never succeed.

```json theme={null}
{
  "message": "Go includes 5 exports a month...",
  "code": "export_quota_reached",
  "readyAt": "2026-10-01T00:00:00.000Z",
  "used": 5,
  "allowed": 5
}
```

## If a key leaks

Revoke it in **Settings > Developer**. It stops working within a minute, and
immediately for the API's own cache. Revoked keys stay in the list rather than
being deleted, because the record that a key existed is what you need when
working out what it touched.

<Note>
  Only a hash of each key is stored, so a lost secret cannot be recovered or
  shown to you again. Revoke it and create another.
</Note>

## Related

<CardGroup cols={2}>
  <Card title="API reference" icon="code" href="/api-reference">
    Every operation, generated from the routes a key can actually call.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/webhooks/overview">
    Be told when something happens, instead of polling these endpoints for it.
  </Card>

  <Card title="MCP & Agents" icon="robot" href="/mcp/overview">
    The same data for an assistant, over OAuth rather than a static key.
  </Card>

  <Card title="Workspace and settings" icon="gear" href="/guides/workspace-and-settings">
    Where keys are created, and why one is never an admin.
  </Card>
</CardGroup>


## Related topics

- [Getting results out](/guides/getting-results-out.md)
- [Workspace, people and settings](/guides/workspace-and-settings.md)
- [What Open Pulse does](/index.md)
