# Images

Your library: every conversion of the same image is a version of one image.

### List images

`GET /v1/images`

The caller's library, one entry per image, a page at a time: an image's versions are never cut at a page's edge. Pass a page's `nextCursor` back as `cursor`. `deleted=true` lists Recently deleted (newest deletion first).

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `filter` | query | one of `all`, `unlocked`, `not_downloaded`, `failed` | no |  |
| `sort` | query | one of `newest`, `oldest`, `name` | no |  |
| `q` | query | string | no | A substring of the name, any case. |
| `deleted` | query | one of `true`, `false` | no |  |
| `limit` | query | integer, 1 to 100 | no |  |
| `cursor` | query | string | no | A page's `nextCursor`. |

```bash
curl https://api.vecsnap.com/v1/images \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
```

Answer 200:

```json
{
  "object": "list",
  "data": [
    {
      "object": "image",
      "id": "00000000-0000-4000-8000-000000000000",
      "name": "Brand colors",
      "renamed": false,
      "createdAt": "2026-10-24T12:00:00.000Z",
      "deletedAt": "2026-10-24T12:00:00.000Z",
      "erasedAfter": "2026-10-24T12:00:00.000Z",
      "lastConvertedAt": "2026-10-24T12:00:00.000Z",
      "state": "converting",
      "versions": 1,
      "unlocked": true,
      "latest": {
        "object": "conversion",
        "id": "00000000-0000-4000-8000-000000000000",
        "livemode": false,
        "status": "completed",
        "phase": null,
        "preset": "default",
        "options": {},
        "imageId": "00000000-0000-4000-8000-000000000001",
        "filename": "logo",
        "inputFormat": null,
        "unlocked": true,
        "allowance": "credit",
        "engineVersion": "sample-27a924dbb20e",
        "result": {
          "anchorPoints": 29,
          "fileSize": 550,
          "formats": [
            {
              "background": "dropped",
              "bytes": 550,
              "currentColor": false,
              "default": true,
              "editableText": false,
              "id": "web",
              "profile": "web"
            },
            {
              "background": "kept",
              "bytes": 600,
              "currentColor": false,
              "default": false,
              "editableText": false,
              "id": "web-background",
              "profile": "web"
            },
            {
              "background": "dropped",
              "bytes": 759,
              "currentColor": false,
              "default": true,
              "editableText": false,
              "id": "design",
              "profile": "design"
            },
            {
              "background": "kept",
              "bytes": 823,
              "currentColor": false,
              "default": false,
              "editableText": false,
              "id": "design-background",
              "profile": "design"
            }
          ]
        },
        "failure": null,
        "inputDeletedAt": null,
        "createdAt": "2026-10-24T12:00:00.000Z",
        "updatedAt": "2026-10-24T12:00:00.000Z"
      },
      "picture": {
        "url": "https://files.vecsnap.com/…",
        "expiresIn": 0,
        "of": "result"
      },
      "original": {
        "url": "https://files.vecsnap.com/…",
        "expiresIn": 0,
        "of": "result"
      },
      "newerEngine": false
    }
  ],
  "hasMore": false,
  "nextCursor": null,
  "counts": {
    "all": 0,
    "unlocked": 0,
    "notDownloaded": 0,
    "failed": 0,
    "deleted": 0
  }
}
```

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

### Retrieve an image

`GET /v1/images/{id}`

One image, with every live version newest first.

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

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

Answer 200:

