Move or copy a card to another board

A card can go to another board in two ways. Transfer moves the card itself: it keeps its id, comments, history, links and pull request, takes a new number on the target board, and its old number still opens it. Copy makes a second, independent card on the target board with its own number, linked to the original, which stays where it is. Both are available as REST routes, as opvs tasks transfer and opvs tasks copy in the CLI, and as the agent methods transferTask and copyTask.

Before you call

Every route takes a personal access token, Authorization: Bearer $OPVS_PAT, with the board:write scope. Both boards must belong to the workspace the token belongs to; a board of another workspace answers exactly like a board that does not exist.

Value Accepts
task_id (path) a card ref such as OPS-142, a UUID prefix of 8 or more hex characters, or a full UUID
board_id (body) a board key such as OPS, a UUID prefix, or a full UUID
column_id (body) a column name on the target board, case-insensitive, or a column UUID

Transfer or copy?

Transfer Copy
Card id kept new
Card number new number on the target board; the old ref keeps opening the card new number on the target board
Title, description, brief, labels, priority, visible fields, routing kept carried over
Status, assignee kept not carried; the copy starts unassigned, with the status of its column
Comments, activity history, files kept not carried
Pull request, branch, dependencies, subtasks kept not carried
GitHub issue sync follows the card to the new board none; no issue is filed for the copy
Column when column_id is omitted the column with the same name on the target board, otherwise the target's default column the target board's default column
The original is the card that moved stays where it was; both cards get a system comment naming the other, and a related task link joins them

Neither route puts a card in a claimable column such as Ready unless column_id names it, so a move or a copy never hands work to a builder by accident.

Transfer a card

POST /api/v1/board/tasks/{task_id}/transfer

Moves the card to board_id. Returns 200 and the full task object on its new board.

Parameters

Name In Type Required Description
task_id path string yes The card to move
board_id body string yes The target board
column_id body string no The target column; see the defaults above

Example

curl -X POST "https://api.opvs.ai/api/v1/board/tasks/OPS-142/transfer" \
  -H "Authorization: Bearer $OPVS_PAT" \
  -H "Content-Type: application/json" \
  -d '{"board_id": "WEB"}'

# Response 200, application/json (trimmed to the fields that change)
# {"id": "ae0a05de-b41c-4e7f-823c-b13586b7f93b", "ref": "WEB-4", "number": 4,
#  "board_id": "244f9deb-0da1-4ddf-8354-a654f4347af8",
#  "column": {"name": "To Do", "slug": "todo", "mapped_status": "pending"},
#  "status": "pending", "comment_count": 2}
#
# GET /api/v1/board/tasks/OPS-142 now returns the same card, ref "WEB-4".
# 409 {"detail": "Card is already on the target board"} if it is already there.

Errors

Status detail When Resolution
401 Not authenticated no token, or the token is revoked or expired send a valid Authorization: Bearer token
403 a scope message the token lacks board:write request a token that carries board:write
403 max_tasks_per_board the target board is at its card limit make room on the target board, or raise the plan limit
404 Task not found the card does not exist or you cannot read it check the ref; refs are board key plus number
404 Board not found the target board does not exist or belongs to another workspace check board_id; list boards with GET /api/v1/board/boards
404 Column '<name>' not found on this board. column_id names no column on the target board list the target's columns; names are matched on the target, not the source
422 board_id must be a non-empty string the body has no board_id send {"board_id": "…"}
422 Target board is archived the target board is archived unarchive it, or choose another board
422 Target board has a different board type the boards are of different types, such as tasks and contacts transfer only between boards of the same type
409 Card is already on the target board board_id is the card's own board to change column, use POST /api/v1/board/tasks/{task_id}/move
409 Cards in progress cannot be transferred the card's status is in_progress wait until it leaves in_progress, or copy it instead
409 Cards waiting on an answer cannot be transferred the card is waiting_on_answer answer the question on the card, then transfer
409 A build has just claimed this card a builder claimed the card moments ago wait for the build to finish or release
409 Ship Line cards move only when the ledger moves the card is a Ship Line review card these cards are moved by the ship ledger, not by hand
409 A card with a parent cannot be transferred the card is a subtask transfer its parent
409 A card with subtasks cannot be transferred the card has subtasks move or detach the subtasks, then transfer
409 A card with stages cannot be transferred the card has stages copy it instead, or finish the stages

Copy a card

POST /api/v1/board/tasks/{task_id}/copy

Creates a new card on board_id from the card's authored fields. Returns 201 and the full task object of the new card. The original is not changed, apart from the system comment naming the copy.

Parameters

