Skip to content

API Reference

HoneyDew exposes a REST API for managing boards, columns, cards, and labels. Resource endpoints are prefixed with /api; health and schema endpoints are not.


Overview

Property Value
Base URL http://localhost:8000
Auth None (designed for local / trusted-network use)
Content type application/json
Interactive docs http://localhost:8000/docs (Swagger UI, auto-generated by FastAPI)
Live OpenAPI schema openapi.json — authoritative request/response fields for your running version

These are default local addresses. For a remote runtime, use its reachable private API base URL. Start with GET /api/config and GET /api/boards to discover profile and board IDs, then GET /api/boards/{id} for columns. IDs in examples are illustrative. Send the configured agent profile explicitly on agent-created cards and comments. File uploads use multipart form data, not JSON.


Health Check

GET /health

Returns {"status": "healthy"} when the backend is running. Use this to verify connectivity before making API calls.


Configuration

GET /api/config

Returns the application configuration (user and agent profile names, board definitions). Useful for agents that need to discover profile IDs at runtime.


Boards

List all boards

GET /api/boards

Returns an array of boards (id, name, created_at). Does not include nested columns/cards.

Create a board

POST /api/boards
Field Type Required Description
name string Yes Board name (1–255 chars).
columns string[] No Column names in order. Defaults to ["To Do", "In Progress", "Done"].

Get a board

GET /api/boards/{id}

Returns the board with all columns and cards. Supports an optional query parameter:

Param Type Description
profile string Filter cards to only those owned by this profile ID.

Update a board

PATCH /api/boards/{id}
Field Type Required Description
name string No New board name.

Delete a board

DELETE /api/boards/{id}

Deletes the board and all its columns and cards. Returns 204 No Content.


Columns

Create a column

POST /api/columns
Field Type Required Description
board_id int Yes The board to add the column to.
name string Yes Column name (1–255 chars).
position int No Position index (0-based). Appends to end if omitted.

Update a column

PATCH /api/columns/{id}
Field Type Required Description
name string No New column name.
position int No New position index.

Delete a column

DELETE /api/columns/{id}

Deletes the column and all its cards. Returns 204 No Content.


Cards

List cards

GET /api/cards
Param Type Description
board_id int Filter by board.
column_id int Filter by column (takes precedence over board_id).
profile string Filter by profile ID.
priority int Filter by priority (1–4).
has_due_date bool true = only cards with a due date; false = only cards without.
include_archived bool Include soft-archived cards. Defaults to false.

Create a card

POST /api/cards
Field Type Required Default Description
column_id int Yes — Column to place the card in.
title string Yes — Card title (1–255 chars).
description string No null Card description (max 5000 chars).
priority int No 2 Priority: 1 = Low, 2 = Medium, 3 = High, 4 = Urgent.
due_date string No null ISO 8601 date (YYYY-MM-DD).
profile string No User profile Profile ID of the card owner. Must be a valid profile from config.
is_epic bool No false Make the card an Epic whose description stores the plan.
epic_id int No null Link a task to an Epic on the same board.
label_ids int[] No [] Existing project tags assigned directly to this issue. Unknown IDs reject the entire creation.

Get a card

GET /api/cards/{id}

Returns the card with all fields and project tags. labels is the deduplicated union of direct_labels (assigned to this issue) and inherited_labels (its Parent Epic’s current tags). Inheritance applies to existing and new issues, including profile-filtered board/API responses; editing, replacing, or unlinking the Epic updates inherited tags without changing direct tags. Epics also include a shallow subtasks list with each child's current column_name for status display.

Update a card

PATCH /api/cards/{id}

label_ids replaces the issue’s direct tags atomically; omit it to preserve them, or send [] to clear them. Inherited tags remain while the issue belongs to the Epic. Create a shared tag through POST /api/labels first, then include its ID. The issue creation/editing form provides both selection and inline tag creation.

All fields are optional. Only provided fields are updated.

Field Type Description
title string New title.
description string New description.
priority int New priority (1–4).
due_date string New due date (ISO 8601).
profile string New profile ID.
is_epic bool Convert an unlinked card to or from an Epic.
epic_id int or null Link or unlink the task from an Epic on the same board.
completed_at string or null Completion datetime. Set automatically on entry to Done and may be edited manually.
archived_at string or null Soft-archive datetime. Set to null to restore a card.
agent_tokens_used int Optional measured cumulative task total so far (0–9,007,199,254,740,991, integers only); replacement, not increment. Report during progress as well as completion.
agent_model string Model name used by the agent (optional, max 120 chars).
agent_execution_time_seconds float Agent execution time in seconds (optional).
agent_started_at string ISO 8601 datetime when the agent started work (optional).
agent_completed_at string ISO 8601 datetime when the agent finished (optional).

