Skill Tracer
Skills › Compound Engineering › ce-proof › api.md

api.md

176 lines · skills/ce-proof/references/api.md at 3449230

Open on GitHub
1# Proof web API reference
2
3Required read before any Proof HTTP call. Endpoints, operation tables, error handling, and lifecycle; the skill body carries the identity, credential, and safety boundaries.
4

Proof web API reference

Required read before any Proof HTTP call. Endpoints, operation tables, error handling, and lifecycle; the skill body carries the identity, credential, and safety boundaries.

Raw lines 1 to 4
5## Web API
6
7On Claude Code, each new `curl` pattern prompts for permission. Suggest the allowlist rule `"Bash(curl * https://www.proofeditor.ai/*)"` under `permissions.allow` if the user wants a quieter session; do not add it silently.
8
9Auth on document surfaces (preferred first):
11- `Authorization: Bearer <accessToken>`
12- `x-share-token: <accessToken>`
13- `?token=<accessToken>` on the request URL
15Canonical agent read/write (v3 only — do not invent other agent mutation paths):
17- Read: `GET /api/agent/<slug>/v3/document`
18- Write: `POST /api/agent/<slug>/v3/edit`

Web API

On Claude Code, each new curl pattern prompts for permission. Suggest the allowlist rule "Bash(curl * https://www.proofeditor.ai/*)" under permissions.allow if the user wants a quieter session; do not add it silently.

Auth on document surfaces (preferred first):

  • Authorization: Bearer <accessToken>
  • x-share-token: <accessToken>
  • ?token=<accessToken> on the request URL

Canonical agent read/write (v3 only — do not invent other agent mutation paths):

  • Read: GET /api/agent/<slug>/v3/document
  • Write: POST /api/agent/<slug>/v3/edit
Raw lines 5 to 19
20### Create a Shared Document
22No authentication required on the public create route. Returns a shareable URL with tokens.
24```bash
25curl -sS -X POST https://www.proofeditor.ai/share/markdown \
26 -H "Content-Type: application/json" \
27 -d '{"title":"My Doc","markdown":"# Hello\n\nContent here."}'
28```
30**Response fields to keep:**
32```json
34 "slug": "abc123",
35 "tokenUrl": "https://www.proofeditor.ai/d/abc123?token=xxx",
36 "accessToken": "xxx",
37 "ownerSecret": "yyy",
38 "shareUrl": "https://www.proofeditor.ai/d/abc123",
39 "_links": {
40 "read": "https://www.proofeditor.ai/api/agent/abc123/v3/document",
41 "edit": { "method": "POST", "href": "/api/agent/abc123/v3/edit" },
42 "delete": { "method": "DELETE", "href": "/api/documents/abc123" }
43 }
45```
47Use `tokenUrl` as the shareable link. Extract `slug`, `accessToken`, and `ownerSecret` immediately — `ownerSecret` is required for cleanup while the doc is still unclaimed.

Create a Shared Document

No authentication required on the public create route. Returns a shareable URL with tokens.

curl -sS -X POST https://www.proofeditor.ai/share/markdown \
  -H "Content-Type: application/json" \
  -d '{"title":"My Doc","markdown":"# Hello\n\nContent here."}'

Response fields to keep:

{
  "slug": "abc123",
  "tokenUrl": "https://www.proofeditor.ai/d/abc123?token=xxx",
  "accessToken": "xxx",
  "ownerSecret": "yyy",
  "shareUrl": "https://www.proofeditor.ai/d/abc123",
  "_links": {
    "read": "https://www.proofeditor.ai/api/agent/abc123/v3/document",
    "edit": { "method": "POST", "href": "/api/agent/abc123/v3/edit" },
    "delete": { "method": "DELETE", "href": "/api/documents/abc123" }
  }
}

Use tokenUrl as the shareable link. Extract slug, accessToken, and ownerSecret immediately — ownerSecret is required for cleanup while the doc is still unclaimed.