```json
{
  "object": "image",
  "id": "00000000-0000-4000-8000-000000000000",
  "name": "Brand colors",
  "renamed": false,
  "createdAt": "2026-10-24T12:00:00.000Z",
  "deletedAt": "2026-10-24T12:00:00.000Z",
  "erasedAfter": "2026-10-24T12:00:00.000Z",
  "lastConvertedAt": "2026-10-24T12:00:00.000Z",
  "state": "converting",
  "versions": 1,
  "unlocked": true,
  "latest": {
    "object": "conversion",
    "id": "00000000-0000-4000-8000-000000000000",
    "livemode": false,
    "status": "completed",
    "phase": null,
    "preset": "default",
    "options": {},
    "imageId": "00000000-0000-4000-8000-000000000001",
    "filename": "logo",
    "inputFormat": null,
    "unlocked": true,
    "allowance": "credit",
    "engineVersion": "sample-27a924dbb20e",
    "result": {
      "anchorPoints": 29,
      "fileSize": 550,
      "formats": [
        {
          "background": "dropped",
          "bytes": 550,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "web",
          "profile": "web"
        },
        {
          "background": "kept",
          "bytes": 600,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "web-background",
          "profile": "web"
        },
        {
          "background": "dropped",
          "bytes": 759,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "design",
          "profile": "design"
        },
        {
          "background": "kept",
          "bytes": 823,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "design-background",
          "profile": "design"
        }
      ]
    },
    "failure": null,
    "inputDeletedAt": null,
    "createdAt": "2026-10-24T12:00:00.000Z",
    "updatedAt": "2026-10-24T12:00:00.000Z"
  },
  "picture": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 0,
    "of": "result"
  },
  "original": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 0,
    "of": "result"
  },
  "newerEngine": false,
  "conversions": [
    {
      "object": "conversion",
      "id": "00000000-0000-4000-8000-000000000000",
      "livemode": false,
      "status": "completed",
      "phase": null,
      "preset": "default",
      "options": {
        "maxColors": 2
      },
      "imageId": "00000000-0000-4000-8000-000000000000",
      "filename": "logo",
      "inputFormat": "png",
      "unlocked": true,
      "allowance": "credit",
      "engineVersion": "1.284.0",
      "result": {
        "anchorPoints": 29,
        "fileSize": 550,
        "formats": [
          {
            "id": "example",
            "profile": "web",
            "background": "kept",
            "currentColor": false,
            "editableText": false,
            "bytes": 0,
            "default": false
          }
        ]
      },
      "failure": null,
      "inputDeletedAt": null,
      "createdAt": "2026-10-24T12:00:00.000Z",
      "updatedAt": "2026-10-24T12:00:00.000Z",
      "picture": {
        "url": "https://files.vecsnap.com/…",
        "expiresIn": 0,
        "of": "result"
      }
    }
  ]
}
```

Answer 404:

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

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |

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

### Name an image

`PATCH /v1/images/{id}`

The person's name for it, cleaned to a printable label; `null` or a blank gives back its file's name. Its files download under it.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `name` | body | string, or null | yes | The name, or null to give back the file's. |

```bash
curl -X PATCH https://api.vecsnap.com/v1/images/00000000-0000-4000-8000-000000000000 \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Brand colors"}'
```

Answer 200:

```json
{
  "object": "image",
  "id": "00000000-0000-4000-8000-000000000000",
  "name": "Brand colors",
  "renamed": false,
  "createdAt": "2026-10-24T12:00:00.000Z",
  "deletedAt": "2026-10-24T12:00:00.000Z",
  "erasedAfter": "2026-10-24T12:00:00.000Z",
  "lastConvertedAt": "2026-10-24T12:00:00.000Z",
  "state": "converting",
  "versions": 1,
  "unlocked": true,
  "latest": {
    "object": "conversion",
    "id": "00000000-0000-4000-8000-000000000000",
    "livemode": false,
    "status": "completed",
    "phase": null,
    "preset": "default",
    "options": {},
    "imageId": "00000000-0000-4000-8000-000000000001",
    "filename": "logo",
    "inputFormat": null,
    "unlocked": true,
    "allowance": "credit",
    "engineVersion": "sample-27a924dbb20e",
    "result": {
      "anchorPoints": 29,
      "fileSize": 550,
      "formats": [
        {
          "background": "dropped",
          "bytes": 550,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "web",
          "profile": "web"
        },
        {
          "background": "kept",
          "bytes": 600,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "web-background",
          "profile": "web"
        },
        {
          "background": "dropped",
          "bytes": 759,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "design",
          "profile": "design"
        },
        {
          "background": "kept",
          "bytes": 823,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "design-background",
          "profile": "design"
        }
      ]
    },
    "failure": null,
    "inputDeletedAt": null,
    "createdAt": "2026-10-24T12:00:00.000Z",
    "updatedAt": "2026-10-24T12:00:00.000Z"
  },
  "picture": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 0,
    "of": "result"
  },
  "original": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 0,
    "of": "result"
  },
  "newerEngine": false,
  "conversions": [
    {
      "object": "conversion",
      "id": "00000000-0000-4000-8000-000000000000",
      "livemode": false,
      "status": "completed",
      "phase": null,
      "preset": "default",
      "options": {
        "maxColors": 2
      },
      "imageId": "00000000-0000-4000-8000-000000000000",
      "filename": "logo",
      "inputFormat": "png",
      "unlocked": true,
      "allowance": "credit",
      "engineVersion": "1.284.0",
      "result": {
        "anchorPoints": 29,
        "fileSize": 550,
        "formats": [
          {
            "id": "example",
            "profile": "web",
            "background": "kept",
            "currentColor": false,
            "editableText": false,
            "bytes": 0,
            "default": false
          }
        ]
      },
      "failure": null,
      "inputDeletedAt": null,
      "createdAt": "2026-10-24T12:00:00.000Z",
      "updatedAt": "2026-10-24T12:00:00.000Z",
      "picture": {
        "url": "https://files.vecsnap.com/…",
        "expiresIn": 0,
        "of": "result"
      }
    }
  ]
}
```

