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

# Add external annotations to Plannotator

> Tested HTTP schemas for adding tool findings to a live Plannotator plan, document, or code review session.

External annotations let a local tool add findings to an open Plannotator session. The user sees them immediately and they are included when Plannotator exports feedback.

Copy the active session URL from the terminal or `plannotator sessions`, then replace `PORT` below. The endpoint is unauthenticated and should remain on the local or forwarded trusted boundary.

## Add a plan or document comment

A sidebar comment needs `source` and `text`. Its default type is `GLOBAL_COMMENT`.

```bash theme={null}
curl -X POST http://localhost:PORT/api/external-annotations \
  -H 'Content-Type: application/json' \
  -d '{
    "source": "style-checker",
    "type": "GLOBAL_COMMENT",
    "text": "Define the rollback condition before implementation.",
    "author": "Docs check"
  }'
```

To pin a comment or deletion to existing text, use `COMMENT` or `DELETION` and include the exact phrase in `originalText`:

```bash theme={null}
curl -X POST http://localhost:PORT/api/external-annotations \
  -H 'Content-Type: application/json' \
  -d '{
    "source": "policy-checker",
    "type": "COMMENT",
    "originalText": "Deploy immediately after merge",
    "text": "Add the verification and rollback steps first."
  }'
```

Plan and document fields:

| Field          | Requirement                                                                        |
| -------------- | ---------------------------------------------------------------------------------- |
| `source`       | Required, non-empty string identifying the tool                                    |
| `text`         | Required, non-empty annotation text                                                |
| `type`         | Optional: `GLOBAL_COMMENT`, `COMMENT`, or `DELETION`; defaults to `GLOBAL_COMMENT` |
| `originalText` | Required and non-empty for `COMMENT` and `DELETION`                                |
| `author`       | Optional display name                                                              |

Plannotator creates the annotation ID and placement metadata. Do not send a `blockId`.

## Add a code review finding

This example creates a line-level concern on the new side of a diff:

```bash theme={null}
curl -X POST http://localhost:PORT/api/external-annotations \
  -H 'Content-Type: application/json' \
  -d '{
    "source": "eslint",
    "scope": "line",
    "type": "concern",
    "filePath": "src/session.ts",
    "lineStart": 48,
    "lineEnd": 48,
    "side": "new",
    "text": "This timer is not cleared when the request is aborted.",
    "author": "eslint bridge"
  }'
```

For a suggestion, include replacement code:

```json theme={null}
{
  "source": "refactor-checker",
  "scope": "line",
  "type": "suggestion",
  "filePath": "src/math.ts",
  "lineStart": 12,
  "lineEnd": 12,
  "side": "new",
  "text": "Avoid mutating the input.",
  "originalCode": "items.sort()",
  "suggestedCode": "items.toSorted()"
}
```

Review fields:

| Field                    | Requirement                                                  |
| ------------------------ | ------------------------------------------------------------ |
| `source`                 | Required, non-empty string identifying the tool              |
| `scope`                  | `line`, `file`, or `general`; defaults to `line`             |
| `filePath`               | Required for `line` and `file`; omitted for `general`        |
| `lineStart`, `lineEnd`   | Both required numbers for `line`                             |
| `side`                   | `new` or `old`; defaults to `new`                            |
| `type`                   | `comment`, `suggestion`, or `concern`; defaults to `comment` |
| `text`, `suggestedCode`  | At least one must be a string                                |
| `originalCode`, `author` | Optional strings                                             |

## Add a batch

Wrap multiple valid objects in `annotations`. The request succeeds with `201` and returns the generated IDs.

```bash theme={null}
curl -X POST http://localhost:PORT/api/external-annotations \
  -H 'Content-Type: application/json' \
  -d '{
    "annotations": [
      { "source": "audit", "scope": "file", "filePath": "src/a.ts", "text": "Add a test for the error path." },
      { "source": "audit", "scope": "general", "text": "The migration needs a rollback command." }
    ]
  }'
```

An empty batch or one invalid object returns `400` and adds nothing.

## Read, update, and remove annotations

| Request                                        | Result                                                                       |
| ---------------------------------------------- | ---------------------------------------------------------------------------- |
| `GET /api/external-annotations`                | `{ "annotations": [...], "version": N }`                                     |
| `GET /api/external-annotations?since=N`        | `304 Not Modified` when the version is unchanged                             |
| `GET /api/external-annotations/stream`         | Server-sent event snapshot followed by add, update, remove, and clear events |
| `PATCH /api/external-annotations?id=UUID`      | Merge JSON fields into one annotation; the ID cannot be changed              |
| `DELETE /api/external-annotations?id=UUID`     | Remove one annotation                                                        |
| `DELETE /api/external-annotations?source=NAME` | Remove every annotation from one source                                      |
| `DELETE /api/external-annotations`             | Clear all external annotations                                               |

The event stream sends a heartbeat every 30 seconds. Use the snapshot endpoint with `since` as a polling fallback.

External annotations live only for the current session. Persist findings in your own tool if they must survive after the Plannotator server closes.

Last verified against Plannotator OSS v0.23.1 on July 18, 2026. Maintained by the Plannotator project.