These agent metadata fields support both progress and completion reports. Token totals appear beside priority on board cards and task subtitles, refreshed every five seconds. Omitted fields preserve existing values; explicit null on PATCH clears them. Usage remains unknown until measured and reported.

Acquire, renew, and release a task lease

Task leases prevent two agents from working the same card. HoneyDew acquires them atomically and returns HTTP 409 when another live lease already owns the card. Epics and archived cards cannot be leased.

POST /api/cards/{id}/lease/acquire
{"owner":"umbra","worker_session":"foreman-pending","ttl_seconds":1800}

POST /api/cards/{id}/lease/renew
{"lease_id":"<lease id>","worker_session":"<session key>","ttl_seconds":1800}

POST /api/cards/{id}/lease/release
{"lease_id":"<lease id>"}

Only the matching opaque lease_id may renew or release a lease. ttl_seconds must be between 60 seconds and six hours and defaults to 30 minutes. An expired lease is inactive and may be atomically replaced. Card responses expose the lease fields plus task_lease_active; the UI shows Umbra working only while that value is true. Moving a non-Epic card into a Done-equivalent or exact Blocked column clears every lease field in the same database transaction.

Task dependencies

POST /api/cards/{id}/dependencies/{prerequisite_id} links a prerequisite; DELETE on the same path removes the link. Self-links, cross-board links, and cycles are rejected. Card responses include prerequisites, dependents, dependencies_satisfied, and blocked_by_dependency_ids. An incomplete prerequisite prevents lease acquisition with HTTP 409. Tasks may use a task or Epic as a prerequisite; the selected card must reach a completion column to satisfy the link. Epics themselves cannot have prerequisites. Dependency summaries include is_epic to distinguish tasks and Epics.

Move a card

POST /api/cards/{id}/move
Field Type Required Default Description
column_id int Yes — Target column ID.
position int No 0 Position within the target column (0-based).

Handles position reordering automatically within and across columns. Entering a Done-equivalent column sets completed_at; leaving it clears completed_at and archived_at. Entering Done or Blocked also clears an active task lease atomically; similarly named nonterminal columns such as Unblocked do not.

Move a card to another board

POST /api/cards/{id}/move-to-board
Field Type Required Description
board_id int Yes Target board ID.
column_name string No Preferred column on the target board.

Target column resolution:

  1. If column_name is provided and exists on the target board, it is used.
  2. Otherwise, the card's current column name is matched on the target board.
  3. If no match, the first column of the target board is used.

Transfer a card

POST /api/cards/{id}/transfer
Field Type Required Description
target_profile string Yes Profile ID to transfer the card to. Must be a valid profile from config.

Delete a card

DELETE /api/cards/{id}

Deletes the card and reorders remaining cards in the column. Returns 204 No Content.


Labels

List all labels

GET /api/labels

Create a label

POST /api/labels
Field Type Required Default Description
name string Yes — Label name (1–100 chars).
color string No #6366f1 Hex color string (e.g. #ff00aa).

Add a label to a card

POST /api/cards/{card_id}/labels/{label_id}

Idempotent — adding an already-attached label is a no-op.

Remove a label from a card

DELETE /api/cards/{card_id}/labels/{label_id}

Returns 204 No Content.


Comments

List comments on a card

GET /api/cards/{card_id}/comments

Returns an array of comments for the card, ordered by created_at.

Add a comment to a card

POST /api/cards/{card_id}/comments

Optional agent_tokens_used reports a measured cumulative task total atomically with the comment (same integer limits as PATCH). Omitted or null preserves existing usage; zero records measured zero. A repeated total replaces rather than adds. Invalid counts reject the entire request.

Field Type Required Description
body string Yes Comment text (1–5000 chars).
profile string Yes Explicit profile ID of the commenter. Omitting it is rejected so agent activity cannot be attributed to the configured user.

Returns the created comment object:

