HTTP API
Base URL: https://api.gutternote.com
Authentication
Every /v1 request carries the project’s public key and is authorised by its Origin:
Gutternote-Key: pk_live_...Origin: https://gutternote-git-fix-nav-acme.vercel.appThe key identifies the project; the origin authorises the call. An origin that doesn’t
match one of the project’s patterns returns 403 origin_not_allowed, and no CORS headers
are echoed back.
Endpoints
GET /v1/config
Widget bootstrap: project identity and backend capabilities.
{ "projectId": "…", "name": "Acme Website", "backend": "postgres", "capabilities": { "attachments": true, "edit": true, "delete": true, "guestAuthors": true, "lowLatencyReads": true }}GET /v1/threads?path=/pricing
Anchors for one page. Never touches the body store, so pins render at full speed even when bodies live in GitHub. Bodies are omitted.
Optional: deploymentId, includeResolved=true.
POST /v1/threads
{ "anchor": { "path": "/pricing", "strategy": "selector", "selector": "[data-testid=\"cta\"]", "textQuote": "Start free trial", "x": 0.5, "y": 0.5, "viewportW": 1440, "viewportH": 900 }, "deployment": { "url": "https://…vercel.app", "branch": "fix/nav", "prNumber": 42 }, "author": { "id": "guest_9a1", "kind": "guest", "displayName": "Dana Reed" }, "markdown": "The CTA is 4px off."}Returns 201 with the thread.
GET /v1/threads/{id}
The thread with its bodies, resolved from whichever store holds them. This is the only read that touches the body store, which is why the widget calls it on thread open rather than on page load.
POST /v1/threads/{id}/replies
PATCH /v1/threads/{id}/status
{ "status": "resolved", "by": "Dana Reed" }Status is anchor-layer state, so this never touches the body store.
Errors
{ "error": { "code": "unsupported_by_backend", "message": "the github backend cannot store attachments" } }| Status | Meaning |
|---|---|
400 | Malformed request or invalid anchor |
401 | Missing or unknown project key |
403 | Origin not registered for the project |
404 | Thread not found |
409 | The project’s backend can’t do this — e.g. attachments on github |
502 | The configured body store failed. Retryable. |
502 is worth calling out: for the github and external backends the body store is a
system Gutternote doesn’t control, so a failure there is distinct from a Gutternote bug and is
usually worth retrying.