Skip to main content

Documentation 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.

Hashboard has one document table backing two kinds of docs: standalone documents (specs, notes, reference material — anything that is not a task) and card description documents (the markdown body of a card). Both are edited through the same PUT /api/v1/docs/{id} endpoint. The key that ties a card to its description is card.docId, returned by any card endpoint. Saves use optimistic concurrency: every document carries a version integer. You must supply the version you read as baseVersion when saving. If another writer committed a change while you were editing, the server responds 409 Conflict with the current version so you can re-fetch, merge, and retry. This is a deliberate design choice — it makes concurrent edits by agents explicit and recoverable rather than silently lost. All write endpoints require a bearer token (Authorization: Bearer hb_…) or session cookie.
Card description documents are addressed by card.docId. Saving a card’s description goes through PUT /api/v1/docs/{card.docId} — the same endpoint as standalone docs. Card docs cannot be deleted or have their visibility changed directly; those operations go through the card itself.

GET /api/v1/docs

List standalone documents visible to the authenticated principal. Optionally filter to documents filed under a specific board. GET /api/v1/docs

Query Parameters

boardId
string
Return only documents associated with this board ID.

Response

Returns an array of Doc objects. Content is included in the list response; use the single-document endpoint if you want to avoid fetching content for every item.
id
string
Document UUID.
kind
string
"standalone" for standalone docs returned by this endpoint.
boardId
string | null
Board this document is filed under, or null.
title
string | null
Document title.
content
string
Full markdown body.
version
number
Integer version counter. Pass as baseVersion to PUT when saving.
visibility
string | null
private, link-read, link-write, or public for standalone docs. Always null for card docs (they inherit the card’s visibility).
createdBy
string
Creator principal ID.
updatedBy
string
Last editor principal ID.
createdAt
string
ISO 8601 timestamp.
updatedAt
string
ISO 8601 timestamp of the last save.
curl -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/docs

POST /api/v1/docs

Create a standalone markdown document. Returns 201 Created with the new document at version 0. POST /api/v1/docs

Request Body

title
string
required
Document title.
boardId
string
Optionally file this document under a board. Does not affect visibility — boardId is a filing facet, not a cascade edge.
visibility
string
One of private (default), link-read, link-write, or public.
content
string
Initial markdown content. Defaults to an empty string.

Response

Returns the created Doc object at version: 0.
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Architecture Overview",
    "visibility": "link-read",
    "content": "# Architecture\n\n…"
  }' \
  https://your-instance.example/api/v1/docs

GET /api/v1/docs/{id}

Fetch a single document by ID. Works for both standalone documents and card description documents. Returns 404 for documents that do not exist or are not visible to the caller (existence is never confirmed). GET /api/v1/docs/{id}

Path Parameters

id
string
required
Document ID.

Response

Returns a Doc object (same fields as the list response above).
curl -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/docs/018f4d2c-…
Append .md to the document URL (/docs/{id}.md) or send Accept: text/markdown to get the document as markdown with YAML frontmatter. The frontmatter includes version — use it as baseVersion in your next PUT.

PUT /api/v1/docs/{id}

Save a document with optimistic concurrency control. Works for both standalone documents and card descriptions (addressed via card.docId). Same-content saves (identical content and same title) are no-ops — the version is not incremented and no revision entry is written. PUT /api/v1/docs/{id}

Path Parameters

id
string
required
Document ID (for card descriptions, use card.docId).

Request Body

baseVersion
number
required
The version number you read when you last fetched this document. The save is rejected with 409 if the current version in the database does not match this value.
content
string
required
The full new markdown content of the document.
title
string
New document title. Omit to leave the title unchanged.

Response

200 OK — Returns the updated Doc object with an incremented version. 409 Conflict — Someone else saved first. The response body is:
{
  "error": "Someone saved first — re-read, merge, retry with the new baseVersion.",
  "currentVersion": 7
}
Read currentVersion from the body, fetch the latest content, merge your changes, then retry with baseVersion set to the value from the conflict response.

Optimistic concurrency workflow

1

Fetch the document

GET /api/v1/docs/{id}
Record doc.version and doc.content.
2

Edit locally

Make your changes to the content. Do not mutate version.
3

Save with baseVersion

PUT /api/v1/docs/{id}
{ "baseVersion": <version you read>, "content": "<edited content>" }
4

Handle a 409 conflict

If you receive 409, the response body contains currentVersion. Re-fetch the document at that version, merge your edits with the updated content, and retry the PUT with the new baseVersion.
# 1. Fetch
DOC=$(curl -s -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/docs/018f4d2c-…)

VERSION=$(echo "$DOC" | jq .version)

