# Results

A completed conversion's files: download one, preview it, read its figures and shapes.

### Download a file of the result

`GET /v1/conversions/{id}/download`

A short-lived URL for one of the result's files: `format` names one of `result.formats` by id (absent, the web default). Served from the storage domain as an attachment, never inline from this origin: SVG is an active document format. Allowed once the conversion's IMAGE is unlocked, on every plan; then every format and re-download is free. A locked image answers 402 `unlock_required` (this GET never spends). `as` takes the format as a print-ready PDF (`pdf`, a design file's of outlines, never its `editableText` twin) or a picture (`png`, a web file's with a preview, `size` px on its long side). A design file of outlines also takes a maker's file: cut-ready (`cut`, each shape minus what is painted over it, for a cutting machine), a DXF (`dxf`, `units` mm or in, for a laser or a CNC), an EPS (`eps`, for a print shop). Each is made from the stored result on first ask, after the unlock check.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `format` | query | string | no | A format's id from `result.formats`; the web default when left out. |
| `as` | query | one of `svg`, `pdf`, `png`, `cut`, `dxf`, `eps`, `plot`, `plot-dxf` | no |  |
| `size` | query | one of `2048`, `4096`, `8192` | no | With `as=png`: the picture's long side in px. |
| `units` | query | one of `mm`, `in` | no | With `as=dxf` or `as=plot-dxf`: the drawing's units (a DXF R12 cannot name them: the file's name does). |
| `variant` | query | id | no | A revision of the result (POST /conversions/{id}/variants): the file under its edits and colors. A `currentColor` file takes its edits, never its colors (a recolor alone: 400 `format_unavailable`). |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/download \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "url": "https://files.vecsnap.com/…",
  "expiresIn": 1,
  "filename": "logo",
  "format": "example"
}
```

Answer 402:

```json
{
  "error": {
    "code": "unlock_required",
    "message": "This image is not unlocked yet: its files, its points and its reshaping edits wait for it.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 402 | `unlock_required` | Unlock it (1 credit, once per image), then send the same request again. |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `variant_not_found` | Use a variant id this result listed. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `file_not_makeable` (400), `format_unavailable` (400), `invalid_edits` (400), `invalid_id` (400), `invalid_request` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_required` (403), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### Preview the result

`GET /v1/conversions/{id}/preview`

A short-lived URL for a web file's rendered PNG, on EVERY tier: the free tier is the product demo, a full-quality conversion, this preview and its figures, with the SVG withheld. Served inline (a PNG is inert). `format` names a web file of `result.formats` that is not `currentColor` (its background kept or dropped); absent, the web default's. 2048 px on its long side, at the drawing's own aspect. `layer=outline`: the anchor-point view at the same size, lying exactly on it (black hairlines and squares on transparency). `layer=plot`: what a machine draws at the same size, in one ink; with `variant`, under its edits and colors, as its file downloads, with that drawing's figures in `plot`. `layer=cut`: the CUT-READY picture of the DESIGN file `format` names (a design file of outlines: what a cutter's blade follows), a revision's too.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `format` | query | string | no | A web file's id; the web default when left out. With `layer=cut`, a design file's id (of outlines), required. |
| `layer` | query | one of `outline`, `plot`, `cut` | no |  |
| `variant` | query | id | no | A revision of the result (POST /conversions/{id}/variants): the same, under its edits and colors (audit `editor-2026-10-27` § 19). |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/preview \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "url": "https://files.vecsnap.com/…",
  "expiresIn": 1,
  "plot": {
    "paths": 0,
    "closed": 0,
    "colours": 0,
    "tiny": 0
  }
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 429:

```json
{
  "error": {
    "code": "compute_limit_reached",
    "message": "Today's editing time for your account (or your guest address) is used: nothing was made.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `variant_not_found` | Use a variant id this result listed. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `file_not_makeable` (400), `format_unavailable` (400), `invalid_edits` (400), `invalid_id` (400), `invalid_request` (400), `layer_unavailable` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### Tiles of a deeper zoom

`POST /v1/conversions/{id}/tiles`

Every tier, like the preview: pictures of the file, never the SVG. Level L draws the drawing 2048·2^L px long, cut into 512-px squares (1 ≤ L ≤ 3); a tile is [x, y] within the square grid of its level. Missing tiles are made first, then served from storage. Several layers at once: POST /conversions/{id}/tiles/batch.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `layer` | body | string | yes | `outline` or `outline-2x` (the anchor-point view drawn for a 1× or 2× screen), `plot` (what a machine draws), a web file's id, or `ids-{format}` (that web file's Shapes ID picture, GET /conversions/{id}/shapes). |
| `level` | body | integer, 1 to 3 | yes |  |
| `tiles` | body | array of array of any | yes |  |
| `variant` | body | id, or null | no | A revision of the result: a web file's tiles, or its Shapes ID picture's, under its edits and colors (never the outline's). |
| `palette` | body | integer, 2 to 24, or null | no | A redraw's preview count (GET /conversions/{id}/palette): a web file's tiles with the drawing merged into its colors. Never with `variant`. |

```bash
curl -X POST https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/tiles \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"layer":"outline","level":1,"tiles":[[0,0]]}'
```

Answer 200:

```json
{
  "layer": "outline",
  "level": 0,
  "variant": "00000000-0000-4000-8000-000000000000",
  "palette": 0,
  "tiles": [
    {
      "x": 0,
      "y": 0,
      "url": "https://files.vecsnap.com/…"
    }
  ],
  "expiresIn": 1
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 429:

```json
{
  "error": {
    "code": "compute_limit_reached",
    "message": "Today's editing time for your account (or your guest address) is used: nothing was made.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `variant_not_found` | Use a variant id this result listed. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `original_not_kept` | Upload the file again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `invalid_edits` (400), `invalid_id` (400), `invalid_options` (400), `invalid_request` (400), `invalid_tiles` (400), `malformed_body` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### Tiles of several layers at once

`POST /v1/conversions/{id}/tiles/batch`

The tiles of every layer one view shows (the picture, its Shapes ID picture, the outline), in one request: each ask is POST /conversions/{id}/tiles's, answered in the same order. At most 24 tiles in all, of one revision (`variant`) and one preview count (`palette`) at most; ask another's apart; it succeeds or fails whole. One request at a time per account makes files: another meanwhile waits its turn (up to 15 s), then, or with 8 already waiting, is refused with 429 `derive_busy` (nothing done; ask again after Retry-After).

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `asks` | body | array of object | yes |  |

```bash
curl -X POST https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/tiles/batch \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"asks":[{"layer":"outline","level":1,"tiles":[[0,0]],"variant":"00000000-0000-4000-8000-000000000000","palette":2}]}'
```

Answer 200:

```json
{
  "asks": [
    {
      "layer": "outline",
      "level": 0,
      "variant": "00000000-0000-4000-8000-000000000000",
      "palette": 0,
      "tiles": [
        {
          "x": 0,
          "y": 0,
          "url": "https://files.vecsnap.com/…"
        }
      ]
    }
  ],
  "expiresIn": 1
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 429:

```json
{
  "error": {
    "code": "compute_limit_reached",
    "message": "Today's editing time for your account (or your guest address) is used: nothing was made.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `variant_not_found` | Use a variant id this result listed. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `original_not_kept` | Upload the file again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `invalid_edits` (400), `invalid_id` (400), `invalid_options` (400), `invalid_request` (400), `invalid_tiles` (400), `malformed_body` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### The original image

`GET /v1/conversions/{id}/original`

A short-lived URL for the image the conversion was made from: the upload, kept with its result for the comparison (deleted with the result or the account, never in the shared cache). While it waits or runs, the upload itself, so a client can show the image being converted. Served inline, as the type its bytes proved at upload; an upload no page shows as itself (a TIFF, an SVG) is answered as its PICTURE, a PNG the engine drew of it, never the file. A result made before originals were kept, or a running conversion whose upload is gone, has none: 404 `original_unavailable`.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/original \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "url": "https://files.vecsnap.com/…",
  "expiresIn": 1
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 429:

```json
{
  "error": {
    "code": "compute_limit_reached",
    "message": "Today's editing time for your account (or your guest address) is used: nothing was made.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `original_unavailable` | Show its redraw instead. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `invalid_id` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### What an uploaded SVG was

`GET /v1/conversions/{id}/original/facts`

Every tier, an SVG upload's only, either tool: its anchor points, its size and its colors as the engine read them, and a short-lived link to its points as data. Written at conversion: an upload of another format, one the engine's SVG reader cannot read, or a result made before these existed has none: 404 `not_found`.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/original/facts \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "anchorPoints": 32,
  "fileSize": 652,
  "colors": 0,
  "points": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 1
  }
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |

Every other refusal it may answer: `invalid_id` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### The result's facts

`GET /v1/conversions/{id}/facts`

Every tier: the engine's facts of the default file, in the ENGINE's names (the same object the site's examples show): the counts a layers panel would sum (anchor points, paths, circles, rectangles, rings, strokes, repeats, elements, the words kept as text) and every color the file draws with what it paints and its share of the frame. `lane`: whether the upload looks like what VecSnap is built for (`in`: logos, icons, illustrations) or like a photograph (`photo`), read by the engine before converting; null when not read (a result converted before it). `lineArt`: whether the drawing is made of lines, so a single-line version may suit it. `plot`: a single-line version's figures for a machine.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/facts \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "summary": {
    "anchor_points": 0,
    "circles": 0,
    "rects": 0,
    "rings": 0,
    "paths": 0,
    "strokes": 0,
    "uses": 0,
    "definitions": 0,
    "elements": 0,
    "words": [
      "example"
    ],
    "colors": 0,
    "gradients": 0
  },
  "colors": [
    {
      "key": "#1f6feb",
      "roles": [
        "fill"
      ],
      "area": 0
    }
  ],
  "ground": "#1f6feb",
  "lane": "in",
  "lineArt": false,
  "plot": {
    "paths": 0,
    "closed": 0,
    "colours": 0,
    "tiny": 0
  }
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 429:

```json
{
  "error": {
    "code": "compute_limit_reached",
    "message": "Today's editing time for your account (or your guest address) is used: nothing was made.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `invalid_id` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### What a Clean did

`GET /v1/conversions/{id}/cleaned`

Every tier, a Clean's only (`tool: clean`): the upload's anchor points and the result's, the upload's size, the distance every outline was kept within, and each step that acted, by its setting's name (`cleanOptions`). A Redraw has none: 404 `not_found`.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/cleaned \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "anchorPoints": {
    "before": 0,
    "after": 0
  },
  "fileSize": {
    "before": 0
  },
  "maxMove": 0,
  "steps": {
    "maxMove": 1,
    "background": 1,
    "circles": 1,
    "rectangles": 1,
    "fewerPoints": 1,
    "joinColors": 1,
    "specks": 1,
    "hiddenShapes": 1,
    "maxColors": 1,
    "everyOutline": 1
  },
  "colors": {
    "before": 0,
    "after": 0
  }
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |

Every other refusal it may answer: `invalid_id` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### The result's shapes

`GET /v1/conversions/{id}/shapes`

Every tier, like the preview: a web file's shapes in the engine's order, and a link to its ID PICTURE at the preview's size: every pixel's color − 1 is the shape on top there, transparent where none is, never a blended pixel. Decode it with color conversion and premultiplying off. Its deeper zoom: POST /conversions/{id}/tiles with the layer `ids-{format}`. The default web file's is made with the conversion; another's on the first ask; then served.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `format` | query | string | no | A web file's id; the default web file when left out. |
| `variant` | query | id | no | A revision of the result (POST /conversions/{id}/variants): the same, under its edits and colors (audit `editor-2026-10-27` § 19). |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/shapes \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "format": "example",
  "width": 1,
  "height": 1,
  "rows": [
    {
      "index": 0,
      "shape": 0,
      "drawn": false,
      "kind": "example",
      "ground": false,
      "points": 0,
      "paint": "#1f6feb",
      "box": [
        0,
        0,
        0,
        0
      ],
      "neighbors": [
        0
      ],
      "tidy": "example"
    }
  ],
  "alike": [
    {
      "from": "#1f6feb",
      "into": "#1f6feb",
      "colors": {}
    }
  ],
  "picture": "https://files.vecsnap.com/…",
  "expiresIn": 1
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 429:

```json
{
  "error": {
    "code": "compute_limit_reached",
    "message": "Today's editing time for your account (or your guest address) is used: nothing was made.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `variant_not_found` | Use a variant id this result listed. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `format_unavailable` (400), `invalid_edits` (400), `invalid_id` (400), `invalid_request` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### Lift a shape

`GET /v1/conversions/{id}/lift`

Every tier, like the preview: two short-lived URLs to MOVE a shape on screen before the move is saved. `without` is the web file without the shape (its preview with one hide more, never saved), `alone` the shape alone, every other one hidden and drawn whole where another covered it; both 2048 px on the long side, lying exactly on the preview. `shape` is its number in a revision's edits (the Shapes table's `shape`); the ground can only be hidden, never lifted. Moving it is then ONE `place` edit (POST /conversions/{id}/variants).

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `shape` | query | integer | yes | The shape, by its number in a revision's edits (the Shapes table's `shape`). |
| `format` | query | string | no | A web file's id; the web default when left out. |
| `variant` | query | id | no | A revision of the result: the shape under its edits and colors. |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/lift \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "without": "https://files.vecsnap.com/…",
  "alone": "https://files.vecsnap.com/…",
  "expiresIn": 1
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 429:

```json
{
  "error": {
    "code": "compute_limit_reached",
    "message": "Today's editing time for your account (or your guest address) is used: nothing was made.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `variant_not_found` | Use a variant id this result listed. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `format_unavailable` (400), `invalid_edits` (400), `invalid_id` (400), `invalid_request` (400), `shape_unavailable` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### Read a shape's anchors

`GET /v1/conversions/{id}/anchors`

Once the image is UNLOCKED (402 `unlock_required` before: the anchors are the file's geometry): a shape's anchor points as data, numbered exactly as the anchor edits name them (`point`, `corner`, `add_point`, `delete_point`, `fillet`, saved by POST /conversions/{id}/variants), on the shape as the revision edits it. `x` and `y` are in the file's own units (the Shapes table's). `reach` is the largest `fillet` radius that fits there (`reachExact`: every radius up to it fits, between two straight sides); `segment` the one leaving the anchor (`add_point`'s `at` is a place on it; an arc takes none). A shape no anchor edit addresses answers an empty list.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `shape` | query | integer | yes | The shape, by its number in a revision's edits (the Shapes table's `shape`). |
| `format` | query | string | no | A web file's id; the web default when left out. |
| `variant` | query | id | no | A revision of the result: the shape under its edits. |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/anchors \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "anchors": [
    {
      "point": 0,
      "x": 0,
      "y": 0,
      "corner": false,
      "smooth": false,
      "reach": 0,
      "reachExact": false,
      "segment": "line",
      "openEnd": false
    }
  ]
}
```

Answer 402:

```json
{
  "error": {
    "code": "unlock_required",
    "message": "This image is not unlocked yet: its files, its points and its reshaping edits wait for it.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 402 | `unlock_required` | Unlock it (1 credit, once per image), then send the same request again. |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `variant_not_found` | Use a variant id this result listed. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `format_unavailable` (400), `invalid_edits` (400), `invalid_id` (400), `invalid_request` (400), `shape_unavailable` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### Try edits

`GET /v1/conversions/{id}/try`

Every tier, like the preview: a short-lived URL to the web file's preview with EDITS after a revision's own (or the result's), NEVER saved: what a press would draw before it is pressed. `edits` is a JSON list of 1 to 8 edits, in a revision's numbering and vocabulary (POST /conversions/{id}/variants); saving the same edits later draws from the same picture. Counted on its own budget, apart from what saving needs. An edit only the engine draws (simplify, round, point, corner, add_point, delete_point, fillet, merge, subtract, intersect, exclude, offset, outline) is tried once the image is unlocked (402 `unlock_required` before).

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `edits` | query | string | yes | The edits tried, a JSON list (1 to 8). |
| `format` | query | string | no | A web file's id; the web default when left out. |
| `variant` | query | id | no | A revision of the result: the edits tried after its own, under its colors. |

```bash
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/try \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "url": "https://files.vecsnap.com/…",
  "expiresIn": 1
}
```

Answer 402:

```json
{
  "error": {
    "code": "unlock_required",
    "message": "This image is not unlocked yet: its files, its points and its reshaping edits wait for it.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 404:

```json
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 409:

```json
{
  "error": {
    "code": "conversion_failed",
    "message": "The conversion ended without a result.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 402 | `unlock_required` | Unlock it (1 credit, once per image), then send the same request again. |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 404 | `variant_not_found` | Use a variant id this result listed. |
| 409 | `conversion_failed` | Convert the image again. Converting is free. |
| 409 | `not_in_test_mode` | Use a live key for it, or test the conversion and its SVG files. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `result_outdated` | Convert the image again. |
| 429 | `compute_limit_reached` | Come back after Retry-After (UTC midnight). |
| 429 | `derive_busy` | Nothing was done. Send it again in a moment (Retry-After). |
| 429 | `editing_capacity_reached` | Come back after Retry-After (UTC midnight), or take a plan: a customer's editing is its own. |
| 429 | `try_limit_reached` | Apply the edit without its preview, or come back after Retry-After (UTC midnight). |
| 502 | `derive_failed` | Try again. The coarser picture still shows. |

Every other refusal it may answer: `format_unavailable` (400), `invalid_edits` (400), `invalid_id` (400), `invalid_request` (400), `invalid_api_key` (401), `unauthenticated` (401), `account_stopped` (403), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

---
This page: https://vecsnap.com/docs/api/results
