codia-image-to-design
Runtime And Auth
Use the local codia-design CLI for this feature. Before calling the API, verify that codia-design is available. If it is missing and global npm installs are allowed, install it with npm install -g @codia-ai/codia-design-cli. Then check codia-design auth status; if it is not connected, run codia-design auth login --platform codex or bind an API key with codia-design auth set --api-key api_key_xxx. Never print API keys or ~/.codia/design-skills/config.json.
Convert UI screenshots into editable hierarchical design trees (VisualElement trees).
CLI Command
# Synchronous direct conversion
codia-design image-to-design --image <PATH|URL> [--out FILE]
# Asynchronous task submit
codia-design image-to-design --image <HTTPS_URL> --async [--callback URL] [--idempotency KEY] [--out task.json]
# Asynchronous task submit and poll
codia-design image-to-design --image <HTTPS_URL> --poll [--timeout 300000] [--out result.json]
Parameters
| Flag | Type | Required | Default | Description |
|---|---|---|---|---|
--image |
path | URL | yes | — | Local PNG/JPG/WebP path, or public HTTPS URL |
--async |
boolean | no | false | Create an image_to_design task and return task_id without waiting |
--poll |
boolean | no | false | Create an image_to_design task, poll /v2/open/tasks/:task_id, and return the completed design tree |
--timeout |
milliseconds | no | 300000 | Maximum wait time for --poll |
--callback |
URL | no | — | Optional task callback URL for async mode |
--idempotency |
string | no | — | Sends Idempotency-Key for async task creation |
--out |
path | no | stdout | Write JSON results to file (recommended for large responses) |
Sync vs Async Selection
Use synchronous POST /v2/open/image_to_design for one image, especially local files and images below 2K on the longest edge. It keeps the result in a single request and supports direct multipart upload for local files.
Use asynchronous POST /v2/open/tasks with operation: "image_to_design" for multiple images, images at 2K or above, or flows that need callback/idempotency/retry behavior. Submit one task per image. Task mode currently accepts input.image_url, so the CLI requires --image to be a public HTTPS URL in --async or --poll mode. For a local large image, upload it to user-owned storage/CDN first and pass that URL, or use synchronous mode if the expected runtime is acceptable.
Response
Synchronous mode and completed --poll mode return the design data. --poll also includes task metadata fields such as task_id, operation, status, and progress.
{
"ok": true,
"data": {
"configuration": {
"scalingFactor": 1.0,
"baseWidth": 375,
"measurementUnit": "px"
},
"visualElement": {
"elementId": "root_001",
"elementName": "Body",
"elementType": "Body",
"layoutConfig": { "positionMode": "Normal" },
"styleConfig": {
"widthSpec": { "sizing": "FIXED", "value": 375 },
"heightSpec": { "sizing": "FIXED", "value": 812 }
},
"contentData": null,
"processingMeta": { "detectionScore": 1.0, "surfaceArea": 304500 },
"childElements": []
}
}
}
configuration field
| Field | Type | Description |
|---|---|---|
scalingFactor |
number | All values must be multiplied by this factor to get the actual pixels |
baseWidth |
number | Canvas base width (375=mobile, 1440=desktop) |
measurementUnit |
string | "px" or "pt" |
VisualElement node structure
Every node (including the visualElement root node and all childElements) has the same schema:
| Field | Type | Description |
|---|---|---|
elementId |
string | Node ID (regenerated for each call, not stable across calls) |
elementName |
string | Human-readable tag name |
elementType |
string | Node type, see the table below |
layoutConfig |
object | Positioning information |
styleConfig |
object | visual style |
contentData |
object | null | Node content (only Text/Image has value) |
processingMeta |
object | Detection confidence and area |
childElements |
array | child nodes (recursive) |
elementType value
| elementType | has child nodes | contentData field | description |
|---|---|---|---|
Body |
yes | — | Root node, always exists |
Layer |
yes | — | Universal container (card, section, etc.) |
Group |
yes | — | Pure grouping, no self-visualization |
Text |
no | textValue: string |
Text leaf node |
Image |
no | imageSource: string |
Image (CDN URL) |
Vector |
no | vectorData |
Vector shape |
Component |
Varies | componentReference |
Detected UI component |
layoutConfig key fields
positionMode: "Flex" | "Absolute" | "Normal" | "Relative"
"Flex"— Participate in the flex layout of the parent node. The parent node’sflexAttributesdescribe the direction/alignment"Absolute"— absolute positioning, readabsoluteAttrs.coord.x/.yto get the offsetflexAttributes:{ flexDirection, alignItems, justifyContent, flexWrap }(on Flex container)
styleConfig key fields
| Field | Type | Description |
|---|---|---|
widthSpec / heightSpec |
{sizing, value} |
sizing: FIXED=exact px / FILL=fill parent / FIT_CONTENT=shrink |
textConfig |
object | fontSize, fontFamily, fontStyle, lineHeight, letterSpacing, textAlign |
textColor |
{rgbValues, hexCode} |
Text color |
borderConfig |
object | borderWidth, borderStyle, borderColor, borderRadius: [tl,tr,br,bl] |
backgroundConfig |
object | type: "COLOR" / "IMAGE" / "LINEAR_GRADIENT" + respective fields |
opacityLevel |
number | 0–255, divided by 255 to get CSS opacity |
paddingValues |
array | [top, right, bottom, left] |
Usage Example
# Synchronous local file, recommended for a single small image
codia-design image-to-design --image ./screenshot.png --out result.json
# Synchronous URL
codia-design image-to-design --image https://example.com/screen.png --out result.json
# Submit an async task for a large image and return task_id
codia-design image-to-design --image https://example.com/large-screen.png --async --out task.json
# Submit and wait for completion
codia-design image-to-design --image https://example.com/large-screen.png --poll --timeout 300000 --out result.json
Traverse the tree after reading the results (Node.js):
const { data } = require('./result.json');
const { scalingFactor } = data.configuration;
function walk(node, depth = 0) {
const pad = ' '.repeat(depth);
if (node.elementType === 'Text') {
console.log(pad + '[Text]', node.contentData?.textValue);
} else if (node.elementType === 'Image') {
console.log(pad + '[Image]', node.contentData?.imageSource);
} else {
console.log(pad + '[' + node.elementType + ']', node.elementName);
}
node.childElements?.forEach(c => walk(c, depth + 1));
}
walk(data.visualElement);
//Extract all text nodes
function extractText(node, results = []) {
if (node.elementType === 'Text') results.push(node.contentData?.textValue);
node.childElements?.forEach(c => extractText(c, results));
return results;
}
Low confidence node filtering (processingMeta.detectionScore < 0.5) is recommended for use in production code.
Input Limits
The maximum size and file size of input images depend on the plan level:
| Packages | Maximum resolution | Maximum file size |
|---|---|---|
| Free | 1440×1440 | 5 MB |
| Starter | 4096×4096 | 20 MB |
| Pro | 10000×10000 | 50 MB |
Errors & Billing
| HTTP | Meaning | Fix |
|---|---|---|
| 400 | The image URL is not accessible or the format is not supported | Confirm that the URL is publicly accessible and the format is PNG/JPG/WebP |
| 402 | Insufficient credits | codia-design credits Recharge after confirming the balance |
| 429 | Rate limit exceeded | Retry after backing off |
| 500 | Service internal error | Safe to try again |
Credits: 13 credits/request. After the command completes, the CLI checks available_credits and reminds the user if the remaining balance is below 26 credits (2x estimate); this does not block generation. Duration: synchronous mobile screenshots are usually < 10s, desktop intensive pages are longer. Prefer async task mode for large images, 2K+ images, and batches.