Answer 404:

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

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |

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

### Delete an image

`DELETE /v1/images/{id}`

Into Recently deleted, restorable for 30 days (POST /images/{id}/restore); then every version and its files are erased. Converting the same bytes again brings it back. Its unlock, if paid, is never lost.

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

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

Answer 200:

```json
{
  "object": "image",
  "id": "00000000-0000-4000-8000-000000000000",
  "name": "Brand colors",
  "renamed": false,
  "createdAt": "2026-10-24T12:00:00.000Z",
  "deletedAt": "2026-10-24T12:00:00.000Z",
  "erasedAfter": "2026-10-24T12:00:00.000Z",
  "lastConvertedAt": "2026-10-24T12:00:00.000Z",
  "state": "converting",
  "versions": 1,
  "unlocked": true,
  "latest": {
    "object": "conversion",
    "id": "00000000-0000-4000-8000-000000000000",
    "livemode": false,
    "status": "completed",
    "phase": null,
    "preset": "default",
    "options": {},
    "imageId": "00000000-0000-4000-8000-000000000001",
    "filename": "logo",
    "inputFormat": null,
    "unlocked": true,
    "allowance": "credit",
    "engineVersion": "sample-27a924dbb20e",
    "result": {
      "anchorPoints": 29,
      "fileSize": 550,
      "formats": [
        {
          "background": "dropped",
          "bytes": 550,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "web",
          "profile": "web"
        },
        {
          "background": "kept",
          "bytes": 600,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "web-background",
          "profile": "web"
        },
        {
          "background": "dropped",
          "bytes": 759,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "design",
          "profile": "design"
        },
        {
          "background": "kept",
          "bytes": 823,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "design-background",
          "profile": "design"
        }
      ]
    },
    "failure": null,
    "inputDeletedAt": null,
    "createdAt": "2026-10-24T12:00:00.000Z",
    "updatedAt": "2026-10-24T12:00:00.000Z"
  },
  "picture": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 0,
    "of": "result"
  },
  "original": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 0,
    "of": "result"
  },
  "newerEngine": false,
  "conversions": [
    {
      "object": "conversion",
      "id": "00000000-0000-4000-8000-000000000000",
      "livemode": false,
      "status": "completed",
      "phase": null,
      "preset": "default",
      "options": {
        "maxColors": 2
      },
      "imageId": "00000000-0000-4000-8000-000000000000",
      "filename": "logo",
      "inputFormat": "png",
      "unlocked": true,
      "allowance": "credit",
      "engineVersion": "1.284.0",
      "result": {
        "anchorPoints": 29,
        "fileSize": 550,
        "formats": [
          {
            "id": "example",
            "profile": "web",
            "background": "kept",
            "currentColor": false,
            "editableText": false,
            "bytes": 0,
            "default": false
          }
        ]
      },
      "failure": null,
      "inputDeletedAt": null,
      "createdAt": "2026-10-24T12:00:00.000Z",
      "updatedAt": "2026-10-24T12:00:00.000Z",
      "picture": {
        "url": "https://files.vecsnap.com/…",
        "expiresIn": 0,
        "of": "result"
      }
    }
  ]
}
```

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_running",
    "message": "The image is still converting.",
    "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_running` | Wait for it to finish, then try again. |

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

