---
title: "Move any item"
method: POST
path: "/api/boards/{boardId}/{kind}/{itemId}/move"
tags: ["Items"]
---

# Move any item

`POST /api/boards/{boardId}/{kind}/{itemId}/move`

## Request

- Base URL: `https://cnvs.app`
- URL: `https://cnvs.app/api/boards/{boardId}/{kind}/{itemId}/move`
- Auth: none declared

Unified move endpoint — works for every item kind. For `texts` / `links` / `images` the top-left lands at (x, y); for `strokes` the whole point array is translated so the bbox top-left sits at (x, y) (no need to re-send the point list). The creator's `author` tag is preserved (immutable after creation) so a move by a collaborator does NOT relabel who originally authored the item.

## Request body

- MoveTextRequest
  - `x` number, required
  - `y` number, required
  - `author` string: Author tag, charset `[A-Za-z0-9:_\-.]`, max 80 chars. Defaults to `ai:rest` for REST mutations. Use `ai:<your-label>` (e.g. `ai:claude`, `ai:mybot`) so humans can tell AI edits apart.

## Response `200`

Moved.

- object
  - `id` string
  - `x` number
  - `y` number

## Other responses

- `400`: Invalid input (missing or malformed board id).
- `401`: Board is access-locked and the request did not carry a valid key. `lockMode` tells the client whether to prompt for a code or just disable write UI.
- `404`: Board does not exist or was deleted within the 30-day tombstone window.
- `413`: Per-board quota exceeded (too many texts, images, strokes, or total image bytes). Response body names the specific limit that was hit.
- `429`: Rate limit exceeded. Standard REST/MCP: 60 requests/10s/board; valid X-Import-Token infrastructure tier: 600/10s/board; browser WebSocket always 60/10s/board. REST/MCP enforcement is soft per-isolate; WebSocket enforcement is strong per Durable Object.

---

[API](https://skmtc.dev/cnvs/apis/cnvs-app-http-api.md) · [All operations](https://skmtc.dev/cnvs/apis/cnvs-app-http-api/llms.txt) · [OpenAPI document](https://skmtc.dev/cnvs/apis/cnvs-app-http-api/revisions/c8f2c3b7ff90?raw)
