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

# Wiki

> Wiki pages are Markdown or CSV documents with revision history. Learnings are sourced proposals a person accepts or rejects.

A wiki page is a Markdown or CSV document in your workspace. Its id is `wik_` plus 16 letters and digits, and each revision has a `wrev_…` id. A learning, `lrn_…`, is a proposal for the wiki that waits for a person's decision. For why they work this way, see [Wiki and learnings](/concepts/wiki-and-learnings).

## States

### Wiki page

A page has no status field. Its state comes from `archivedAt` and from whether it was deleted.

| State | Meaning | Ends here |
| - | - | - |
| Live | `archivedAt` is null. Search returns it. | No |
| Archived | `archivedAt` is set. It keeps its slug and is left out of search. | No |
| Deleted | Gone from the API. Its slug is free and its search chunks are purged. | Yes |

| From | To | Trigger |
| - | - | - |
| (none) | Live | `wiki create`, or `wiki ingest` for a new file. |
| Live | Archived | `wiki archive`, `wiki ingest` when the file left the directory, or another page superseding it. |
| Archived | Live | `wiki unarchive`. |
| Live or Archived | Deleted | `wiki delete`. |

Agents and people can create and update pages. Archive, unarchive, slug changes, delete, restore, supersede and ingest need a person. A page with `currentRevisionId` null has never been published.

### Learning

| State | Meaning | Ends here |
| - | - | - |
| `proposed` | Filed and waiting on its `learning_review` approval. | No |
| `accepted` | A person accepted it. Pinework creates a task to write it into the wiki. | Yes |
| `rejected` | A person rejected it. The reason is saved in `rejectedReason`. | Yes |

| From | To | Trigger |
| - | - | - |
| (none) | `proposed` | `learning add` or `POST /api/v1/learnings`. This opens an approval. |
| `proposed` | `accepted` | `learning accept`, which approves the learning's approval. |
| `proposed` | `rejected` | `learning reject`, which rejects the learning's approval. |

Only a `proposed` learning can be edited.

## Fields

### Wiki page

<ResponseField name="id" type="string" required>Page id, `wik_…`.</ResponseField>
<ResponseField name="object" type="string" required>Always `wiki_page`.</ResponseField>
<ResponseField name="slug" type="string" required>Unique among live pages. Made from the title: lowercase, spaces become `-`, other characters dropped.</ResponseField>
<ResponseField name="title" type="string" required>Title of the current revision.</ResponseField>
<ResponseField name="kind" type="string" required>`markdown` or `csv`.</ResponseField>
<ResponseField name="archivedAt" type="string">Archive time. Null when live.</ResponseField>
<ResponseField name="sourceRef" type="string">Path of the ingested file. Null for a page made in Pinework.</ResponseField>
<ResponseField name="currentRevisionId" type="string">Current revision, `wrev_…`. Null when never published.</ResponseField>
<ResponseField name="tokenCount" type="integer">Approximate tokens the body costs in an agent's context. Null when not counted yet.</ResponseField>
<ResponseField name="body" type="string">Current body, raw. Present on a single get. Null when never published.</ResponseField>
<ResponseField name="supersedes" type="object[]">Live pages this page replaces, each with `id`, `slug` and `title`. Single get only.</ResponseField>
<ResponseField name="supersededBy" type="object[]">Live pages that replace this one. Single get only.</ResponseField>
<ResponseField name="createdAt" type="string" required>Creation time.</ResponseField>
<ResponseField name="updatedAt" type="string" required>Last change time.</ResponseField>

A revision (`wiki_revision`) has `id`, `pageId`, `title`, `baseRevisionId`, `sourceRef`, `author`, `taskId`, `runId`, `tokenCount` and `createdAt`. A single get adds `body`.

### Learning

<ResponseField name="id" type="string" required>Learning id, `lrn_…`.</ResponseField>
<ResponseField name="object" type="string" required>Always `learning`.</ResponseField>
<ResponseField name="topic" type="string" required>The one subject of the block.</ResponseField>
<ResponseField name="status" type="string" required>`proposed`, `accepted` or `rejected`.</ResponseField>

