PerfectVector API for AI agents
Keys, endpoints, prices, limits, errors and a full example, on one page for coding agents.
On this page
This page is for AI coding agents and the people who use them. It puts what you need to write an integration in one place, and each section links to the guide with the details.
The PerfectVector API converts PNG, JPEG and WebP images into SVG files. You send an image with an API key, and you get the SVG back.
Using an AI assistant instead? See the MCP docs.
Before you start
- Base URL:
https://api.perfectvector.com/v1 - An API key. Someone signed in to perfectvector.com creates it on the Developer API page of their account. An API key cannot manage keys.
- A server or a script. The API sends no CORS headers, so browsers block calls from web pages, and an API key in a web page would be public.
API keys
| Prefix | Mode | What it does |
|---|---|---|
pv_test_ | test | Returns a fixed sample SVG and never uses credits. |
pv_live_ | live | Converts your image and uses API credits when the conversion succeeds. |
- Start with a test key. It runs the whole request at no cost: the key check, the file checks, the rate limits and the response shape work as they do in live mode.
- Send the key only in the
Authorizationheader:Authorization: Bearer <key>. A key in the URL is ignored, and the request fails with401 invalid_api_key. - Keep the key out of your code. The examples read it from the
PERFECTVECTOR_API_KEYenvironment variable. - We show a key once, when it is created. An account can have up to 10 active keys, live and test together.
GET /v1/accountshows which key you are using, your API balance, prices and limits.
See Authentication and Test mode.
Endpoints
| Method | Path | What it does | Credits |
|---|---|---|---|
POST | /v1/vectorizations | Convert one image. Waits for the result, or answers at once and lets you poll. | 1 on success |
GET | /v1/vectorizations/{id} | The conversion's status and result links. | 0 |
GET | /v1/vectorizations/{id}/result | Download the SVG. | 0 |
GET | /v1/vectorizations/{id}/results/{index} | Download the SVG of one result, by its position (0 in v1). | 0 |
DELETE | /v1/vectorizations/{id} | Delete the conversion's image and SVG now. | 0 |
GET | /v1/account | Your API balance, prices, limits and the key you used. | 0 |
There is no endpoint that lists your conversions. Keep the id of each conversion you create.
- Requests:
POST /v1/vectorizationstakesmultipart/form-datawith the fieldimage(required) and the fieldoptions(optional; leave it out in v1). No other fields. The other endpoints take no body. - Responses: JSON, except the SVG itself. Errors are
application/problem+json. - IDs:
vec_…for conversions,key_…for keys,req_…for requests. Times are RFC 3339 in UTC. - Headers on every response:
X-Request-IDandX-Credits-Charged. - New fields: we may add fields to responses. Ignore fields you do not know.
A complete example
Convert logo.png with a test key. Send an Idempotency-Key with every POST, so a retry after a
network error never converts or charges twice:
curl https://api.perfectvector.com/v1/vectorizations \
-H "Authorization: Bearer $PERFECTVECTOR_API_KEY" \
-H "Idempotency-Key: logo-0001" \
-F image=@logo.png
When the conversion has finished, the answer is 201 Created:
HTTP/1.1 201 Created
Content-Type: application/json
Location: /v1/vectorizations/vec_6Jd2LpQ8sV1nX4cR7tY0aB
X-Credits-Charged: 0
X-Credits-Would-Charge: 1
X-Request-ID: req_4Tq8WmX2r9LcB0vZs7KpY1
{
"id": "vec_6Jd2LpQ8sV1nX4cR7tY0aB",
"object": "vectorization",
"mode": "test",
"status": "succeeded",
"request_type": "single",
"created_at": "2026-10-26T09:30:12Z",
"completed_at": "2026-10-26T09:30:12Z",
"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:12Z"
},
"error": null
}
],
"result_counts": { "total": 1, "succeeded": 1, "failed": 0, "pending": 0 },
"credits_charged": 0,
"deleted_at": null
}
Download the SVG with the same API key. -OJ saves it under the name the API gives it
(logo.svg):
curl -OJ https://api.perfectvector.com/v1/vectorizations/vec_6Jd2LpQ8sV1nX4cR7tY0aB/result \
-H "Authorization: Bearer $PERFECTVECTOR_API_KEY"
A test key returns a fixed sample SVG and charges nothing; X-Credits-Would-Charge shows what a live
key would have paid. With a live key (pv_live_…) the same request converts your image and uses 1
API credit when it succeeds.
Handle every answer
| Answer | What to do |
|---|---|
201 with "status": "succeeded" | Download results[0].result.url with the same key. The result stays available for 24 hours, so keep your own copy. |
202 Accepted | Not finished within the wait. Poll GET /v1/vectorizations/{id} about every 2 seconds until status is succeeded or failed. |
201 with "status": "failed" | No charge. results[0].error.code says why. Retry with a new Idempotency-Key. |
4xx or 5xx | An error: see Errors below. |
- Waiting:
POST /v1/vectorizationswaits up to 120 seconds by default. Set your HTTP client's timeout above that, or sendPrefer: wait=N(1 to 120 seconds) orPrefer: respond-async. - The SVG in one call: send
Accept: image/svg+xml. When the conversion succeeds within the wait, the201body is the SVG itself. Check theContent-Typeheader before you save the body. - Retries: the same
Idempotency-Keywith the same image within 24 hours returns the same conversion, never charged twice. The same key with another image answers409 idempotency_conflict. A key is 8 to 128 letters, digits,-and_.
Complete Python and Node.js programs that create, poll and save are in the Quickstart. See also Waiting and async, Idempotency and Results.
Prices
- A live request uses 1 API credit when its conversion succeeds.
GET /v1/accountshows the current price inpricing.credits_per_request. - Free: failed and timed-out conversions; requests the API refuses, including
402,429and503answers; status checks,GET /v1/accountandDELETE; downloading a result again while it is available; repeating a request with the sameIdempotency-Keywithin 24 hours; every call with a test key. - API credits are separate from the credits used on the website, and the two never convert into each other. They are bought as one-time packs on the Developer API page, with no subscription and no automatic top-up.
- There is no overdraft: when your available credits are lower than the price,
POST /v1/vectorizationsanswers402 insufficient_creditsbefore any work starts.
The current API credit packs:
API credits are separate from website credits. A live API request uses 1 API credit only when its conversion succeeds; test keys are free. During the beta, every pack is 20% off at checkout; the regular price is listed for reference.
| Pack | API credits | Regular price | Price at checkout | Per conversion | Packs per order | Credit expiry |
|---|---|---|---|---|---|---|
| Starter | 10 | USD 5.00 | USD 4.00 | USD 0.40 | up to 10 | 12 months after purchase |
| Bulk 100 | 100 | USD 20.00 | USD 16.00 | USD 0.16 | up to 10 | 12 months after purchase |
| Bulk 1,000 | 1000 | USD 100.00 | USD 80.00 | USD 0.08 | up to 10 | 12 months after purchase |
For 10000 API credits or more, email sales@perfectvector.com for custom pricing.
Lemon Squeezy, our Merchant of Record, may add tax at checkout. See Credits.
Limits
| Limit | Value | When you reach it |
|---|---|---|
| Conversions created per minute | 20 | 429 rate_limited |
POST /v1/vectorizations attempts per minute (every POST, also replays and refused requests) | about 40 | 429 rate_limited |
Other requests per minute (status, downloads, DELETE, GET /v1/account) | about 120 | 429 rate_limited |
| Live conversions in progress at once | 1 (test keys: no limit) | 429 too_many_in_flight |
| Active API keys | 10, live and test together |
| File limit | Value |
|---|---|
| Formats | PNG, JPEG, WebP (checked from the file's content, not its name) |
| File size | 5 MiB (5,242,880 bytes) |
| Image size | 100 to 4096 pixels on each side |
| Frames | One. Animated images are refused. |
- Limits apply to the whole account, across all of its keys. Test keys have their own counters.
- One live conversion at a time. Send the next image when the first one has finished. Requests are not queued for you.
- On
429and503, wait theRetry-Afterseconds, then retry with the sameIdempotency-Key. GET /v1/accountreturns your current limits inlimits. If you need more, email contact@perfectvector.com.
See Limits.
Errors
Every error is RFC 9457 problem details, with
Content-Type: application/problem+json. Branch on code, never on title or detail. Errors
are never charged.
{
"type": "https://perfectvector.com/docs/api/errors#insufficient_credits",
"title": "Not enough API credits",
"status": 402,
"detail": "This request needs 1 API credit. Available: 0.",
"code": "insufficient_credits",
"request_id": "req_4Tq8WmX2r9LcB0vZs7KpY1",
"credits_required": 1,
"credits_available": 0
}
code | HTTP | Retry? |
|---|---|---|
invalid_request | 400 | After fixing the request |
invalid_api_key | 401 | After fixing the key |
insufficient_credits | 402 | After buying credits |
account_suspended | 403 | No; contact us |
access_not_granted | 403 | No; contact us |
not_found | 404 | No |
method_not_allowed | 405 | No |
idempotency_conflict | 409 | With a new key |
conversion_in_progress | 409 | After it finishes |
result_not_ready | 409 | After it succeeds |
result_expired | 410 | No |
file_too_large | 413 | With a smaller file |
unsupported_media_type | 415 | With PNG, JPEG or WebP |
invalid_image | 422 | With another image |
rate_limited | 429 | After Retry-After |
too_many_in_flight | 429 | When the running one finishes |
internal_error | 500 | Yes, with the same Idempotency-Key |
service_busy | 503 | After Retry-After |
api_paused | 503 | After Retry-After |
A failed conversion is not an error: it answers 201 or 200 with "status": "failed", and
costs nothing.
error.code | What to do |
|---|---|
processing_failed | Check the image; another image may work. |
timeout | Retry with a new Idempotency-Key. |
provider_unavailable | Retry later with a new Idempotency-Key. |
A 403 or 429 whose body is not problem details comes from our network edge, not from the API.
Slow down and retry later. See Errors for every code.
Privacy
From the API Privacy Notice: "Your images are never used to train AI models and never sold."
- Results stay available for 24 hours after the conversion completes. We delete images and results from storage within 48 hours.
DELETE /v1/vectorizations/{id}deletes a conversion's image and SVG at once.- With a test key, we check the image and then discard it.
Terms and support
- You accept the API Terms when you create your first key or buy credits for the first time.
- Questions: contact@perfectvector.com. Please include the
request_id.