Hashboard organizes work into boards, columns, and cards — but a card does not have to live on a board at all. Loose cards exist independently at their own URL and can be promoted onto a board at any time. Understanding this model, along with how assignees and labels interact with placement, is the foundation for using Hashboard effectively.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.
Boards
A board is a named container with an optional description and a visibility setting. The principal who creates a board is its owner; the owner’s household plus any card assignees can access cards on it (subject to the board’s visibility). Boards are listed, filtered, and searched independently from their cards.Board fields
name, description, visibility, createdBy, archivedAt
Board endpoints
GET /api/v1/boards — list visible boardsGET /api/v1/boards/{id} — composite view: { board, columns, cards }PATCH /api/v1/boards/{id} — update fieldsPOST /api/v1/boards/{id}/archive — archiveColumns
Columns are ordered containers within a board. They carry a name and a fractional-indexpos value that determines their left-to-right order. Columns can be archived independently — archiving a column does not archive the board or its other columns. The archived state is reversible via POST /api/v1/columns/{id}/unarchive.
Cards
A card is the atomic unit of work. Every card has a title, a visibility level, an optional due date, and a linked description document (see Documents). Cards belong to at most one column, and therefore at most one board.Card placement
A card’s placement is determined by three nullable columns —board_id, column_id, and pos — which are either all set or all null, enforced by a database CHECK constraint:
cards.board_id is deliberately denormalized (because a column already implies a board) to make board-scoped queries join-free. The service layer keeps board_id and column_id in sync atomically when cards move between boards.
Loose cards are cards where all three placement fields are null. A loose card exists at its own URL (
/cards/{id}) and appears in every eligible principal’s inbox (GET /api/v1/inbox). Loose cards have the full card feature set — description, labels, assignees, attachments — independent of any board. To place a loose card onto a board, call POST /api/v1/cards/{id}/move with a target columnId and optional prevId/nextId neighbors.Ordering
Card position within a column uses fractional-index text keys — lexicographic keys in the style popularized by Figma. Because keys sort lexicographically, inserting a card between two existing cards or moving a card to a new position writes exactly one row. Move APIs acceptprevId and nextId (the IDs of neighboring cards in the target column) rather than absolute positions, so callers never need to re-number their siblings.
null appends the card at the end of the column. Passing only prevId (with nextId: null) inserts after that card; passing only nextId (with prevId: null) inserts before it.
Card Descriptions
Every card is linked to a row in thedocs table (kind card) via cards.doc_id. The description is a full markdown document — not a plain-text field. It can contain headings, fenced code blocks, tables, and links to other Hashboard resources. Card docs inherit the card’s visibility and never hold their own — see Documents for the editing model.
Assignees
Principals (humans or agents) can be assigned to a card. Assignment does two things:- Task attribution — the card surfaces in the assignee’s workload views.
- Sharing — an assignee can read the card regardless of the board’s visibility. This grant is durable: it survives visibility changes on the board or the card.
Assigning agents
Assigning agents
Agents are first-class principals and can be assigned to cards exactly like humans. An agent acts with its owner’s authorization (resolved through
principals.owner_id), but its edits and comments are attributed to the agent’s own identity in activity feeds. This means you can hand off a task to an agent and its work remains legible as its own.Labels
Labels are a global, instance-wide palette with unique names. Any card — board-placed or loose — can carry any label. Because labels belong to the instance rather than to a board, moving a card between boards never invalidates its labels, and loose cards can be tagged before they are placed.Archival
Boards, columns, and cards each carry an independentarchived_at timestamp. Archiving operates at whichever level you target:
| Target | What it affects |
|---|---|
| Card | That card only — column and board remain live |
| Column | That column only — board and other columns remain live |
| Board | The board itself — columns and cards retain their own archive state |
GET /api/v1/boards/{id}/archived (returns { columns, cards }). All archive operations are reversible via the corresponding unarchive endpoint.
Quick Reference: Card Endpoints
Card API surface
Card API surface
| Method | Path | Description |
|---|---|---|
GET | /api/v1/inbox | Loose cards visible to you |
POST | /api/v1/cards | Create a card (loose or placed) |
GET | /api/v1/cards/{id} | Composite view: { card, doc, assignees, labelIds, linkedDocs, attachments } |
PATCH | /api/v1/cards/{id} | Update card fields |
POST | /api/v1/cards/{id}/move | Move to a column (or make loose) |
POST | /api/v1/cards/{id}/archive | Archive |
POST | /api/v1/cards/{id}/unarchive | Unarchive |
POST | /api/v1/cards/{id}/detach | Remove from board (make loose) |
GET | /api/v1/boards/{id}/cards | Cards on a board in position order |
GET | /api/v1/boards/{id}/archived | Archived cards on a board |