Raw lines 20 to 48
49### Read a Shared Document
51If you already have a shared Proof URL, fetch with content negotiation or v3:
53```bash
54curl -sS -H "Accept: application/json" "https://www.proofeditor.ai/d/{slug}?token=<token>"
55curl -sS -H "Accept: text/markdown" "https://www.proofeditor.ai/d/{slug}?token=<token>"
57curl -sS "https://www.proofeditor.ai/api/agent/{slug}/v3/document" \
58 -H "Authorization: Bearer <token>" \
59 -H "X-Agent-Id: ai:compound-engineering"
60# -> { ok, revision, title, markdown, comments[], suggestions[], mutationReady? }
61```
63ACTIVE docs can be read tokenlessly via `v3/document`. Mutations, presence, and events need a tokenized credential. Tokenless `GET /d/<slug>` JSON reports `role: null` and no mutation links — that is truthful capability reporting, not a browser lock.
65`comments[]` and `suggestions[]` on the v3 read are the source of review state. Use a comment's `id` for `reply` / `resolve` / `unresolve`. Use a suggestion's `id` for `accept` / `reject`. v3 supports resolving and unresolving comments; it does **not** support deleting comments. A comment with `orphaned: true` and an empty `quote` has lost its anchor — its thread is still readable and replyable, but do not treat its old target text as a live anchor.
67When `mutationReady` is `false`, `revision` may be `null` — omit `baseRevision` and re-read shortly.

Read a Shared Document

If you already have a shared Proof URL, fetch with content negotiation or v3:

curl -sS -H "Accept: application/json" "https://www.proofeditor.ai/d/{slug}?token=<token>"
curl -sS -H "Accept: text/markdown" "https://www.proofeditor.ai/d/{slug}?token=<token>"

curl -sS "https://www.proofeditor.ai/api/agent/{slug}/v3/document" \
  -H "Authorization: Bearer <token>" \
  -H "X-Agent-Id: ai:compound-engineering"
# -> { ok, revision, title, markdown, comments[], suggestions[], mutationReady? }

ACTIVE docs can be read tokenlessly via v3/document. Mutations, presence, and events need a tokenized credential. Tokenless GET /d/<slug> JSON reports role: null and no mutation links — that is truthful capability reporting, not a browser lock.

comments[] and suggestions[] on the v3 read are the source of review state. Use a comment's id for reply / resolve / unresolve. Use a suggestion's id for accept / reject. v3 supports resolving and unresolving comments; it does not support deleting comments. A comment with orphaned: true and an empty quote has lost its anchor — its thread is still readable and replyable, but do not treat its old target text as a live anchor.

When mutationReady is false, revision may be null — omit baseRevision and re-read shortly.

Raw lines 49 to 68
69### Edit a Shared Document
71Send `{ by, baseRevision?, operations: [...] }` to `POST /api/agent/{slug}/v3/edit`. Targets are **visible text** in `markdown` (not raw markdown syntax, not block refs). There is no base token. `baseRevision` (integer from the last read) is an optional conflict guard — omit it to apply at head. `Idempotency-Key` is optional; use one for important writes and retries.
73```bash
74curl -sS -X POST "https://www.proofeditor.ai/api/agent/{slug}/v3/edit" \
75 -H "Content-Type: application/json" \
76 -H "Authorization: Bearer <token>" \
77 -H "X-Agent-Id: ai:compound-engineering" \
78 -H "Idempotency-Key: $(uuidgen)" \
79 -d '{
80 "by":"ai:compound-engineering",
81 "operations":[
82 {"op":"replace","find":"old visible text","with":"new text"},
83 {"op":"comment","on":"text to anchor on","body":"Is this still accurate?"}
84 ]
85 }'
86```
88**Content operations:**
90| op | body |
91|---|---|
92| `replace` | `find`, `with` (optional `occurrence` / `before` / `after`) |
93| `insert` | `after` or `before` + `markdown` (anchor: quote, `heading:Title`, `section:Title`, `"start"`, or `"end"`) |
94| `delete` | `find` |
95| `set_document` | `markdown` (whole-doc replace as a minimal diff; safe with live collaborators) |
97**Review operations:**
99| op | body |
100|---|---|
101| `comment` | `on`, `body` (optional `occurrence`) |
102| `reply` | `comment` (id), `body`, optional `resolve: true` |
103| `resolve` / `unresolve` | `comment` (id) |
104| `suggest` | `kind: "insert"\|"delete"\|"replace"`, `find`, `with?` (`with` required for insert/replace) |
105| `accept` / `reject` | `suggestion` (id) |
106| `modify_suggestion` | `suggestion` (id), `with` — replace the proposed text of a pending plain insert/replace suggestion |
108`suggest` also accepts typed structural forms (`command: "table.*"`, `"format.*"`, `"node.update"`, and atom `target: {node: "image"|"hr"|...}`); see `https://www.proofeditor.ai/agent-docs` before using them. A request holds at most 100 operations; `set_document` accepts at most 2 MiB of markdown.

Edit a Shared Document

Send { by, baseRevision?, operations: [...] } to POST /api/agent/{slug}/v3/edit. Targets are visible text in markdown (not raw markdown syntax, not block refs). There is no base token. baseRevision (integer from the last read) is an optional conflict guard — omit it to apply at head. Idempotency-Key is optional; use one for important writes and retries.