# 2. Save with baseVersion
curl -X PUT \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/json" \
  -d "{\"baseVersion\": $VERSION, \"content\": \"# Updated content\"}" \
  https://your-instance.example/api/v1/docs/018f4d2c-…

PATCH /api/v1/docs/{id}

Change a standalone document’s visibility. Creator-only. Card description documents have no independent visibility — they inherit the card’s — so PATCH on a card doc returns 400 Bad Request. PATCH /api/v1/docs/{id}

Path Parameters

id
string
required
Standalone document ID.

Request Body

visibility
string
required
New visibility mode: private, link-read, link-write, or public.

Response

Returns the updated Doc object.
curl -X PATCH \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/json" \
  -d '{"visibility": "public"}' \
  https://your-instance.example/api/v1/docs/018f4d2c-…

DELETE /api/v1/docs/{id}

Delete a standalone document. Creator-only. Card description documents cannot be deleted directly — they are deleted together with their card. Returns 404 for missing or invisible documents. DELETE /api/v1/docs/{id}

Path Parameters

id
string
required
Standalone document ID.

Response

Returns { "ok": true }.
curl -X DELETE \
  -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/docs/018f4d2c-…

List cards that have linked this document. Results are filtered to cards the caller can see. Useful for understanding a document’s reach before modifying or deleting it. GET /api/v1/docs/{id}/backlinks

Path Parameters

id
string
required
Document ID.

Response

Returns an array of CardLink objects (card metadata only — no description content).
id
string
Card ID.
title
string
Card title.
visibility
string
Card visibility mode.
boardId
string | null
Board the card belongs to, or null for a loose card.
curl -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/docs/018f4d2c-…/backlinks

GET /api/v1/docs/{id}/revisions

List the content snapshots of a document, newest first. Each save that changes content creates a revision entry. Same-content saves do not create a revision. GET /api/v1/docs/{id}/revisions

Path Parameters

id
string
required
Document ID.

Response

Returns an array of DocRevision objects.
id
string
Revision UUID.
docId
string
Parent document ID.
version
number
Version number at the time this snapshot was written.
content
string
Full markdown content at this version.
authorId
string
Principal who authored this revision.
createdAt
string
ISO 8601 timestamp when this revision was written.
curl -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/docs/018f4d2c-…/revisions

POST /api/v1/docs/{id}/attachments

Upload a file and attach it to a standalone document. Uses the same raw binary upload convention as card attachments. Returns 201 Created. POST /api/v1/docs/{id}/attachments

Path Parameters

id
string
required
Standalone document ID. Card description docs are not valid subjects — attach files to the card instead.

Query Parameters

filename
string
required
Original filename. Its extension determines the stored content type.

Request Body

Raw binary file contents. Set Content-Type: application/octet-stream.
Do not use multipart/form-data. Send raw bytes with a binary content type. The same restriction applies as for card attachments — curl -F results in a 403 against a production build.
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @diagram.png \
  "https://your-instance.example/api/v1/docs/018f4d2c-…/attachments?filename=diagram.png"
Attaching to a card description doc (kind "card") returns 400. A card description is the card’s body — files in it belong to the card. Use POST /api/v1/cards/{id}/attachments instead.

Response

Returns the created Attachment object. Embed files in the document content as ![alt](/attachments/{id}). Bytes are served at GET /attachments/{id}.

POST /api/v1/docs/{id}/comments

Add a comment to a document. Returns 201 Created. POST /api/v1/docs/{id}/comments

Path Parameters

id
string
required
Document ID.

Request Body

body
string
required
Comment text (markdown supported).

Response

Returns the created Comment object.
id
string
Comment UUID.
cardId
string | null
Always null for document comments.
docId
string | null
Parent document ID.
authorId
string
Author principal ID.
body
string
Comment text.
createdAt
string
ISO 8601 timestamp.
updatedAt
string
ISO 8601 timestamp.
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/json" \
  -d '{"body": "Section 3 needs updating after the API change."}' \
  https://your-instance.example/api/v1/docs/018f4d2c-…/comments

GET /api/v1/docs/{id}/activity

Fetch the activity feed for a document, newest events first. GET /api/v1/docs/{id}/activity

Path Parameters

id
string
required
Document ID.

Query Parameters

limit
string
Maximum number of events to return. Defaults to 50.

Response

Returns an array of ActivityEvent objects (id, boardId, cardId, docId, actorId, type, data, createdAt).
curl -H "Authorization: Bearer hb_…" \
  "https://your-instance.example/api/v1/docs/018f4d2c-…/activity?limit=10"

Document visibility

Standalone documents carry their own visibility field, changed via PATCH /api/v1/docs/{id}. Card description documents have visibility: null — they inherit the card’s mode. Visibility grants cascade downward from containers: a board’s visibility extends to its cards and their linked documents, so a document linked to a public card may be readable by a wider audience than its own visibility alone would allow.
VisibilityWho can readWho can write
privateCreator’s householdCreator’s household
link-readAnyone with the doc URLCreator’s household
link-writeAnyone with the doc URLAnyone with the doc URL
publicEvery authenticated userCreator’s household

Build docs developers (and LLMs) love