### Restore an image

`POST /v1/images/{id}/restore`

Back from Recently deleted, every version with it.

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

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

Answer 200:

```json
{
  "object": "image",
  "id": "00000000-0000-4000-8000-000000000000",
  "name": "Brand colors",
  "renamed": false,
  "createdAt": "2026-10-24T12:00:00.000Z",
  "deletedAt": "2026-10-24T12:00:00.000Z",
  "erasedAfter": "2026-10-24T12:00:00.000Z",
  "lastConvertedAt": "2026-10-24T12:00:00.000Z",
  "state": "converting",
  "versions": 1,
  "unlocked": true,
  "latest": {
    "object": "conversion",
    "id": "00000000-0000-4000-8000-000000000000",
    "livemode": false,
    "status": "completed",
    "phase": null,
    "preset": "default",
    "options": {},
    "imageId": "00000000-0000-4000-8000-000000000001",
    "filename": "logo",
    "inputFormat": null,
    "unlocked": true,
    "allowance": "credit",
    "engineVersion": "sample-27a924dbb20e",
    "result": {
      "anchorPoints": 29,
      "fileSize": 550,
      "formats": [
        {
          "background": "dropped",
          "bytes": 550,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "web",
          "profile": "web"
        },
        {
          "background": "kept",
          "bytes": 600,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "web-background",
          "profile": "web"
        },
        {
          "background": "dropped",
          "bytes": 759,
          "currentColor": false,
          "default": true,
          "editableText": false,
          "id": "design",
          "profile": "design"
        },
        {
          "background": "kept",
          "bytes": 823,
          "currentColor": false,
          "default": false,
          "editableText": false,
          "id": "design-background",
          "profile": "design"
        }
      ]
    },
    "failure": null,
    "inputDeletedAt": null,
    "createdAt": "2026-10-24T12:00:00.000Z",
    "updatedAt": "2026-10-24T12:00:00.000Z"
  },
  "picture": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 0,
    "of": "result"
  },
  "original": {
    "url": "https://files.vecsnap.com/…",
    "expiresIn": 0,
    "of": "result"
  },
  "newerEngine": false,
  "conversions": [
    {
      "object": "conversion",
      "id": "00000000-0000-4000-8000-000000000000",
      "livemode": false,
      "status": "completed",
      "phase": null,
      "preset": "default",
      "options": {
        "maxColors": 2
      },
      "imageId": "00000000-0000-4000-8000-000000000000",
      "filename": "logo",
      "inputFormat": "png",
      "unlocked": true,
      "allowance": "credit",
      "engineVersion": "1.284.0",
      "result": {
        "anchorPoints": 29,
        "fileSize": 550,
        "formats": [
          {
            "id": "example",
            "profile": "web",
            "background": "kept",
            "currentColor": false,
            "editableText": false,
            "bytes": 0,
            "default": false
          }
        ]
      },
      "failure": null,
      "inputDeletedAt": null,
      "createdAt": "2026-10-24T12:00:00.000Z",
      "updatedAt": "2026-10-24T12:00:00.000Z",
      "picture": {
        "url": "https://files.vecsnap.com/…",
        "expiresIn": 0,
        "of": "result"
      }
    }
  ]
}
```

Answer 404:

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

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |

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

### Erase an image now

`POST /v1/images/{id}/erase`

Before its 30 days: its versions are erased and their files deleted; it cannot be restored after. Only from Recently deleted: an image in the library is 409 `not_deleted` (delete it first).

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

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

Answer 200:

