Hashboard treats documents as first-class resources, not footnotes to cards. The sameDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/cryguy/hashboard/llms.txt
Use this file to discover all available pages before exploring further.
docs table backs both the description attached to every card and freestanding markdown documents — specs, notes, runbooks — that exist on their own. Both kinds share the same editing API, revision history, and markdown rendition. Understanding how the two kinds diverge (and where they stay identical) makes the rest of the data model click.
One Table, Two Kinds
Thedocs table has a kind column with two possible values:
| Kind | Lives at | Visibility | Lifecycle |
|---|---|---|---|
card | Owned by a card via cards.doc_id | Inherited from the card (NULL in DB) | Created and deleted with the card in one transaction |
standalone | /docs/{id} as a first-class resource | Its own visibility column | Independent — outlives any board |
/docs/{id} — you reach a card’s description through the card itself (GET /api/v1/cards/{id} returns doc in the composite payload, or edit it via the card’s docId).
Editing Documents
All doc edits go throughPUT /api/v1/docs/{id} with a JSON body:
title is optional — omitting it leaves the title unchanged. baseVersion is required and is the concurrency anchor described below.
Optimistic Concurrency
Doc saves use optimistic concurrency control rather than locking. The service issues a version-gated update:version since you read the document — the endpoint returns 409 Conflict with the current version in the body:
currentVersion (via GET /api/v1/docs/{id} or the .md rendition), merging its changes, and retrying with baseVersion: 5. This is deliberate: there is no CRDT or operational transform. A versioned 409 makes staleness an explicit, recoverable outcome — a live merge would silently interleave an agent’s stale-context write with no conflict signal.
Revision History
Every save that changes the document content appends a row todoc_revisions — a snapshot of the content at that version, attributed to the author. Revision history is append-only and survives doc updates.
docs row is always the current version.
Markdown Rendition and YAML Frontmatter
Every doc URL — and every card URL — serves a markdown rendition when requested withAccept: text/markdown or a .md suffix (see Content Negotiation). The rendition opens with YAML frontmatter:
The
version field is load-bearing. When an agent reads a document through the markdown rendition, it must round-trip the version value back as baseVersion in its PUT /api/v1/docs/{id} request. Without it the 409 conflict check cannot fire, and the agent may overwrite concurrent edits silently. Every tool that fetches a doc rendition should extract and preserve version.Every link in the rendition carries the .md suffix — /cards/{id}.md, /docs/{id}.md — so an agent that follows a link stays in markdown without needing to set an Accept header.Backlinks
Hashboard tracks which docs and cards reference a given document.GET /api/v1/docs/{id}/backlinks returns the reverse index:
Card–Doc Links
Cards can reference standalone documents through thecard_doc_links join table. This is a many-to-many relationship distinct from the one-to-one ownership of a card’s description. A card might link to a spec doc, a runbook, or meeting notes without those docs belonging exclusively to the card.
kind: card) are not valid link targets in card_doc_links — service-enforced. A description belongs to exactly one card; surfacing it as a shared link would create two lists (card attachments vs. doc attachments) that nothing keeps in agreement.
Standalone Doc Lifecycle
Standalone docs are created withPOST /api/v1/docs and are listed at GET /api/v1/docs. They carry their own visibility and appear in the filing index when assigned a board_id (a filing facet — not a cascade edge; see Visibility). Deleting a standalone doc removes the row and all its revisions; any card_doc_links pointing to it are cascade-deleted, and the activity log retains the docId in its JSON data so history is not rewritten.
Doc API surface
Doc API surface
| Method | Path | Description |
|---|---|---|
GET | /api/v1/docs | List standalone docs visible to you |
POST | /api/v1/docs | Create a standalone doc |
GET | /api/v1/docs/{id} | Get doc (composite: { doc, linkedCards, attachments }) |
PUT | /api/v1/docs/{id} | Save content — requires baseVersion |
GET | /api/v1/docs/{id}/revisions | Revision history, newest-first |
GET | /api/v1/docs/{id}/backlinks | Docs and cards that link here |
DELETE | /api/v1/docs/{id} | Delete a standalone doc |