<ResponseField name="bullets" type="object[]" required>
  The block, in order.

  <Expandable title="bullet">
    <ResponseField name="ord" type="integer" required>Position, from 0.</ResponseField>
    <ResponseField name="text" type="string" required>One imperative instruction.</ResponseField>
    <ResponseField name="sources" type="object[]" required>Links backing the bullet, each with `url` and `ord`.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="entities" type="object[]" required>Tags, each with `type` and a lowercase `name`.</ResponseField>
<ResponseField name="conversationId" type="string">Conversation it was learned in, `cnv_…`. Null when none.</ResponseField>
<ResponseField name="createdByAgentId" type="string">Filing agent, `agt_…`. Null when a person filed it.</ResponseField>
<ResponseField name="createdByUserId" type="string">Filing person. Currently always null.</ResponseField>
<ResponseField name="runId" type="string">Run that filed it, `run_…`. Null when filed outside a run.</ResponseField>
<ResponseField name="taskId" type="string">Task that run was on, `tsk_…`. Null when none.</ResponseField>
<ResponseField name="approvalId" type="string">The `learning_review` approval, `apr_…`. Null when none.</ResponseField>
<ResponseField name="rejectedReason" type="string">Your note, or `rejected by reviewer`. Null unless rejected.</ResponseField>
<ResponseField name="createdAt" type="string" required>Filing time.</ResponseField>
<ResponseField name="updatedAt" type="string" required>Last change time.</ResponseField>

## CLI

| Command | Does |
| - | - |
| `wiki list` | Lists pages by last update, archived ones included. `--archived` lists only archived pages. |
| `wiki get` | Shows pages with bodies. `--revision` reads an old revision. `--out` writes the body to a file. |
| `wiki history` | Lists a page's revisions, newest first. |
| `wiki create` | Creates and publishes a page. `--kind` defaults to `markdown`. |
| `wiki update` | Publishes a new revision. |
| `wiki restore` | Republishes an old revision. |
| `wiki archive` / `unarchive` | Hides a page from search, or shows it again. |
| `wiki delete` | Deletes a page. |
| `wiki ingest` | Loads Markdown and CSV files from local directories. |
| `wiki embed-status` | Shows search embedding coverage. |
| `learning add` | Files a learning: `--topic`, then each `--bullet` with its `--source` links. |
| `learning list` / `learning get` | Lists or reads learnings. |
| `learning accept` / `reject` | Decides one id, `--ids`, or `--all-proposed-before` a date. An agent run is refused. |

```bash theme={null}
pinework wiki get release-checklist --out page.md
pinework wiki update release-checklist --body-file page.md
pinework learning add --topic "Database migrations" --bullet "Generate migrations with drizzle-kit, never by hand." --source pinework://task/PIN-42
pinework learning reject lrn_AbCdEfGh12345678 --note "Wrong, see PIN-42"
```

## API

A page `{id}` takes a `wik_` id or an exact slug.

| Method | Path | Does |
| - | - | - |
| `GET` | `/api/v1/wiki/pages` | Lists pages. Filters: `archived`, `neverPublished`, `q`, `ids`. |
| `POST` | `/api/v1/wiki/pages` | Creates and publishes a page. |
| `GET` | `/api/v1/wiki/pages/{id}` | Gets a page with its body. |
| `PATCH` | `/api/v1/wiki/pages/{id}` | Sets `archived` or `slug`. Person only. |
| `DELETE` | `/api/v1/wiki/pages/{id}` | Deletes a page. Person only. |
| `GET` | `/api/v1/wiki/pages/{id}/revisions` | Lists revisions, newest first. |
| `POST` | `/api/v1/wiki/pages/{id}/revisions` | Publishes a revision. Send `baseRevisionId` to catch concurrent edits. |
| `GET` | `/api/v1/wiki/pages/{id}/revisions/{revisionId}` | Gets one revision with its body. |
| `POST` | `/api/v1/wiki/pages/{id}/revisions/{revisionId}/restore` | Republishes an old revision. Person only. |
| `POST` | `/api/v1/wiki/pages/{id}/relations` | Supersedes `toPageId` and archives it, unless ingest owns it. Person only. |
| `DELETE` | `/api/v1/wiki/pages/{id}/relations` | Removes a supersede. Person only. |
| `GET` | `/api/v1/wiki/pages/{id}/backlinks` | Lists live pages that link to this page. |
| `GET` | `/api/v1/wiki/pages/{id}/sources` | Lists the links in the body. |
| `GET` | `/api/v1/wiki/embedding-status` | Returns embedding coverage counts. |
| `POST` | `/api/v1/wiki/ingest/plan` | Returns the paths whose bodies the server lacks. Person only. |
| `POST` | `/api/v1/wiki/ingest` | Ingests pages and archives missing ones. Person only. |
| `POST` | `/api/v1/learnings` | Files a learning. |
| `GET` | `/api/v1/learnings` | Lists learnings. Filters: `status`, `entityType`, `entityName`, `conversationId`, `approvalId`. |
| `GET` | `/api/v1/learnings/{id}` | Gets one learning. |
| `PATCH` | `/api/v1/learnings/{id}` | Replaces `topic`, `bullets` or `entities` on a proposed learning. Person only. |
| `POST` | `/api/v1/approvals/{approvalId}/approve` | Accepts the learning gated by that approval. |
| `POST` | `/api/v1/approvals/{approvalId}/reject` | Rejects it. `reason` becomes `rejectedReason`. |