curl -sS -X POST "https://www.proofeditor.ai/api/agent/{slug}/v3/edit" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -H "X-Agent-Id: ai:compound-engineering" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "by":"ai:compound-engineering",
    "operations":[
      {"op":"replace","find":"old visible text","with":"new text"},
      {"op":"comment","on":"text to anchor on","body":"Is this still accurate?"}
    ]
  }'

Content operations:

opbody
replacefind, with (optional occurrence / before / after)
insertafter or before + markdown (anchor: quote, heading:Title, section:Title, "start", or "end")
deletefind
set_documentmarkdown (whole-doc replace as a minimal diff; safe with live collaborators)

Review operations:

opbody
commenton, body (optional occurrence)
replycomment (id), body, optional resolve: true
resolve / unresolvecomment (id)
suggest`kind: "insert"\"delete"\"replace", find, with? (with` required for insert/replace)
accept / rejectsuggestion (id)
modify_suggestionsuggestion (id), with — replace the proposed text of a pending plain insert/replace suggestion

suggest also accepts typed structural forms (command: "table.*", "format.*", "node.update", and atom target: {node: "image"|"hr"|...}); see https://www.proofeditor.ai/agent-docs before using them. A request holds at most 100 operations; set_document accepts at most 2 MiB of markdown.

Raw lines 69 to 109
110### Edit Strategy
112Prefer the narrowest op:
1141. Literal or scoped prose change → `replace` / `insert` / `delete`
1152. Visible track-changes desired → `suggest` (then `accept`/`reject` as needed)
1163. Whole-doc replacement → `set_document` only when the user asks for full replacement or the change cannot be expressed narrowly
118If a `find`/anchor matches more than once, the server rejects with `TARGET_AMBIGUOUS` and `error.candidates` — nothing is changed. Disambiguate with `occurrence` (`"first"`, `"last"`, or 0-based index) or `before`/`after`. Never assume silent first-match.
120Content ops in one request apply atomically; review ops then apply in order. If a review op fails after content committed, the response is `ok: false` with `partial: true` — re-read and retry only the failed op (same `Idempotency-Key` safely replays).
122**Errors** use `{ ok:false, error:{ code, message, retryable, opIndex?, target?, candidates?, current? } }`. Codes: `AUTH`, `NOT_FOUND`, `INVALID_REQUEST`, `TARGET_NOT_FOUND`, `TARGET_AMBIGUOUS`, `CONFLICT`, `TOO_LARGE`, `BUSY`, `PENDING`, `INTERNAL`.
124- `retryable: false` — fix the request; do not blind-retry
125- `retryable: true` with `error.current` — re-resolve targets against `current` and retry once
126- `TARGET_AMBIGUOUS` — add `occurrence` / `before` / `after` from `candidates`
127- `BUSY` — brief backoff and retry
128- Retryable `CONFLICT` on a structural suggestion — a connected editor is on an older suggestion reader; retry after it reconnects. Non-retryable `CONFLICT` — the op crosses frontmatter, raw HTML, or unknown content; use a whole-block op or leave it
129- `accept` that keeps failing with `SUGGESTION_OWNERSHIP_MISSING` after a fresh read — the suggestion is wedged; `reject` it (always allowed) and recreate instead of retrying `accept`
130- Settled `200` with `ok:true` — inspect returned `revision` / document; chain without an extra read when the body is complete
131- `202` / `PENDING` — write may have committed; re-read `v3/document` before chaining or reporting success
133After every successful edit: confirm `ok:true`, confirm the intended text/comment/suggestion, then report the Proof link with a short summary.

Edit Strategy

Prefer the narrowest op:

  1. Literal or scoped prose change → replace / insert / delete
  2. Visible track-changes desired → suggest (then accept/reject as needed)
  3. Whole-doc replacement → set_document only when the user asks for full replacement or the change cannot be expressed narrowly

If a find/anchor matches more than once, the server rejects with TARGET_AMBIGUOUS and error.candidates — nothing is changed. Disambiguate with occurrence ("first", "last", or 0-based index) or before/after. Never assume silent first-match.

Content ops in one request apply atomically; review ops then apply in order. If a review op fails after content committed, the response is ok: false with partial: true — re-read and retry only the failed op (same Idempotency-Key safely replays).

