# Results, downloads and the 24-hour expiry

Read the vectorization object, download the SVG, and delete files early.

> **Coming soon:** The Developer API opens soon. You can read the docs now; API keys arrive when it opens.

## The vectorization object

`POST /v1/vectorizations`, `GET /v1/vectorizations/{id}` and `DELETE /v1/vectorizations/{id}` all
return the same object:

```json
{
  "id": "vec_6Jd2LpQ8sV1nX4cR7tY0aB",
  "object": "vectorization",
  "mode": "live",
  "status": "succeeded",
  "request_type": "single",
  "created_at": "2026-10-26T09:30:12Z",
  "completed_at": "2026-10-26T09:30:31Z",
  "input": { "filename": "logo.png", "width": 1024, "height": 1024, "bytes": 182311 },
  "results": [
    {
      "index": 0,
      "status": "succeeded",
      "options": {},
      "result": {
        "format": "svg",
        "url": "https://api.perfectvector.com/v1/vectorizations/vec_6Jd2LpQ8sV1nX4cR7tY0aB/results/0",
        "expires_at": "2026-10-27T09:30:31Z"
      },
      "error": null
    }
  ],
  "result_counts": { "total": 1, "succeeded": 1, "failed": 0, "pending": 0 },
  "credits_charged": 1,
  "deleted_at": null
}
```

| Field | Meaning |
|---|---|
| `id` | The conversion's ID. Keep it: there is no list endpoint. |
| `mode` | `live` or `test`, from the key that created it. |
| `status` | `queued`, `processing`, `succeeded` or `failed` (`partially_succeeded` is reserved for requests with several results). |
| `request_type` | `single` in v1. |
| `completed_at` | When the conversion finished; `null` before. |
| `input` | The uploaded image: its cleaned file name, width and height in pixels, and size in bytes. `filename` is cleared together with the files (see the 24-hour expiry below) and after `DELETE`; it is `null` when the upload had no name. |
| `results` | One entry per result. In v1 a request always has exactly one, at `index` 0. |
| `results[].result` | The download link and its expiry. Present when that result `succeeded`, and `null` after `DELETE`. |
| `results[].error` | Why that result `failed`: a `code` and a `message`. See below. |
| `result_counts` | Totals over `results`. |
| `credits_charged` | Credits this request has been charged so far: `0`, or `1` once a live conversion succeeded. |
| `deleted_at` | When you deleted it; `null` otherwise. |

The `options` form field and each result's `options` are reserved for processing settings. In v1,
`options` may be left out, or be `{}` or `{"variants": [{}]}`; anything else answers
`400 invalid_request`.

## Failed conversions

A failed conversion is not an HTTP error. The request answers `201` (or `200` on a status check)
with `"status": "failed"`, and the result's `error` says why. It costs nothing.

| `error.code` | Message | What to do |
|---|---|---|
| `processing_failed` | The image could not be vectorized. | Check the image. Another image may work. |
| `timeout` | The conversion did not finish in time. Retry with a new Idempotency-Key. | Retry with a new `Idempotency-Key`. |
| `provider_unavailable` | The vectorization service was temporarily unavailable. Retry with a new Idempotency-Key. | Retry later with a new `Idempotency-Key`. |

## Download the SVG

Use the result's `url`, or the shortcut `/v1/vectorizations/{id}/result`, which is the same as
`/results/0`. Send the same API key:

```bash
curl -OJ https://api.perfectvector.com/v1/vectorizations/vec_6Jd2LpQ8sV1nX4cR7tY0aB/result \
  -H "Authorization: Bearer $PERFECTVECTOR_API_KEY"
```

- The link is **not public**. It needs a key of the same account and mode, so you cannot put it in
  an `<img>` tag or send it to someone else. Download the file and serve your own copy.
- The API sends the SVG itself, never a redirect to another host, so your key never leaves the API.
- Downloads are free and can be repeated while the result is available. They count toward the read
  limit ([Limits](/docs/api/limits)).

The response is `200` with `Content-Type: image/svg+xml` and these headers:

| Header | Value |
|---|---|
| `Content-Disposition` | `attachment; filename="logo.svg"`: your image's name with `.svg`, or `vectorization-<id>.svg` when the upload had no name. A name with non-ASCII characters also gets a UTF-8 `filename*`. |
| `Cache-Control` | `private, no-store` |
| `X-Content-Type-Options` | `nosniff` |
| `Content-Security-Policy` | `default-src 'none'; style-src 'unsafe-inline'; sandbox`, so an SVG opened in a browser on the API host cannot run anything. |

A download can also answer:

| Status | `code` | When |
|---|---|---|
| `404` | `not_found` | No such conversion for this key's account and mode, or no such result index. |
| `409` | `result_not_ready` | The result is `queued`, `processing` or `failed`. The body's `result_status` says which. |
| `410` | `result_expired` | More than 24 hours after `completed_at`, or after `DELETE`. |

## The 24-hour expiry

Results are available for **24 hours** after the conversion completes (`expires_at`). After that,
the download answers `410 result_expired`. We delete inputs and results from storage within
48 hours. **Keep your own copy of every SVG you need.**

The conversion's record stays after the files are gone: `GET /v1/vectorizations/{id}` keeps
answering with its status, sizes and charge, for your usage history and billing.

## Delete files early

`DELETE /v1/vectorizations/{id}` deletes the conversion's image and SVG at once:

- It answers `200` with the object: `deleted_at` is set and every `result` is `null`. Downloads then
  answer `410`.
- Deleting again answers `200` with the same object.
- While the conversion is still `queued` or `processing`, it answers `409 conversion_in_progress`.
  Delete it after it has finished.
- Deleting never refunds a charge. The record stays, as above.

[Site index](https://perfectvector.com/llms.txt) — available pages and descriptions.
