---
title: Public API
description: Use the Feeblo Public API v1 to read and manage a workspace's posts, comments, votes, tags, boards, changelog entries, companies, and end users over HTTP with an API key.
---

The Public API is the versioned HTTP surface for one workspace. Use it to sync feedback with a CRM, file posts from a support tool, publish changelog entries from a CMS, or read end-user records without a browser session.

It is **not** the [widget HTTP API](/developers/api), which anonymous visitors call, and **not** the dashboard transport. The dashboard uses session-authenticated RPC; the Public API uses an API key on every request.

| Surface | Where |
| --- | --- |
| Base URL | `https://api.feeblo.com/api/v1` |
| OpenAPI 3.1 document | `https://api.feeblo.com/api/v1/openapi.json` |
| Reference (readable without a key) | [api.feeblo.com/api/v1/docs](https://api.feeblo.com/api/v1/docs) |
| MCP endpoint | `https://api.feeblo.com/mcp` — see [MCP server](/developers/mcp) |
| Agent authentication guide | [feeblo.com/auth.md](https://feeblo.com/auth.md) |

Self-hosted installations serve the same paths from their own `API_URL`.

## Authentication

Send a workspace API key in the `x-api-key` header. There is no OAuth flow and no session cookie.

```bash
curl https://api.feeblo.com/api/v1/boards \
  -H "x-api-key: fbk_..."
```

A workspace admin or owner creates keys in the dashboard under **Settings → Developers**. The plaintext key is shown once, starts with `fbk_`, and is bound to the workspace that owns it. No request parameter can point a key at another workspace.

The Public API is included in the Starter and Professional plans. A workspace on the Free plan cannot create keys. Keys survive a downgrade and start working again after an upgrade — no rotation is required. See [Plans](#plans).

### Scopes

A key is created with a fixed set of scopes and never gains one later. Every key receives the read scopes for boards, posts, comments, votes, tags, and changelog. The write scopes, the CRM scopes, and the end-user scopes are opt-in at creation:

| Capability | Read scopes | Write scopes |
| --- | --- | --- |
| Boards | `boards.read` | — |
| Posts | `posts.read` | `posts.create`, `posts.update`, `posts.delete`, `posts.merge` |
| Comments | `comments.read` | `comments.create`, `comments.update`, `comments.delete`, `comments.pin` |
| Votes | `votes.read` | `votes.create`, `votes.delete` |
| Tags | `tags.read` | `tags.create`, `tags.update`, `tags.delete`, `tags.assign` |
| Changelog | `changelog.read` | `changelog.create`, `changelog.update`, `changelog.delete`, `changelog.publish` |
| Companies | `companies.read` | `companies.create`, `companies.update`, `companies.delete` |
| End users | `end_users.read` | `end_users.write` |

Publishing is separate from editing because it emails every changelog subscriber. Merging is separate from editing because it archives one post and moves its comments and votes onto another. If an integration needs more than the key was issued, create a new key with the wider set; a key cannot be widened.

## Requests and responses

Every response is JSON. Errors carry a machine-readable `_tag`:

```json
{
  "_tag": "FORBIDDEN_SCOPE",
  "message": "This API key is missing the posts.create scope."
}
```

| Status | `_tag` | Meaning |
| --- | --- | --- |
| 401 | `MISSING_API_KEY` | No `x-api-key` header, or an empty one. |
| 401 | `INVALID_API_KEY` | Unknown, revoked, expired, or disabled key. |
| 403 | `FORBIDDEN_SCOPE` | The key lacks the scope the endpoint requires. |
| 403 | `PLAN_REQUIRES_UPGRADE` | The workspace plan does not include the Public API. |
| 404 | `NOT_FOUND` | The record does not exist in this workspace. |
| 409 | `CONFLICT` | The write conflicts with the current state. |
| 429 | `RATE_LIMITED` | The per-key budget is exhausted; read `Retry-After`. |
| 500 | `INTERNAL_ERROR` | Unexpected server failure. |
| 503 | `SERVICE_UNAVAILABLE` | A required dependency is unavailable; requests fail closed. |

Switch on `_tag`, not on `message`. Codes are append-only within v1.

List endpoints accept `limit` (1–100, default 25) and an opaque `cursor`. The response carries the next cursor as `nextCursor`:

```json
{
  "data": [],
  "nextCursor": null
}
```

## Rate limits

Limits are per key, not per IP, and are shared by reads and writes: **300 requests per minute**. Every successful response and every `429` reports the budget:

| Header | Meaning |
| --- | --- |
| `X-RateLimit-Limit` | Requests allowed in the current window. |
| `X-RateLimit-Remaining` | Requests left after this one. |
| `X-RateLimit-Reset` | When the budget next allows a request, as a Unix timestamp in seconds. |

A request refused before it spends a budget — a missing key, an invalid key, or a plan without the API — carries none of these headers.

## Plans

The Public API is included in Starter and Professional. On the Free plan, key creation is blocked and existing keys answer `403 PLAN_REQUIRES_UPGRADE`. Keys are kept while the workspace is on Free, can still be revoked, and work again on upgrade.

## Versioning

The path carries the version (`/api/v1`). Within v1, fields may be added, new error codes may appear, and optional request fields may be added. Existing fields keep their meaning and type, and are not removed. A breaking change ships as `/api/v2`; when a v2 exists, v1 responses carry `Deprecation` and `Sunset` headers.

## Companion surfaces

- **MCP:** the same operations as tools over streamable HTTP at `https://api.feeblo.com/mcp`, with the same key. See [MCP server](/developers/mcp).
- **Discovery:** `https://feeblo.com/.well-known/api-catalog`, `https://api.feeblo.com/.well-known/api-catalog`, and `https://api.feeblo.com/.well-known/mcp.json`.
- **Agent guide:** `https://feeblo.com/auth.md` and `https://api.feeblo.com/auth.md` cover key creation and client setup without a browser.
- **Full endpoint reference:** [api.feeblo.com/api/v1/docs](https://api.feeblo.com/api/v1/docs), generated from the same OpenAPI document the API serves.
