# Overview

The Polyscope API lets you manage servers, repositories, and workspaces programmatically. All endpoints are prefixed with `/api/v1` and require authentication via a Bearer token.

For higher-level integrations, see the [Laravel / PHP SDK](/docs/integrations/laravel-php-sdk) and [JavaScript / TypeScript SDK](/docs/integrations/javascript-sdk) which wrap this API with a convenient interface.

## Base URL

All API endpoints use the following base URL:

```
https://getpolyscope.com/api/v1
```

## Authentication

All API requests require a valid Bearer token in the `Authorization` header:

```
Authorization: Bearer your-api-token
```

You can create and manage API tokens from the [Settings > API Tokens](/settings/api-tokens) page. See the [Authentication](/docs/api/authentication) page for details.

## Response Format

All successful responses return a JSON object with a `data` key:

```json
{
    "data": { ... }
}
```

List endpoints return an array:

```json
{
    "data": [
        { ... },
        { ... }
    ]
}
```

## Error Responses

When a request fails, the API returns a JSON error object:

```json
{
    "error": {
        "code": "server_offline",
        "message": "No server available for this workspace."
    }
}
```

Common error codes:

| Code | HTTP Status | Description |
|---|---|---|
| `validation_error` | 422 | Invalid input data |
| `unauthenticated` | 401 | Invalid or missing API token |
| `not_found` | 404 | The requested server or workspace does not exist |
| `server_offline` | 503 | Target Polyscope server is not connected |
| `server_timeout` | 504 | Server did not respond in time |
| `relay_error` | 500 | Communication error with the server |

`not_found` and `server_offline` mean different things and are worth handling separately: `not_found` is final, `server_offline` means the resource may well exist on a server that is currently unreachable — retry later rather than treating it as deleted.

## Available Resources

| Resource | Description |
|---|---|
| [Servers](/docs/api/servers) | List connected Polyscope servers |
| [Models](/docs/api/models) | List available agents and their models per server |
| [Repositories](/docs/api/repositories) | List repositories across servers |
| [Workspaces](/docs/api/workspaces) | Create, list, view, and delete workspaces |
| [Messages](/docs/api/messages) | Read and send workspace messages |
| [Actions](/docs/api/actions) | Trigger diffs, commits, PRs, and stop agents |
| [Team](/docs/api/team) | Invite teammates to your Polyscope team |

## Changelog

### July 29, 2026

Three corrections to error responses. If your client only branches on `2xx` vs. everything else, nothing changes — but calls that used to return an empty `200` now return the error that was actually happening.

- **Explicitly requested servers no longer disappear.** `GET /repositories` and `GET /workspaces` with a `server_id` now return `404 not_found` for a server that isn't on your account, `503 server_offline` for one that isn't connected, and the underlying `504 server_timeout` / `500 relay_error` when the call to it fails. Previously all four cases returned `200` with an empty `data` array, indistinguishable from a server that genuinely had nothing. Requests without `server_id` are unchanged: they still aggregate across servers and skip any that don't respond.
- **Workspace lookups distinguish "gone" from "unreachable".** `GET`, `DELETE`, the message endpoints, and the action endpoints now return `404 not_found` when every connected server confirms it doesn't have the workspace. `503 server_offline` is reserved for a genuinely inconclusive answer — no server connected, or one failed to respond and may be the owner. Deleting an already-deleted workspace therefore returns `404` rather than `503`, which makes suppressing `404` a safe way to get idempotent deletes.
- **The `after` cursor on messages is a message id.** It was documented as an ISO-8601 timestamp, which never worked — the value is cast to an integer and compared against message ids. See [Messages](/docs/api/messages).