{
  "id": 1,
  "card_id": 5,
  "profile": "tony",
  "body": "Looks good, moving to Done.",
  "created_at": "2026-02-22T14:30:00"
}

Priority Values

Value Name Description
1 Low Low-priority work.
2 Medium Default priority.
3 High Important work that should be addressed soon.
4 Urgent Critical work that needs immediate attention.

Issue activity timestamps

Card.updated_at powers Date last updated. It records the most recent persisted direct change to an issue, not the most recent change anywhere in its rendered/derived response. New relationship timestamps use the same installation- local, timezone-naive clock as existing card field updates, not storage objects' UTC clock.

Mutation Cards whose updated_at changes
Changed card fields, profile, column, position, completion/archive or agent metadata The changed cards (including cards shifted by reordering).
Successful lease acquire, renew or release The leased card; renewal is real expiry/heartbeat activity.
Add a comment Its parent card. Every accepted POST creates a new comment, even with repeated text. Comments currently have no edit/delete API.
Add/remove a label The card, only if membership changes.
Rename/recolor/delete a shared label All directly labeled cards, including archived cards, only on a real change.
Add/remove a prerequisite link Both endpoints, only if the link changes.
Create/link/unlink/reassign an Epic child The child and old/new parent Epics whose membership changes.
Delete a card (also via column/board deletion) Surviving prerequisite/dependent endpoints, its parent Epic, and children unlinked from a deleted Epic.
Publish/link/detach/rename an attachment Its parent card, only if the link or normalized display filename changes.
Rename a column/status Cards directly in that column, only if the name changes.

Relationship timestamps are written in the same database transaction as the relationship mutation. Rejected operations and rolled-back writes leave them unchanged. A failed upload never bumps a card unless its attachment is successfully published. Duplicate label/prerequisite additions, removal of absent links, idempotent upload retries, duplicate object attachments, same-name attachment renames, same-value field patches and same-position moves do not bump timestamps.

Reads, polling, downloads, standalone object operations, board renames and column reordering do not count as issue activity. There is no transitive timestamp propagation: changes in prerequisite completion/readiness, linked card titles, Epic child progress, or inherited Epic labels can change a displayed result without updating the observing card. Direct membership changes still count as specified above. Automatic archival retains its existing direct-write semantics.

This policy applies prospectively. No migration/backfill rewrites historical created_at, updated_at, completion or comment timestamps; earlier unrecorded relationship activity cannot be reconstructed from today's state.

Card Response Shape

All card endpoints return a consistent object:

{
  "id": 1,
  "column_id": 2,
  "profile": "jarvis",
  "title": "Implement feature X",
  "description": "Details here",
  "priority": 3,
  "due_date": "2026-03-01",
  "position": 0,
  "created_at": "2026-02-22T10:30:00",
  "updated_at": "2026-02-22T11:45:00",
  "labels": [
    { "id": 1, "name": "frontend", "color": "#06b6d4" }
  ],
  "comments": [
    { "id": 1, "card_id": 1, "profile": "tony", "body": "Started working on this.", "created_at": "2026-02-22T12:00:00" }
  ],
  "agent_tokens_used": null,
  "agent_model": null,
  "agent_execution_time_seconds": null,
  "agent_started_at": null,
  "agent_completed_at": null
}

Error Responses

Errors return a JSON body with a detail field:

{
  "detail": "Card with id 99 not found"
}
Status Meaning
400 Bad request (invalid profile, missing fields, board has no columns).
404 Resource not found.
422 Validation error (Pydantic).

File attachments and storage

See Attachments and S3-compatible storage for issue/Epic uploads, managed-object APIs, native MCP, host file roots, limits, retention and backup/restore.

Settings

  • PATCH /api/config: update user_display_name, agent_display_name, and/or archive_completed_after_hours (null or zero disables archiving). Existing profile IDs cannot be changed through this endpoint.
  • POST /api/profiles: create an additional profile with profile_id, display_name, and role (user or agent, default user). IDs use lowercase letters, numbers, hyphens, and underscores, begin with a letter or number, and must be unique. Duplicate IDs return 409.
  • PATCH /api/boards/{id}/theme: set theme to midnight, umbra, ember, verdant, executive, or linen.

These endpoints return the updated application configuration and persist narrow, atomic updates to the active config file while preserving unrelated fields. Changes take effect without restarting. POST /api/boards creates a board with default columns when none are supplied; boards now survive startup even when not listed in config.