API REFERENCE

Conversions

Create a conversion, read it, list them, unlock one, follow its progress.

POST/v1/conversions

Create a conversion

Converting is FREE: 1 credit = 1 image, spent when the image is UNLOCKED (here with unlock: true, or later with POST /conversions/{id}/unlock). A free conversion counts against the daily caps (guests 3 a UTC day, free accounts 10, customers 100). A guest never unlocks: unlock: true answers it 403 account_required. Accepted formats: PNG, JPG, WebP, AVIF, GIF, BMP and TIFF (read by their bytes; an animation or a multi-page TIFF at its first frame), at most 4096×4096. HEIC: send a PNG (the website converts it in the browser). Repeating an idempotencyKey answers 200 with the conversion it already made, never a second one and never a second charge.

Headers

Retry-Afterstring
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.

Body

inputKeystringrequired
From POST /uploads. Must be the caller's.
inputHashstring
OPTIONAL assertion about what was uploaded. The API computes the real hash itself and answers input_hash_mismatch on disagreement: a client-chosen cache key would be a cache-poisoning path.
presetone of default
optionsobject
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).
idempotencyKeystringrequired
Unique per conversion you mean: a retry with the same key is answered with the conversion it made.
filenamestring
OPTIONAL: the uploaded file's own name. Kept as a cleaned label (the base name, no extension, at most 80 characters); the download is <name>.svg.
unlockbooleandefault false
OPTIONAL: unlock the image with this conversion: 1 credit held now, committed when it completes, refunded if it fails. On an image already unlocked it holds nothing (a free re-run); on one a conversion still running is unlocking, 409 unlock_pending. No request spends a credit unless it says so.
queuebooleandefault false
OPTIONAL: past the active limit, WAIT in line (status waiting) instead of a 409 too_many_active_jobs. It starts by itself when one of the caller's conversions ends, oldest first, and may be stopped while it waits (POST /conversions/{id}/cancel). Every cap applies at creation: a waiting conversion counts against the day, and a held credit is held while it waits.

Errors

StatusCodeWhat to do
402insufficient_creditsBuy credits, then send the same request again.
403account_requiredSign in or create an account. The conversions come with you.
404not_foundCheck the id. Another account's objects read as not found too.
409idempotency_key_reusedMake a new key for a new request.
409too_many_active_jobsWait for one to finish, or send queue: true to wait in line.
409unlock_pendingWait for that conversion to finish.
429free_capacity_reachedCome back after Retry-After (UTC midnight), or unlock with a credit.
429free_limit_reachedCome back after Retry-After (UTC midnight), or unlock with a credit.

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl -X POST https://api.vecsnap.com/v1/conversions \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"inputKey":"inputs/2026-10-25/0b6f3c1e-7a2d-4e8b-9c10-5d4e3f2a1b0c/6e1d2c3b-4a5f-4e6d-8c7b-9a0f1e2d3c4b.png","idempotencyKey":"order-1042-logo"}'
example answers
{
  "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
}

GET/v1/conversions

List conversions

The caller's conversions, newest first, a page at a time: pass a page's nextCursor back as cursor. With live=true, only the LIVE ones (waiting, queued, processing), oldest first: the queue as the server holds it, in one page (limit and cursor are then refused).

Query

liveone of true, false
true: only the live ones, oldest first.
limitinteger, 1 to 100default 20
cursorstring
A page's nextCursor.

Errors

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl https://api.vecsnap.com/v1/conversions \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
200
example answers
{
  "object": "list",
  "data": [
    {
      "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"
    }
  ],
  "hasMore": false,
  "nextCursor": null
}

GET/v1/conversions/{id}

Retrieve a conversion

A permalink: for the slow tail this is the normal way a conversion is seen, and it answers the same an hour later as while it runs. Another's conversion is 404, the same as none.

Path

ididrequired

Errors

StatusCodeWhat to do
404not_foundCheck the id. Another account's objects read as not found too.

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000 \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
example answers
{
  "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"
}

DELETE/v1/conversions/{id}

Delete a conversion

Deletes this VERSION of its image: erased at once, it leaves every list and permalink, and its files are deleted within the hour. The image's LAST version is not erased: deleting it deletes the image (Recently deleted, restorable), and deleted says which. Its unlock, if paid, stays the image's.

