Tasks
Este conteúdo não está disponível em sua língua ainda.
Tasks are issues in the API. Address a task by its KEY-N identifier (e.g. ENG-42) or by id — on reads AND writes. Create tasks under a project (see Projects) or in bulk with the batch endpoint at the bottom of this page.
Search issues
Section titled “Search issues”Search issues across a workspace by title or exact KEY-N identifier. Returns up to 20 board rows (id, identifier KEY-N, title, state, assignees).
GET /v1/workspaces/{workspaceId}/issues/search
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/search?query=onboarding"Response: a list envelope { data, has_more, next_cursor }. While has_more is true, pass next_cursor back as cursor to get the next page.
Get issue
Section titled “Get issue”Get one issue by its identifier (KEY-N, e.g. “ENG-42”). Compact by default: id, identifier, title, state, priority, assigneeIds, startDate, dueDate, plus commentCount/subIssueCount/relationCount/attachmentCount. Heavy sections load only via include: “description” (plain text — an issue description can be huge, so it is never returned unless asked), “labels”, “comments”, “relations”, “subIssues”, “attachments” (file metadata + a short-lived signed download url per file — fetch it promptly, it expires in ~15 minutes; to view an image, request this and fetch the url), “fields” (resolved custom-property values: fieldId, name, kind, raw value, displayValue). “whiteboards” (first 4 description embeds with gated structured content; follow list_whiteboards with issueId and nextCursor for more). Including “description” also returns whiteboardIds for discovery. Unknown include keys are ignored.
GET /v1/workspaces/{workspaceId}/issues/{identifier}
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42"Response: the resulting object as JSON.
Get Task URL
Section titled “Get Task URL”Get the canonical, workspace-scoped web URL for one Task. Returns its stable raw id, current KEY-N identifier, and absolute URL. An old KEY-N retained as an alias after moving the Task resolves to the Task’s current identifier and URL.
GET /v1/workspaces/{workspaceId}/issues/{identifier}/url
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/url"Response: the resulting object as JSON.
Query issues
Section titled “Query issues”Filter and page issues across a workspace — the way to NARROW instead of dumping. All filters are optional; multiple VALUES within one filter would be OR (v1 takes single values), and DIFFERENT filters are AND-ed; absent = no constraint. Index-backed filters: projectId, assigneeUserId, creatorUserId, labelId, cycleId, moduleId. Status by dotby’s five workflow buckets (backlog|unstarted|started|completed|canceled) or an exact stateId. Post-filters (best combined with an index-backed filter or a project scope): priority (0-4), typeId, includeArchived (default false). Index-backed date ranges (ms epoch, inclusive): dueFrom/dueTo (on due date), completedFrom/completedTo (on completion time) — a range only matches issues that HAVE that date. Pagination: limit (default 25, max 100), opaque cursor (page until nextCursor is null to get everything), desc (default true); order is “created” (default) or “due” (pages by due date via its index). Note that when you filter by assigneeUserId or labelId, “created” orders by when that assignment/label was added, not when the issue was created (that filter drives the read). A low count with a non-null nextCursor does NOT mean few matches — post-filters can thin a page, so keep paging until nextCursor is null. Rows are COMPACT by default (id, identifier, title, state, priority, assigneeIds, startDate, dueDate); fields:“full” adds labels/module/cycle/type/assignee-names, and include:[“description”,“labels”] adds those per row (description is plain text; comments/relations/sub-issues/attachments are get_issue-only). Response: { issues, nextCursor, count }.
GET /v1/workspaces/{workspaceId}/issues
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues?limit=25"Response: a list envelope { data, has_more, next_cursor }. While has_more is true, pass next_cursor back as cursor to get the next page.
List my issues
Section titled “List my issues”List the current user’s issues in a workspace: assigned to them, created by them, or subscribed to.
GET /v1/workspaces/{workspaceId}/issues/mine
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/mine?tab=assigned"Response: a list envelope { data, has_more, next_cursor }. While has_more is true, pass next_cursor back as cursor to get the next page.
List sub-issues
Section titled “List sub-issues”List the sub-issues (children) of an issue.
GET /v1/workspaces/{workspaceId}/issues/{issueId}/sub-issues
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/sub-issues"Response: a list envelope { data, has_more, next_cursor }. While has_more is true, pass next_cursor back as cursor to get the next page.
List comments
Section titled “List comments”List the comments on an issue, oldest first.
GET /v1/workspaces/{workspaceId}/issues/{issueId}/comments
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/comments"Response: a list envelope { data, has_more, next_cursor }. While has_more is true, pass next_cursor back as cursor to get the next page.
Comment on issue
Section titled “Comment on issue”Add a comment to a Task. body is always Markdown, converted and validated as rich text by the server; no format flag or TipTap JSON is needed. @mentions notify. Optionally reply to a comment.
POST /v1/workspaces/{workspaceId}/issues/{issueId}/comments
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/comments" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"body":"Plain text content."}'Response: the resulting object as JSON.
List relations
Section titled “List relations”List the relations from an issue (blocks / blocked_by / relates / duplicate).
GET /v1/workspaces/{workspaceId}/issues/{issueId}/relations
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/relations"Response: a list envelope { data, has_more, next_cursor }. While has_more is true, pass next_cursor back as cursor to get the next page.
Link issues
Section titled “Link issues”Create a relation from one issue to another.
POST /v1/workspaces/{workspaceId}/issues/{issueId}/relations
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/relations" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"relatedIssueId":"ENG-7","type":"blocks"}'Response: the resulting object as JSON.
Unlink issues
Section titled “Unlink issues”Remove a relation between two issues. Pass the same (issueId, relatedIssueId, type) you’d give to link_issues; idempotent — a no-op when the relation isn’t there.
DELETE /v1/workspaces/{workspaceId}/issues/{issueId}/relations
curl -X DELETE -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/relations?relatedIssueId=ENG-7&type=blocks"Response: the resulting object as JSON.
List links
Section titled “List links”List an issue’s curated links to internal surfaces (page / whiteboard / ERD) and external URLs.
GET /v1/workspaces/{workspaceId}/issues/{issueId}/links
curl -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/links"Response: a list envelope { data, has_more, next_cursor }. While has_more is true, pass next_cursor back as cursor to get the next page.
Add link
Section titled “Add link”Add a curated link from an issue to an internal surface (kind “page” / “whiteboard” / “erd”, with targetId = that item’s id) or an external URL (kind “url”, with targetId = the http(s) URL). Idempotent per (kind, targetId). Optional label overrides the display text.
POST /v1/workspaces/{workspaceId}/issues/{issueId}/links
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/links" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"kind":"url","targetId":"https://example.com/spec"}'Response: the resulting object as JSON.
Remove link
Section titled “Remove link”Remove a curated link from an issue by its (kind, targetId) — the same pair you passed to add_link. Idempotent.
DELETE /v1/workspaces/{workspaceId}/issues/{issueId}/links
curl -X DELETE -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/links?kind=url&targetId=https%3A%2F%2Fexample.com%2Fspec"Response: the resulting object as JSON.
Update issue
Section titled “Update issue”Update a Task’s fields. description is always Markdown, converted and validated as rich text by the server; no format flag or TipTap JSON is needed. Only pass the fields to change. An empty description clears it; omitting it leaves it unchanged.
PATCH /v1/workspaces/{workspaceId}/issues/{issueId}
curl -X PATCH "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Content-Type: application/json" \ -d '{"title":"Ship the onboarding flow"}'Response: the resulting object as JSON.
Delete issue
Section titled “Delete issue”Permanently delete an issue and its comments/relations/attachments. Irreversible.
DELETE /v1/workspaces/{workspaceId}/issues/{issueId}
curl -X DELETE -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42"Response: the resulting object as JSON.
Add task to project
Section titled “Add task to project”Add a top-level task to another project without duplicating it. The task keeps one title, description, comments, attachments, subtasks, relations, and dates; the added project gets its own board column, ordering, assignees, and planning slots. Current assignees are copied by default, then remain project-specific. The caller must be a non-guest member of both projects. This is idempotent: an existing project membership is returned unchanged.
POST /v1/workspaces/{workspaceId}/issues/{issueId}/projects
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/projects" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"projectId":"ENG"}'Response: the resulting object as JSON.
Remove task from project
Section titled “Remove task from project”Remove a task from one added project without deleting the shared task. A non-guest member of either the task’s home project or the target project may recall or eject an existing membership. With access to both projects, this is idempotent: an already-absent membership returns removed: false.
DELETE /v1/workspaces/{workspaceId}/issues/{issueId}/projects/{projectId}
curl -X DELETE -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/projects/ENG"Response: the resulting object as JSON.
Set custom property
Section titled “Set custom property”Set or clear ONE custom-property value on an issue (Spec 109). value is {“kind”: <the field’s kind>, “value”: …} — text/url → string; number → number; date → ms epoch number; checkbox → boolean; select → array of option ids; member → array of user ids — or null to clear. Kinds/options/members are validated server-side; member values obey the same assignability rules as assignees.
PATCH /v1/workspaces/{workspaceId}/issues/{issueId}/fields
curl -X PATCH "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/fields" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Content-Type: application/json" \ -d '{"fieldId":"FIELD_ID","value":{"kind":"text","value":"Blue"}}'Response: the resulting object as JSON.
Move issue
Section titled “Move issue”Move an issue to a workflow state (board column) and/or reorder it.
POST /v1/workspaces/{workspaceId}/issues/{issueId}/move
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/move" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"stateId":"STATE_ID"}'Response: the resulting object as JSON.
Set assignees
Section titled “Set assignees”Replace an issue’s entire assignee set (pass [] to clear).
PATCH /v1/workspaces/{workspaceId}/issues/{issueId}/assignees
curl -X PATCH "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/assignees" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Content-Type: application/json" \ -d '{"userIds":["USER_ID"]}'Response: the resulting object as JSON.
Add assignee
Section titled “Add assignee”Add one assignee to an issue (idempotent).
POST /v1/workspaces/{workspaceId}/issues/{issueId}/assignees
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/assignees" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"userId":"USER_ID"}'Response: the resulting object as JSON.
Remove assignee
Section titled “Remove assignee”Remove one assignee from an issue.
DELETE /v1/workspaces/{workspaceId}/issues/{issueId}/assignees/{userId}
curl -X DELETE -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/assignees/USER_ID"Response: the resulting object as JSON.
Add label
Section titled “Add label”Add a label to an issue (idempotent).
POST /v1/workspaces/{workspaceId}/issues/{issueId}/labels
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/labels" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"labelId":"LABEL_ID"}'Response: the resulting object as JSON.
Remove label
Section titled “Remove label”Remove a label from an issue.
DELETE /v1/workspaces/{workspaceId}/issues/{issueId}/labels/{labelId}
curl -X DELETE -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/labels/LABEL_ID"Response: the resulting object as JSON.
Add sub-issue
Section titled “Add sub-issue”Nest an existing issue under another as a sub-issue — this is how you make one task a subtask of another. Both issues must be in the SAME workspace; re-parents the child if it already had a parent (the change is global). Rejects self-nesting and cycles. (To create a NEW issue already nested, pass parentIssueId to create_issue instead. PATCH update_issue does not accept a parent field.)
POST /v1/workspaces/{workspaceId}/issues/{parentIssueId}/sub-issues
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/sub-issues" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"childIssueId":"ENG-43"}'Response: the resulting object as JSON.
Remove sub-issue
Section titled “Remove sub-issue”Detach a sub-issue from its parent. The issue stays alive as a top-level issue — only its parent link is cleared, it is never deleted. Idempotent when it has no parent.
DELETE /v1/workspaces/{workspaceId}/issues/{childIssueId}/parent
curl -X DELETE -H "Authorization: Bearer $DOTBY_TOKEN" \ "https://api.dotby.app/v1/workspaces/acme/issues/ENG-43/parent"Response: the resulting object as JSON.
Archive issue
Section titled “Archive issue”Archive an issue (soft delete — reversible in the app).
POST /v1/workspaces/{workspaceId}/issues/{issueId}/archive
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/archive" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)"Response: the resulting object as JSON.
Attach file
Section titled “Attach file”Attach a SMALL file you already hold (a screenshot, a short document) to a task, passing its bytes inline as base64. data accepts bare base64 or a full data: URI. Limited to 1MB — MCP clients corrupt larger base64 in tool arguments, so for anything bigger (or any file on disk) use create_attachment_upload + register_attachment instead. Allowed: images, video, audio, text, PDF, Office/OpenDocument, zip, json, rtf — executables are rejected. Pass commentId to attach inside a comment rather than on the task itself. Read it back later with read_attachment.
POST /v1/workspaces/{workspaceId}/issues/{issueId}/attachments
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/attachments" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"fileName":"screenshot.png","contentType":"image/png","data":"iVBORw0KGgoAAA..."}'Response: the resulting object as JSON.
Start file upload
Section titled “Start file upload”Step 1 of 2 for a file of ANY size up to 25MB (the path to use for anything on disk, and for anything over 1MB). Returns { url, key }: PUT the raw bytes to url with a native HTTP client (e.g. curl -X PUT --upload-file <path> "<url>"), then call register_attachment with the same key to finish. The upload URL is short-lived — use it promptly. contentType and size are checked here and re-verified against the real uploaded object at register time, so they must be accurate.
POST /v1/workspaces/{workspaceId}/issues/{issueId}/attachments/upload-url
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/attachments/upload-url" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"contentType":"image/png","size":4096}'Response: the resulting object as JSON.
Finish file upload
Section titled “Finish file upload”Step 2 of 2: finish an upload started with create_attachment_upload, after the bytes have been PUT to the returned url. Pass the same key. The real object’s size and type are verified here — a mismatched or disallowed file is rejected and deleted. Pass commentId to attach inside a comment rather than on the task itself.
POST /v1/workspaces/{workspaceId}/issues/{issueId}/attachments/register
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/ENG-42/attachments/register" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"key":"ENG","fileName":"screenshot.png","contentType":"image/png","size":4096}'Response: the resulting object as JSON.
Batch create issues
Section titled “Batch create issues”Create up to 100 issues in one call with PER-ITEM results under HTTP 200 — one bad item never poisons the rest. Body: { projectId (id or KEY), items: [{title, description?, …create_issue fields}], plus shared defaults (stateId, priority, assigneeUserIds, labelIds) applied to every item. Task descriptions are always Markdown, converted and validated by the server. Legacy descriptionFormat values at batch or item level are ignored. Honors Idempotency-Key for the whole batch. Response: { succeeded: [{index, …}], failed: [{index, problem}] }.
POST /v1/workspaces/{workspaceId}/issues/batch
curl -X POST "https://api.dotby.app/v1/workspaces/acme/issues/batch" \ -H "Authorization: Bearer $DOTBY_TOKEN" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"projectId":"ENG","items":[{"title":"First task"},{"title":"Second task"}]}'Response: HTTP 200 with PER-ITEM results { succeeded: [{index, …}], failed: [{index, problem}] } — one bad item never fails the rest. Check failed even on 200.
Errors
Section titled “Errors”Every error is an RFC 9457 application/problem+json body with a machine-stable code. Branch on the code, not the message:
401—unauthenticated/invalid_token: the bearer token is missing, expired, or revoked. Re-authenticate; do not retry as-is.403—insufficient_scope/forbidden/upgrade_required: the token works but may not do this.upgrade_requiredmeans the workspace is not on Pro.404—not_found_or_forbidden: the resource does not exist for this token. Never probe for existence.409—idempotency_conflict: sameIdempotency-Key, different body. Mint a new key.429—rate_limited: back off for the number of seconds inRetry-After, then retry.400—validation_failed: the request shape is wrong. Fix the request; retrying unchanged will fail again.