```json
{
  "erased": 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": "not_deleted",
    "message": "The image is not in Recently deleted.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 409 | `not_deleted` | Delete it first, or leave it. |

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

### Convert an image again

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

A new version of the image with today's engine, from the bytes it was made from: the API copies them (its result's kept original, else a version's upload while kept), so nothing is uploaded again. Every rule of POST /conversions applies: free (an unlocked image's re-runs always are), counted by the daily caps. `options` absent keeps the newest version's; `{"maxColors": N}` redraws it with at most N colors (GET /conversions/{id}/palette previews it first). 409 `original_not_kept` when the image's file is no longer kept: upload it again.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `id` | path | id | yes |  |
| `Retry-After` | header | string | no | On a 429 (`free_limit_reached`, or every free conversion together reaching today's shared capacity of 2000): seconds until the caps renew, the next UTC midnight. On a 409 `too_many_active_jobs` (guest 1, free 1, paid 5 at once): wait for one to end, or send `queue: true`. |
| `idempotencyKey` | body | string | yes |  |
| `options` | body | object | no | Optional choices about this image beside its preset. `{}` for none. Two conversions share a cached result only with the same options. Not offered yet: `merge` (a redraw that merges two colors is not offered yet; merge them in the Colors tab, or ask for fewer colors). |

```bash
curl -X POST https://api.vecsnap.com/v1/images/00000000-0000-4000-8000-000000000000/conversions \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"idempotencyKey":"order-1042-logo"}'
```

Answer 200:

```json
{
  "object": "conversion",
  "id": "00000000-0000-4000-8000-000000000000",
  "livemode": false,
  "status": "completed",
  "phase": null,
  "preset": "default",
  "options": {
    "maxColors": 2
  },
  "imageId": "00000000-0000-4000-8000-000000000000",
  "filename": "logo",
  "inputFormat": "png",
  "unlocked": true,
  "allowance": "credit",
  "engineVersion": "1.284.0",
  "result": {
    "anchorPoints": 29,
    "fileSize": 550,
    "formats": [
      {
        "id": "example",
        "profile": "web",
        "background": "kept",
        "currentColor": false,
        "editableText": false,
        "bytes": 0,
        "default": false
      }
    ]
  },
  "failure": null,
  "inputDeletedAt": null,
  "createdAt": "2026-10-24T12:00:00.000Z",
  "updatedAt": "2026-10-24T12:00:00.000Z",
  "cacheHit": false
}
```

Answer 201:

```json
{
  "object": "conversion",
  "id": "00000000-0000-4000-8000-000000000000",
  "livemode": false,
  "status": "completed",
  "phase": null,
  "preset": "default",
  "options": {
    "maxColors": 2
  },
  "imageId": "00000000-0000-4000-8000-000000000000",
  "filename": "logo",
  "inputFormat": "png",
  "unlocked": true,
  "allowance": "credit",
  "engineVersion": "1.284.0",
  "result": {
    "anchorPoints": 29,
    "fileSize": 550,
    "formats": [
      {
        "id": "example",
        "profile": "web",
        "background": "kept",
        "currentColor": false,
        "editableText": false,
        "bytes": 0,
        "default": false
      }
    ]
  },
  "failure": null,
  "inputDeletedAt": null,
  "createdAt": "2026-10-24T12:00:00.000Z",
  "updatedAt": "2026-10-24T12:00:00.000Z",
  "cacheHit": false
}
```

Answer 402:

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "There are not enough credits for this unlock. None was spent.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

Answer 403:

```json
{
  "error": {
    "code": "account_required",
    "message": "Trying without an account does not include this.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 402 | `insufficient_credits` | Buy credits, then send the same request again. |
| 403 | `account_required` | Sign in or create an account. The conversions come with you. |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 409 | `idempotency_key_reused` | Make a new key for a new request. |
| 409 | `original_not_kept` | Upload the file again. |
| 409 | `too_many_active_jobs` | Wait for one to finish, or send queue: true to wait in line. |
| 409 | `unlock_pending` | Wait for that conversion to finish. |
| 429 | `free_capacity_reached` | Come back after Retry-After (UTC midnight), or unlock with a credit. |
| 429 | `free_limit_reached` | Come back after Retry-After (UTC midnight), or unlock with a credit. |

Every other refusal it may answer: `dimensions_too_large` (400), `file_empty` (400), `file_too_large` (400), `invalid_id` (400), `invalid_idempotency_key` (400), `invalid_options` (400), `invalid_request` (400), `invalid_size` (400), `malformed_body` (400), `malformed_image` (400), `unsupported_type` (400), `invalid_api_key` (401), `unauthenticated` (401), `email_unverified` (403), `plan_required` (403), `account_exists` (409), `email_refused` (422), `rate_limited` (429), `internal_error` (500), `auth_unavailable` (503).

### Unlock several images

`POST /v1/images/unlock`

1 credit per image not yet unlocked, in ONE transaction: all or nothing. A short balance unlocks none (402); so does an image with no finished result (409 `not_ready`) or whose hold is still running (409 `unlock_pending`). An image already unlocked spends nothing, so a retry is safe.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `ids` | body | array of id | yes | The images, by their ids in GET /images. A repeat is read once. |

```bash
curl -X POST https://api.vecsnap.com/v1/images/unlock \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids":["00000000-0000-4000-8000-000000000000"]}'
```

Answer 200:

```json
{
  "unlocked": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "spent": 0
}
```

Answer 402:

```json
{
  "error": {
    "code": "insufficient_credits",
    "message": "There are not enough credits for this unlock. None was spent.",
    "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": "not_ready",
    "message": "The conversion is still running.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}
```

| Status | Code | What to do |
| --- | --- | --- |
| 402 | `insufficient_credits` | Buy credits, then send the same request again. |
| 404 | `not_found` | Check the id. Another account's objects read as not found too. |
| 409 | `not_ready` | Wait for it to finish (a webhook, the events stream, or a read), then ask again. |
| 409 | `unlock_pending` | Wait for that conversion to finish. |

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

### Delete several images

`POST /v1/images/delete`

ONE transaction, each image's outcome said back. Partial by design: one still converting is refused (`converting`) and the others are still deleted. Restorable for 30 days (POST /images/restore). A repeat keeps the first date (`already_deleted`); another's is `not_found`.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `ids` | body | array of id | yes | The images, by their ids in GET /images. A repeat is read once. |

```bash
curl -X POST https://api.vecsnap.com/v1/images/delete \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids":["00000000-0000-4000-8000-000000000000"]}'
```

Answer 200:

```json
{
  "outcomes": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "outcome": "deleted"
    }
  ]
}
```

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

### Restore several images

`POST /v1/images/restore`

ONE transaction, each image's outcome said back: `restored`, `in_library` (nothing to do), `not_found` (another's, or past its window). A delete's Undo.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `ids` | body | array of id | yes | The images, by their ids in GET /images. A repeat is read once. |

```bash
curl -X POST https://api.vecsnap.com/v1/images/restore \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids":["00000000-0000-4000-8000-000000000000"]}'
```

Answer 200:

```json
{
  "outcomes": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "outcome": "restored"
    }
  ]
}
```

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

### Erase images now

`POST /v1/images/erase`

With `{ ids }`: those images, in ONE transaction, each one's outcome said back: `erased`, `not_deleted` (it is in the library: only Recently deleted is erased now), `not_found`. With `{ all: true }`: every image in Recently deleted ("Erase all now"); "all" is said, never inferred. Exactly one of the two. Versions erased are gone for good, their files deleted.

| Field | In | Type | Required | What |
| --- | --- | --- | --- | --- |
| `ids` | body | array of id | no | The images, by their ids in GET /images. A repeat is read once. |
| `all` | body | `true` | no | Every image in Recently deleted. |

```bash
curl -X POST https://api.vecsnap.com/v1/images/erase \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids":["00000000-0000-4000-8000-000000000000"],"all":true}'
```

Answer 200:

```json
{
  "outcomes": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "outcome": "erased"
    }
  ],
  "versions": 0
}
```

Every refusal it may answer: `invalid_request` (400), `malformed_body` (400), `invalid_api_key` (401), `unauthenticated` (401), `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/images