Path

ididrequired

Errors

StatusCodeWhat to do
404not_foundCheck the id. Another account's objects read as not found too.
409conversion_runningWait for it to finish, then try again.

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl -X DELETE https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000 \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
example answers
{
  "deleted": "conversion"
}

POST/v1/conversions/{id}/cancel

Cancel a waiting conversion

Only a WAITING conversion (created with queue: true, past the active limit) can be stopped: once it has started, a worker holds it. Stopped, it is canceled: a held credit comes back, it leaves the library (an image whose only version it was goes with it), and it is not counted against the day.

Path

ididrequired

Errors

StatusCodeWhat to do
404not_foundCheck the id. Another account's objects read as not found too.
409not_waitingLet a running conversion finish.

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl -X POST https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/cancel \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
example answers
{
  "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"
}

POST/v1/conversions/{id}/unlock

Unlock a conversion's image

1 credit, at most once per image (the same uploaded bytes in this account). After it every result of the image downloads in every format and every re-run of it is free. A repeat, or a conversion of an image already unlocked, spends nothing (spent: 0), so a retry is safe. A POST, never folded into the download: a GET that spends a credit is a GET a link previewer spends.

Path

ididrequired

Errors

StatusCodeWhat to do
402insufficient_creditsBuy credits, then send the same request again.
404not_foundCheck the id. Another account's objects read as not found too.
409conversion_failedConvert the image again. Converting is free.
409not_readyWait for it to finish (a webhook, the events stream, or a read), then ask again.
409result_outdatedConvert the image again.
409unlock_pendingWait for that conversion to finish.

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl -X POST https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/unlock \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
example answers
{
  "unlocked": true,
  "spent": 0
}

GET/v1/conversions/{id}/events

Watch a conversion

Server-Sent Events: a status event at once with the current state, then one on each change of status or phase; its data is a ConversionEvent. The stream closes when the conversion ends. A serverless function has a bounded lifetime and a conversion can outlive it, so a client MUST reconnect and re-read the conversion rather than treat this stream as the only way to learn an outcome.

Path

ididrequired

Errors

StatusCodeWhat to do
404not_foundCheck the id. Another account's objects read as not found too.

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/events \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
404
example answers
{
  "error": {
    "code": "not_found",
    "message": "There is nothing at that id for this caller.",
    "requestId": "req_8Gq2Lw0fTz1kVb6s"
  }
}

GET/v1/conversions/{id}/feedback

Retrieve the verdict

The caller's verdict on a result, or null.

Path

ididrequired

Errors

StatusCodeWhat to do
404not_foundCheck the id. Another account's objects read as not found too.

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/feedback \
  -H "Authorization: Bearer $VECSNAP_API_KEY"
example answers
{
  "verdict": {
    "vote": "up",
    "reasons": [
      "lost_detail"
    ],
    "note": "example",
    "shareImage": false,
    "updatedAt": "2026-10-24T12:00:00.000Z"
  }
}

PUT/v1/conversions/{id}/feedback

Give a verdict

One per result, given or changed: thumbs up or down; a down's reasons; a note; and shareImage. Moves no money: a failed result's credit comes back after a look, by an operator.

Path

ididrequired

Body

voteone of up, downrequired
reasonsarray of one of lost_detail, wrong_colors, rough_edges, too_many_shapes, text, failed
Only with a thumb down.
notestring
shareImagebooleandefault false

Errors

StatusCodeWhat to do
404not_foundCheck the id. Another account's objects read as not found too.
409conversion_failedConvert the image again. Converting is free.
409not_readyWait for it to finish (a webhook, the events stream, or a read), then ask again.
409result_outdatedConvert the image again.

Every refusal carries its code and a requestId. Errors and retries.

curl
your key in VECSNAP_API_KEY
curl -X PUT https://api.vecsnap.com/v1/conversions/00000000-0000-4000-8000-000000000000/feedback \
  -H "Authorization: Bearer $VECSNAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"vote":"up"}'
example answers
{
  "verdict": {
    "vote": "up",
    "reasons": [
      "lost_detail"
    ],
    "note": "example",
    "shareImage": false,
    "updatedAt": "2026-10-24T12:00:00.000Z"
  }
}