El mismo motor, en el servidor.
Convierte cualquier imagen en arte vectorial limpio y editable: trazados reales, un relleno por región de color. La API ejecuta el mismo motor WebAssembly que el convertidor del navegador, en nuestra máquina en lugar de la tuya, así que el SVG que recibes es el mismo que produciría la aplicación.
curl -X POST "https://vectortrace.app/api/v1/vectorize?format=svg" \ -F image=@logo.png \ -o logo.svg
Una solicitud, un archivo de vuelta. No se necesita clave para los límites anónimos de abajo.
Autenticación
Las solicitudes anónimas funcionan, con límites estrictos. Una clave los eleva y se envía como token de portador (bearer). Una clave que no reconocemos —incluida una revocada— se rechaza con 401 en lugar de degradarse en silencio al nivel anónimo, y el rechazo cuenta contra el presupuesto de tu IP: una degradación silenciosa convertiría una errata en un error de límite de tasa una hora después.
Authorization: Bearer $VECTORTRACE_KEY
Las claves se crean en la página de tu cuenta y se muestran una sola vez; solo se guarda un hash. Forman parte de Pro: se incluyen 500 imágenes al mes, y cada imagen adicional cuesta 0,02 €, facturada a través de tu suscripción. Revoca una clave en la página de tu cuenta y deja de funcionar en la siguiente solicitud. La gestión de claves es una superficie del navegador, autenticada por la cookie de sesión y verificada por origen; está documentada en el archivo OpenAPI para que un cliente vea las formas, pero no está pensada para automatizarse.
GET /api/account/keys → { keys, usage, maxKeys }
POST /api/account/keys { name } → { key, secret } # secret shown once
DELETE /api/account/keys/{id} → { revoked: true, id }POST/api/v1/vectorize
Vectoriza una imagen ráster. Envíala como parte multipart o en base64 dentro de un cuerpo JSON. La respuesta es el propio archivo vectorial, o el documento en JSON si lo solicitas.
PNG · JPG · JPEG · WebP · BMP · GIF
Solicitud
| Parte | Dónde | Valor |
|---|---|---|
| image | multipart/form-data | El archivo ráster. |
| image | cuerpo application/json | El mismo archivo, codificado en base64, con o sin el prefijo data:. Usa una de las dos opciones. |
| options | cuerpo JSON, o campo de formulario | Cualquier subconjunto de las opciones de abajo. Los campos que omitas toman los valores del preajuste indicado. |
| format | cadena de consulta | Qué exportar. La consulta prevalece sobre el cuerpo. |
| Accept | cabecera de la solicitud | application/json devuelve el documento y sus estadísticas en lugar del archivo. |
Ejemplos
curl -X POST "https://vectortrace.app/api/v1/vectorize?format=svg" \
-H "Authorization: Bearer $VECTORTRACE_KEY" \
-F "image=@logo.png" \
-F 'options={"preset":"logo","colors":8}' \
-o logo.svgimport { readFile, writeFile } from 'node:fs/promises'
const form = new FormData()
form.append('image', new Blob([await readFile('logo.png')]), 'logo.png')
form.append('options', JSON.stringify({ preset: 'logo', colors: 8 }))
const response = await fetch('https://vectortrace.app/api/v1/vectorize?format=svg', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.VECTORTRACE_KEY}` },
body: form,
})
if (!response.ok) throw new Error(await response.text())
await writeFile('logo.svg', Buffer.from(await response.arrayBuffer()))import json, os, requests
with open("logo.png", "rb") as image:
response = requests.post(
"https://vectortrace.app/api/v1/vectorize",
params={"format": "svg"},
headers={"Authorization": f"Bearer {os.environ['VECTORTRACE_KEY']}"},
files={"image": image},
data={"options": json.dumps({"preset": "logo", "colors": 8})},
)
response.raise_for_status()
open("logo.svg", "wb").write(response.content)Cuerpo JSON
POST /api/v1/vectorize?format=svg
Content-Type: application/json
Accept: application/json
{
"image": "iVBORw0KGgoAAAANSUhEUgAA…",
"options": { "preset": "logo", "colors": 8 }
}Opciones
Todos los campos son opcionales. Un preajuste rellena el resto; un campo que definas prevalece sobre el preajuste. Son los mismos controles que el inspector del convertidor, y la misma tabla que lee el motor en Rust.
| Campo | Valores | Predeterminado | Notas |
|---|---|---|---|
| preset | logo · line-art · photo · embroidery · vinyl · laser | logo | Conjuntos de opciones con nombre. La misma tabla que la aplicación y que el motor en Rust. |
| mode | color · binary | color | Binario traza una sola tinta; color agrupa antes una paleta. |
| colors | 2 – 64 | 16 | Tamaño de la paleta tras el agrupamiento. Se ignora en modo binario. |
| filterSpeckle | píxeles de área | 4 | Se descartan las regiones más pequeñas que este valor. |
| cornerThreshold | 0 – 180 grados | 60 | Los giros más cerrados que este ángulo se mantienen como esquinas vivas en vez de curvas. |
| pathPrecision | 0 – 4 | 2 | Decimales escritos en los datos del trazado. |
| curveFitting | pixel · polygon · spline | spline | Píxel conserva el efecto escalera, polígono ajusta líneas rectas, spline ajusta curvas cúbicas. |
| hierarchical | stacked · cutout | stacked | Apilado pinta las regiones unas sobre otras; recorte hace que cada región sea disjunta. |
| spliceThreshold | 0 – 180 grados | 45 | Ángulo a partir del cual una curva ajustada se divide en dos. |
| lengthThreshold | píxeles | 4 | Arista de polígono más corta que se conserva antes de la simplificación. |
| maxIterations | 1 – 100 | 10 | Presupuesto de refinamiento del ajuste de curvas por subtrazado. |
Respuestas y errores
Éxito
| Estado | Content-Type | Cuerpo |
|---|---|---|
| 200 | image/svg+xml | El archivo SVG exportado, en línea, con un nombre de archivo derivado por el servidor. |
| 200 | application/pdf | El archivo PDF exportado, en línea, con un nombre de archivo derivado por el servidor. |
| 200 | application/postscript | El archivo EPS exportado, en línea, con un nombre de archivo derivado por el servidor. |
| 200 | image/vnd.dxf | El archivo DXF exportado, en línea, con un nombre de archivo derivado por el servidor. |
| 200 | image/png | El archivo PNG exportado, en línea, con un nombre de archivo derivado por el servidor. |
| 200 | application/json | El documento vectorial y sus estadísticas, con Accept: application/json. |
{
"document": {
"version": 1, "width": 512, "height": 512, "unit": "px",
"palette": ["#101114", "#e8491d"],
"elements": [{ "kind": "path", "fill": 0, "stroke": null, "subpaths": [ … ] }]
},
"stats": { "paths": 12, "nodes": 184, "colors": 2, "ms": 41, "estimatedSvgBytes": 3210 }
}Toda respuesta incluye las cabeceras de límite de tasa, se rechace o no. X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
Formato de error
Un único formato, siempre. Distingue por el código, nunca por el texto: el código es estable y el mensaje no.
{ "error": { "code": "IMAGE_TOO_LARGE", "message": "…" } }| Estado | Código | Cuándo |
|---|---|---|
| 400 | DECODE_FAILED | Los bytes son de un formato aceptado pero no se pudieron decodificar. |
| 400 | VALIDATION_ERROR | El cuerpo o un campo no coincide con el contrato. |
| 401 | UNAUTHORIZED | Una cabecera Authorization ilegible, o una clave que no reconocemos. |
| 413 | IMAGE_TOO_LARGE | La imagen supera el límite de píxeles de esta clase de llamada. |
| 413 | PAYLOAD_TOO_LARGE | El cuerpo supera el límite de bytes de esta clase de llamada. |
| 415 | UNSUPPORTED_FORMAT | El formato de salida solicitado no tiene exportador en esta versión. |
| 415 | UNSUPPORTED_INPUT_FORMAT | Los bytes no corresponden a ninguno de los rásteres aceptados. |
| 429 | RATE_LIMITED | Presupuesto horario agotado. Retry-After indica cuándo volver. |
| 500 | ENGINE_ERROR | El trazador se ejecutó y falló con esta imagen. |
| 500 | INTERNAL_ERROR | Culpa nuestra. Reinténtalo una vez y después avísanos. |
Límites de tasa
| Nivel | Cuerpo máx. | Píxeles máx. | Solicitudes | Se cuenta por |
|---|---|---|---|---|
| Anónimo | 2 MB | 1 MP | 20 / hora | IP del cliente |
| Con clave | 20 MB | 16 MP | 600 / hora | Identificador de clave |
Una imagen que supera el límite de píxeles se rechaza, no se reduce. El convertidor de tu navegador reduce las obras de gran tamaño porque la alternativa es una reserva de un cuarto de gigabyte en tu propia pestaña; aquí el límite es un presupuesto, y devolver coordenadas que no encajan con la obra enviada sería peor que un error.
OpenAPI
La referencia de arriba se genera a partir de los mismos esquemas zod con los que valida el servidor, así que no hay una especificación escrita a mano que pueda desactualizarse. Apunta a ella un generador de clientes.
GET https://vectortrace.app/api/openapi.json
llms.txt
Un resumen en texto plano del producto, las páginas y este endpoint, escrito para modelos de lenguaje y agentes. La versión completa añade el índice de páginas y la tabla de preajustes.
GET https://vectortrace.app/llms.txt GET https://vectortrace.app/llms-full.txt
CLI
semana 10El motor como comando. Los mismos preajustes, la misma salida, sin servidor de por medio.
npx @vectortrace/cli in.png -o out.svg --preset laser
MCP
semana 10Un servidor MCP que expone el motor a agentes por stdio o HTTP en streaming. Tres herramientas:
| Herramienta | Hace |
|---|---|
| vectorize_image | Traza una imagen y devuelve un identificador de documento más estadísticas. |
| list_presets | Devuelve la tabla de preajustes con todos los valores de opción. |
| export_document | Serializa un identificador a uno de los formatos de exportación. |