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.

Cards are the primary unit of work in Hashboard. A card can live inside a board column or exist as a loose card outside any board (sometimes called an inbox card). Every card owns a full-markdown description document, referenced by card.docId — to read or edit the description body, use the Documents API at GET /api/v1/docs/{card.docId} and PUT /api/v1/docs/{card.docId}. Cards support rich metadata: assignees (which also grant visibility), labels from the global palette, linked standalone documents, file attachments, comments, and an activity feed. Visibility changes, archival, and deletion are creator-only. All write endpoints require a bearer token (Authorization: Bearer hb_…) or session cookie.

GET /api/v1/inbox

Return your household’s loose cards — cards that are not placed on any board, created by or assigned to you or any agent you own. Pass ?archived=true to see archived loose cards. GET /api/v1/inbox

Query Parameters

archived
string
Pass true to return archived loose cards instead of live ones.

Response

Returns an array of Card objects (see Card fields below).
curl -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/inbox

POST /api/v1/cards

Create a new card. Without columnId, the card is created as a loose card in the inbox. Pass columnId (and optionally the board will be inferred) to place it directly onto a board. Returns 201 Created. POST /api/v1/cards

Request Body

title
string
required
Card title.
columnId
string
Column to place the card in. The card is appended at the end of the column. Omit to create a loose card.
visibility
string
One of private (default), link-read, link-write, or public.
dueAt
string
Optional ISO 8601 due date/time.
content
string
Initial markdown content for the card’s description document. Defaults to an empty string.

Response

Returns the created Card object. The docId field references the description document — pass it to PUT /api/v1/docs/{docId} to update the description later.
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Implement OAuth flow",
    "columnId": "018f3c1a-…",
    "visibility": "private",
    "content": "## Scope\n\nImplement PKCE + OIDC."
  }' \
  https://your-instance.example/api/v1/cards

GET /api/v1/cards/{id}

Fetch a composite card view in one request: card metadata, its description document, assignee IDs, label IDs, linked documents, and attachments. GET /api/v1/cards/{id}

Path Parameters

id
string
required
Card ID.

Response

card
Card
Card metadata.
doc
Doc
The card’s description document. Use PUT /api/v1/docs/{doc.id} to save edits.
assignees
string[]
Array of principal IDs assigned to this card.
labelIds
string[]
Array of label IDs attached to this card.
linkedDocs
LinkedDoc[]
Standalone documents linked to this card (metadata only — no content).
attachments
Attachment[]
Files attached to this card.
curl -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/cards/018f3c1b-…
Append .md to the card URL (/cards/{id}.md) or send Accept: text/markdown to get the full card as a markdown document with YAML frontmatter. The frontmatter includes doc (the docId) and version — use those to round-trip edits through PUT /api/v1/docs/{docId}.

PATCH /api/v1/cards/{id}

Update card fields. All fields are optional. Visibility changes are creator-only — other principals receive 403. To edit the card’s description, use PUT /api/v1/docs/{card.docId}. PATCH /api/v1/cards/{id}

Path Parameters

id
string
required
Card ID.

Request Body

title
string
New card title.
dueAt
string | null
New due date (ISO 8601), or null to clear it.
visibility
string
New visibility mode. Creator-only.

Response

Returns the updated Card object.
curl -X PATCH \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/json" \
  -d '{"title": "Implement OAuth (PKCE)", "dueAt": "2025-09-01T00:00:00Z"}' \
  https://your-instance.example/api/v1/cards/018f3c1b-…

POST /api/v1/cards/{id}/move

Place a card in a column, optionally between two neighboring cards. The column must belong to a board the caller can write. Pass prevId/nextId from the current column card list to position the card precisely; omit both (or pass null) to append it at the end. POST /api/v1/cards/{id}/move

Path Parameters

id
string
required
Card ID.

Request Body

columnId
string
required
Target column ID. The card will be moved to this column (and its board).
prevId
string | null
ID of the card that should be immediately before this one. null or omitted means insert at the start.
nextId
string | null
ID of the card that should be immediately after this one. null or omitted means append at the end.

Response

Returns the updated Card object with new columnId, boardId, and pos values.
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/json" \
  -d '{"columnId": "col-done-id", "prevId": null, "nextId": null}' \
  https://your-instance.example/api/v1/cards/018f3c1b-…/move

POST /api/v1/cards/{id}/detach

Remove a card from its board and column, making it a loose (inbox) card. The card’s content, assignees, labels, and linked documents are preserved. A detached card can be re-placed onto any board via POST /api/v1/cards/{id}/move. POST /api/v1/cards/{id}/detach

Path Parameters

id
string
required
Card ID.

Response

Returns the updated Card object with boardId, columnId, and pos all set to null.
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/cards/018f3c1b-…/detach

POST /api/v1/cards/{id}/archive

Archive a card. Creator-only. Archived cards are excluded from board and inbox views but remain accessible via their direct URL and through GET /api/v1/boards/{boardId}/archived. POST /api/v1/cards/{id}/archive

Path Parameters

id
string
required
Card ID.

Response

Returns the updated Card object with archivedAt set.
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/cards/018f3c1b-…/archive

POST /api/v1/cards/{id}/unarchive

Restore an archived card to active status. Creator-only. POST /api/v1/cards/{id}/unarchive

