---
title: "Paste an image onto the board"
method: POST
path: "/api/boards/{boardId}/images"
tags: ["Items"]
---

# Paste an image onto the board

`POST /api/boards/{boardId}/images`

## Request

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

Mirrors the MCP `add_image` tool. `dataUrl` must be a `data:image/(png|jpeg|gif|webp|svg+xml);base64,...` string, ≤ ~900 kB. Hosted URLs are NOT accepted — if you have a URL, fetch the bytes yourself and re-encode as a data URL. Strongly recommended: also pass `thumbDataUrl` (≤8 kB, ~64 px) — it gets embedded into SVG previews so other AI viewers see an actual image instead of a placeholder box.

Example (upload a 1×1 PNG):
```
curl -X POST https://cnvs.app/api/boards/<id>/images \
  -H 'Content-Type: application/json' \
  -d '{"x":200,"y":300,"width":80,"height":80,"dataUrl":"data:image/png;base64,iVBORw0KGgo..."}'
```
For a hosted image, convert first:
```
BASE64=$(curl -sL https://example.com/pic.png | base64)
curl -X POST https://cnvs.app/api/boards/<id>/images \
  -H 'Content-Type: application/json' \
  -d "{\"x\":200,\"y\":300,\"width\":400,\"height\":300,\"dataUrl\":\"data:image/png;base64,$BASE64\"}"
```

## Request body

- AddImageRequest
  - `id` string
  - `x` number, required
  - `y` number, required
  - `width` number, required: Displayed width in board px.
  - `height` number, required: Displayed height in board px.
  - `dataUrl` string, required: Data URL: `data:image/(png|jpeg|gif|webp|svg+xml);base64,<payload>`. Max ~900 kB total. Hosted URLs NOT accepted — fetch + base64-encode first.
  - `thumbDataUrl` string, nullable: Optional tiny thumbnail (≤8 kB JPEG/PNG/WebP, ~64 px on long edge). Embedded into SVG previews so other AI viewers see the image instead of a placeholder.
  - `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`

Image placed.

- object
  - `id` string
  - `x` number
  - `y` number
  - `width` number
  - `height` number
  - `hasThumbDataUrl` boolean: Whether a thumbnail was stored alongside the full image. Governs whether `/svg-preview` inlines the image or shows a placeholder.
  - `author` string

## Other responses

- `400`: Bad data URL, too large, or invalid dimensions.
- `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)
