Comments and attachments let you annotate any card or standalone document with threaded text notes and uploaded files. Comments are markdown bodies attributed to the posting principal; attachments are binary files stored on disk whose bytes are served back over a dedicated download endpoint. Both resources follow the visibility of their subject — there is no separate access control to configure.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.
Comments
A comment belongs to exactly one card or exactly one document (never both). The database enforces this with aCHECK constraint. Comments are returned oldest-first by default and are never paginated — use the ?limit= parameter on the activity feeds if you need a bounded window of recent events instead.
List comments on a card
The card ID.
Comment objects:
UUID of the comment.
The card this comment belongs to.
Always
null for card comments.Principal ID of the author.
Markdown body of the comment.
ISO 8601 timestamp.
ISO 8601 timestamp.
Add a comment to a card
The card ID.
Markdown body of the comment.
201 with the created Comment object.
List comments on a document
The document ID.
Add a comment to a document
The document ID.
Markdown body of the comment.
201 with the created Comment object.
Delete a comment
The comment ID.
{ "ok": true }.
Attachments
Attachments are binary files uploaded to a card or a standalone document. The file bytes live on disk inATTACHMENTS_DIR — not in SQLite — so a complete backup must capture both the database file and the attachments directory. The path on disk is derived from the attachment id and is never stored in the database; this prevents path-injection and means a row without its bytes is impossible by construction (writes go file-then-row; deletes go row-then-file).
The ?filename= query parameter is required. It is stored as-is for display purposes and its extension determines the Content-Type served on download — the Content-Type header you send on upload is ignored entirely. This prevents a malicious upload from claiming a dangerous MIME type.
A card description doc is not a valid attachment subject. Files pasted or dropped into a card’s description belong to the card, not to the underlying doc. Attempting to attach to a card-description doc returns
400. Always attach files to the card itself when working with card descriptions.List attachments on a card
The card ID.
Attachment objects:
UUID of the attachment. Use this in
/attachments/{id} to download the bytes.The card this file belongs to.
Always
null for card attachments.Original filename as uploaded, sanitized for display.
Server-resolved MIME type based on file extension.
File size in bytes.
Hex-encoded SHA-256 of the file bytes. Used as the ETag for cache validation.
Principal ID of the uploader.
ISO 8601 timestamp.
Upload a file to a card
The card ID.
The filename including extension. The extension determines the served
Content-Type.Content-Type: application/octet-stream.
Returns 201 with the created Attachment object.
List attachments on a document
The standalone document ID.
Upload a file to a document
The standalone document ID. Returns
400 if this document is a card description doc — attach to the card instead.The filename including extension.
Content-Type: application/octet-stream.
Returns 201 with the created Attachment object.
Download an attachment
The attachment ID.
Content-Typeresolved server-side from the stored filename extension (never the uploader’s claim).Content-Disposition: attachmentfor all file types except a small allowlist of inline image formats. SVG is explicitly excluded from inline serving — it can carry script and this endpoint is on the app’s own origin.ETagderived from thesha256hash for cache revalidation.
The attachment download path deliberately has no filename segment (e.g.
/attachments/{id}, not /attachments/{id}/screenshot.png). A trailing .md anywhere in the path would be intercepted by hooks.server.ts as a markdown rendition request before the route handler runs. To embed an attachment inline in a markdown document, use .Delete an attachment
The attachment ID.
{ "ok": true }.
Embedding attachments in markdown
Once uploaded, any attachment can be embedded inline in a card description or standalone document:sha256 field on the attachment record is used as the HTTP ETag, so browsers cache the bytes and only re-fetch when the file changes.