Errors use { ok:false, error:{ code, message, retryable, opIndex?, target?, candidates?, current? } }. Codes: AUTH, NOT_FOUND, INVALID_REQUEST, TARGET_NOT_FOUND, TARGET_AMBIGUOUS, CONFLICT, TOO_LARGE, BUSY, PENDING, INTERNAL.

  • retryable: false — fix the request; do not blind-retry
  • retryable: true with error.current — re-resolve targets against current and retry once
  • TARGET_AMBIGUOUS — add occurrence / before / after from candidates
  • BUSY — brief backoff and retry
  • Retryable CONFLICT on a structural suggestion — a connected editor is on an older suggestion reader; retry after it reconnects. Non-retryable CONFLICT — the op crosses frontmatter, raw HTML, or unknown content; use a whole-block op or leave it
  • accept that keeps failing with SUGGESTION_OWNERSHIP_MISSING after a fresh read — the suggestion is wedged; reject it (always allowed) and recreate instead of retrying accept
  • Settled 200 with ok:true — inspect returned revision / document; chain without an extra read when the body is complete
  • 202 / PENDING — write may have committed; re-read v3/document before chaining or reporting success

After every successful edit: confirm ok:true, confirm the intended text/comment/suggestion, then report the Proof link with a short summary.

Raw lines 110 to 134
135### Presence
137```bash
138curl -sS -X POST "https://www.proofeditor.ai/api/agent/{slug}/presence" \
139 -H "Content-Type: application/json" \
140 -H "Authorization: Bearer <token>" \
141 -H "X-Agent-Id: ai:compound-engineering" \
142 -d '{"name":"Compound Engineering","status":"reading","summary":"Joining the doc"}'
143```
145Common statuses: `reading`, `thinking`, `acting`, `waiting`, `completed`, `error`.

Presence

curl -sS -X POST "https://www.proofeditor.ai/api/agent/{slug}/presence" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -H "X-Agent-Id: ai:compound-engineering" \
  -d '{"name":"Compound Engineering","status":"reading","summary":"Joining the doc"}'

Common statuses: reading, thinking, acting, waiting, completed, error.

Raw lines 135 to 146
147### Title
149```bash
150curl -sS -X PUT "https://www.proofeditor.ai/api/documents/{slug}/title" \
151 -H "Content-Type: application/json" \
152 -H "Authorization: Bearer <token>" \
153 -d '{"title":"Updated document title"}'
154```

Title

curl -sS -X PUT "https://www.proofeditor.ai/api/documents/{slug}/title" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"title":"Updated document title"}'
Raw lines 147 to 155
156### Delete
158Only owner credentials can delete:
160```bash
161curl -sS -X DELETE "https://www.proofeditor.ai/api/documents/{slug}" \
162 -H "Authorization: Bearer <ownerSecret>"
163```
165Viewer, commenter, and editor `accessToken` values cannot delete. Success returns `shareState: "DELETED"`; later reads return deleted-document responses (`410` on many routes).
167**Lifecycle:** Do **not** auto-delete after every publish handoff — review docs must linger. Persist `ownerSecret` for the session. Delete when the user asks to remove/clean up, or when finishing an explicitly ephemeral scratch doc the user is done with.

Delete

Only owner credentials can delete:

curl -sS -X DELETE "https://www.proofeditor.ai/api/documents/{slug}" \
  -H "Authorization: Bearer <ownerSecret>"

Viewer, commenter, and editor accessToken values cannot delete. Success returns shareState: "DELETED"; later reads return deleted-document responses (410 on many routes).

Lifecycle: Do not auto-delete after every publish handoff — review docs must linger. Persist ownerSecret for the session. Delete when the user asks to remove/clean up, or when finishing an explicitly ephemeral scratch doc the user is done with.

Raw lines 156 to 168
169### Marks and privacy
171Emptying the markdown (including `set_document` to blank/minimal content) does **not** scrub comment marks. Quote and commentary fields can remain readable via `v3/document` to anyone with the share credential. Without owner delete authority, content wipe is not a privacy cleanup — delete the document with `ownerSecret` (while unclaimed) or ask the owner after claim.

Marks and privacy

Emptying the markdown (including set_document to blank/minimal content) does not scrub comment marks. Quote and commentary fields can remain readable via v3/document to anyone with the share credential. Without owner delete authority, content wipe is not a privacy cleanup — delete the document with ownerSecret (while unclaimed) or ask the owner after claim.

Raw lines 169 to 172
173### When the loop breaks
175If a mutation keeps failing after a fresh read and one safe retry, call `POST https://www.proofeditor.ai/api/bridge/report_bug` with the failing request ID, slug, and raw response. The server enriches and files an issue. Ask before including the user's name/email.

When the loop breaks

If a mutation keeps failing after a fresh read and one safe retry, call POST https://www.proofeditor.ai/api/bridge/report_bug with the failing request ID, slug, and raw response. The server enriches and files an issue. Ask before including the user's name/email.

Raw lines 173 to 176