## Errors

| Code | HTTP | When | What to do |
| - | - | - | - |
| `wiki_page_not_found` | 404 | No page has that id or slug. | Check with `wiki list`. |
| `wiki_revision_not_found` | 404 | The revision is not on this page. | Check with `wiki history`. |
| `wiki_stale_base_revision` | 409 | The page changed since your base revision. | Read it again and reapply. |
| `wiki_body_truncated` | 422 | The body has a "tokens truncated" marker. | Read with `wiki get --out`. |
| `wiki_body_shrunk` | 422 | The body is under 60% of the current length. | Pass `--allow-shrink` if meant. |
| `wiki_citation_style` | 422 | A Markdown body has numbered citations or a Sources section. | Cite with inline links. |
| `wiki_page_slug_conflict` | 409 | Another live page has that slug. | Change the title or slug. |
| `wiki_publish_failed` | 409 | Publishing the new page failed. | Retry. |
| `wiki_source_page_immutable` | 409 | You changed an ingested page's slug or archive state. | Edit the source file and ingest again. |
| `wiki_relation_self` | 400 | A page supersedes itself. | Pick another page. |
| `wiki_relation_exists` | 409 | The supersede already exists. | Nothing to do. |
| `wiki_relation_workspace_mismatch` | 400 | The target page is in another workspace. | Pick a local page. |
| `wiki_ingest_request_too_large` | 400 | The request is over 8 MiB. | Send fewer pages. |
| `wiki_ingest_invalid_root` | 400 | An ingest root is not valid. | Fix the directory path. |
| `learning_not_found` | 404 | No such learning in the workspace. | Check the `lrn_` id. |
| `learning_not_editable` | 409 | You edited a learning that is not `proposed`. | File a new learning. |
| `run_not_found` | 404 | The filing run was not found. | File from a valid run. |
| `http_exception` | 403 | An agent calls a person-only route. | A person must do it. |

For shared codes, see [API errors](/reference/api#errors).

## Limits

* A page body holds 262,144 bytes (256 KiB) of UTF-8.
* An update under 60% of the current body length is refused without `allowShrink`.
* An ingest request holds 8 MiB (8,388,608 bytes).
* A list returns 25 items by default and 100 at most. `q` holds 1 to 100 characters.
* A learning topic holds 200 bytes.
* A learning has 1 to 5 bullets. A bullet holds 25 words and 1,024 bytes.
* A bullet has 1 to 10 sources. A source holds 2,048 bytes and is a `pinework://<object>/<id>` link or an `https://` URL.
* A learning has up to 6 tags. A tag name holds 128 bytes.

<CardGroup cols={2}>
  <Card title="Wiki and learnings" href="/concepts/wiki-and-learnings">
    Why learnings wait for a person.
  </Card>

  <Card title="Review learnings" href="/guides/review-learnings">
    Accept, edit or reject what agents propose.
  </Card>

  <Card title="Approval" href="/reference/approval">
    The gate that decides each learning.
  </Card>

  <Card title="File" href="/reference/file">
    Bytes you attach, rather than pages you edit.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.