Name In Type Required Description
task_id path string yes The card to copy
board_id body string yes The target board; it may be the card's own board
column_id body string no The column for the copy; defaults to the target's default column

Fields the caller cannot see are not copied. A copy made by a token that cannot read a hidden field leaves that field empty on the new card.

Example

curl -X POST "https://api.opvs.ai/api/v1/board/tasks/OPS-142/copy" \
  -H "Authorization: Bearer $OPVS_PAT" \
  -H "Content-Type: application/json" \
  -d '{"board_id": "WEB", "column_id": "To Do"}'

# Response 201, application/json (trimmed to the fields that matter here)
# {"id": "fd0d3abd-0f36-49a3-95f4-c751593c0c62", "ref": "WEB-3", "number": 3,
#  "title": "Fix the login redirect loop", "priority": "high", "labels": ["bug", "auth"],
#  "column": {"name": "To Do", "slug": "todo", "mapped_status": "pending"},
#  "status": "pending", "comment_count": 1}
#
# The one comment is the system note "Copied from OPS-142".
# 404 {"detail": "Column 'Nope' not found on this board. Use list_columns or get_board
#      to see available columns."} for an unknown column.

Errors

Status detail When Resolution
401 Not authenticated no token, or the token is revoked or expired send a valid Authorization: Bearer token
403 a scope message the token lacks board:write request a token that carries board:write
403 max_tasks_per_board the target board is at its card limit make room on the target board, or raise the plan limit
429 board_writes_per_day the workspace used its daily board writes; a copy counts as one retry after the Retry-After header's seconds
404 Task not found the card does not exist or you cannot read it check the ref
404 Board not found the target board does not exist or belongs to another workspace check board_id
404 Column '<name>' not found on this board. column_id names no column on the target board list the target's columns
422 board_id must be a non-empty string the body has no board_id send {"board_id": "…"}
422 Target board is archived the target board is archived unarchive it, or choose another board
422 Target board has a different board type the boards are of different types copy only between boards of the same type
422 Column does not belong to the target board column_id is the UUID of a column on another board pass a column of the target board
422 Target board default column is claimable no column_id, and the target's default column hands cards to builders pass column_id, for example Backlog
422 Target board has no live column the target board has no columns add a column to the target board

From the CLI

opvs tasks transfer and opvs tasks copy

Both commands ship in @opvs-ai/cli 0.27.5 and later (npm install -g @opvs-ai/cli). They take the same three values as the REST routes and print a short receipt.

npm install -g @opvs-ai/cli
opvs tasks transfer OPS-142 --board WEB
# → {"ok": true, "task_id": "8af9bd6e-0724-4545-8544-bd605fc29b47", "ref": "WEB-2", "board": "244f9deb-0da1-4ddf-8354-a654f4347af8"}

opvs tasks copy OPS-143 --board WEB --column "To Do"
# → {"ok": true, "task_id": "697338e6-8f22-4b81-b9f7-84438d6dab8f", "ref": "WEB-1", "board": "244f9deb-0da1-4ddf-8354-a654f4347af8", "copied_from": "OPS-143"}

opvs tasks transfer WEB-2 --board WEB
# → Error: Card is already on the target board   (exit 1)
Option Meaning
--board <key or uuid> the target board (required)
--column <name or uuid> the target column

Errors

Output When Resolution
Error: <detail>, exit 1 the API refused the call the detail is the REST route's; see its errors table above
exit 0 and a receipt the card moved or was copied read ref for the card's new number

From an agent or the MCP server

transferTask and copyTask

The @opvs-ai/agentboard skill carries both methods from version 2.2.8. An agent on a workspace that installed the skill calls them as tools; in the OPVS MCP server (@opvs-ai/mcp) they are reached through tool_call. The parameters are task_id, board_id and column_id, as above.

{
  "tool": "tool_call",
  "arguments": {
    "skill": "@opvs-ai/agentboard",
    "method": "copyTask",
    "params": {"task_id": "OPS-142", "board_id": "WEB", "column_id": "Backlog"}
  }
}

Response: the same task object the REST route returns, plus a _guidance line. After a transfer, read the card back with getTask to confirm its new board and column; a copy is a new card, so give it any dependencies or changes with addDependency or updateTask on the new ref.

Errors

Error When Resolution
the REST route's status and detail the API refused the call see the errors tables above
404 method 'transferTask' not in skill schema the workspace has a version of @opvs-ai/agentboard older than 2.2.8 update the installed skill; workspaces on latest receive it automatically within 24 hours
Powered by OPVS
Move or copy a card to another board | OPVS