Path Parameters

id
string
required
Card ID.

Response

Returns the updated Card object with archivedAt set to null.
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/cards/018f3c1b-…/unarchive

GET /api/v1/cards/{id}/assignees

List the principal IDs assigned to a card. Assignees always have read access to the card regardless of its visibility setting — assignment is a durable sharing grant that survives visibility changes. GET /api/v1/cards/{id}/assignees

Path Parameters

id
string
required
Card ID.

Response

Returns an array of principal ID strings.
curl -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/cards/018f3c1b-…/assignees

PUT /api/v1/cards/{id}/assignees/{principalId}

Assign a principal to a card. Idempotent — assigning an already-assigned principal is a no-op. Only the card creator, existing assignees, or household members may assign. Assignment grants the principal read access to the card permanently (including if the card later becomes private). PUT /api/v1/cards/{id}/assignees/{principalId}

Path Parameters

id
string
required
Card ID.
principalId
string
required
ID of the principal to assign (human or agent).

Response

Returns { "ok": true }.
curl -X PUT \
  -H "Authorization: Bearer hb_…" \
  https://your-instance.example/api/v1/cards/018f3c1b-…/assignees/agent-018f…

DELETE /api/v1/cards/{id}/assignees/{principalId}

Unassign a principal from a card. If the card is private and the principal has no other visibility path, they lose access. DELETE /api/v1/cards/{id}/assignees/{principalId}

Path Parameters

id
string
required
Card ID.
principalId
string
required
ID of the principal to remove.

Response

Returns { "ok": true }.
List standalone documents linked to a card. Returns metadata only — never document content. GET /api/v1/cards/{id}/links

Path Parameters

id
string
required
Card ID.

Response

Returns an array of LinkedDoc objects (id, title, visibility, updatedAt).

PUT /api/v1/cards/{id}/links/{docId}

Link a standalone document to a card. Idempotent. The caller must have read access to both the card and the document. Only standalone documents can be linked; passing a card description doc ID returns 400. PUT /api/v1/cards/{id}/links/{docId}

Path Parameters

id
string
required
Card ID.
docId
string
required
Standalone document ID to link.

Response

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

DELETE /api/v1/cards/{id}/links/{docId}

Remove a document link from a card. The document itself is not deleted. DELETE /api/v1/cards/{id}/links/{docId}

Path Parameters

id
string
required
Card ID.
docId
string
required
Document ID to unlink.

Response

Returns { "ok": true }.

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

Upload a file and attach it to a card. The file bytes are sent as the raw request body with a binary content type — not multipart/form-data. The filename is passed as a query parameter; the server resolves the content type from the file extension (the declared Content-Type header is ignored). Returns 201 Created. POST /api/v1/cards/{id}/attachments

Path Parameters

id
string
required
Card ID.

Query Parameters

filename
string
required
Original filename (e.g. report.pdf). 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 or curl -F. SvelteKit treats those content types as browser form submissions and rejects them with 403 before any route handler runs. This behavior differs between development and production — it will appear to work locally but fail against a production build.Always send the raw bytes:
curl -X POST \
  -H "Authorization: Bearer hb_…" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @report.pdf \
  "https://your-instance.example/api/v1/cards/018f3c1b-…/attachments?filename=report.pdf"

Response

Returns the created Attachment object. The file bytes are served at GET /attachments/{id} and can be embedded in any markdown document as ![alt text](/attachments/{id}).
id
string
Attachment UUID. Used to construct the download URL.
cardId
string | null
Parent card ID.
filename
string
Stored filename (sanitized).
contentType
string
MIME type resolved server-side from the extension.
size
number
File size in bytes.
sha256
string
Hex SHA-256 of the file contents (returned as ETag on download).
createdBy
string
Principal who uploaded the file.
createdAt
string
ISO 8601 timestamp.

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

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

Path Parameters

id
string
required
Card ID.

Request Body

body
string
required
Comment text (markdown supported).

Response

Returns the created Comment object.
id
string
Comment UUID.
cardId
string | null
Parent card ID.
docId
string | null
Always null for card comments.
authorId
string
Principal who authored the comment.
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": "LGTM — merging tomorrow."}' \
  https://your-instance.example/api/v1/cards/018f3c1b-…/comments

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

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

Path Parameters

id
string
required
Card 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). Activity entries survive the deletion of their subject.
curl -H "Authorization: Bearer hb_…" \
  "https://your-instance.example/api/v1/cards/018f3c1b-…/activity?limit=25"

Editing card descriptions

A card’s description is a full markdown document stored separately from the card row. To read or edit it:
  1. Fetch the card: GET /api/v1/cards/{id} — note card.docId and doc.version.
  2. Edit locally.
  3. Save: PUT /api/v1/docs/{card.docId} with { "baseVersion": <version>, "content": "…" }.
If another editor saved while you were editing, you’ll receive 409 Conflict with currentVersion in the response body. Re-fetch, merge, and retry. See the Documents API for the full save reference.
Card description docs inherit the card’s visibility and cannot be archived or deleted independently. To delete the card (and its description), archive the card via POST /api/v1/cards/{id}/archive. Standalone document deletion is covered on the Documents page.

Build docs developers (and LLMs) love