Lo stesso motore, lato server.
Trasforma qualsiasi immagine in arte vettoriale pulita e modificabile — tracciati reali, un riempimento per ogni regione di colore. L'API esegue lo stesso motore WebAssembly del convertitore nel browser, sulla nostra macchina invece che sulla tua, quindi l'SVG che ricevi è l'SVG che avrebbe prodotto l'app.
curl -X POST "https://vectortrace.app/api/v1/vectorize?format=svg" \ -F image=@logo.png \ -o logo.svg
Una richiesta, un file in risposta. Nessuna chiave necessaria per i limiti anonimi qui sotto.
Autenticazione
Le richieste anonime funzionano, con limiti stretti. Una chiave li innalza e viene inviata come bearer token. Una chiave che non riconosciamo — inclusa una revocata — viene rifiutata con 401 invece di essere silenziosamente declassata al livello anonimo, e il rifiuto conta sul budget del tuo IP: un declassamento silenzioso trasformerebbe un errore di battitura in un errore di limite di frequenza un'ora dopo.
Authorization: Bearer $VECTORTRACE_KEY
Le chiavi si creano nella pagina del tuo account e vengono mostrate una sola volta; viene memorizzato solo un hash. Fanno parte di Pro: 500 immagini al mese sono incluse, e ogni immagine oltre quella soglia costa 0,02 €, fatturata tramite il tuo abbonamento. Revoca una chiave nella pagina dell'account e smetterà di funzionare alla richiesta successiva. La gestione delle chiavi è una superficie da browser, autenticata dal cookie di sessione e verificata sull'origine — è documentata nel file OpenAPI così un client può vederne le forme, ma non è pensata per essere scriptata.
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
Vettorizza un'immagine raster. Inviala come parte multipart o come base64 dentro un corpo JSON. La risposta è il file vettoriale stesso, oppure il documento come JSON se lo richiedi.
PNG · JPG · JPEG · WebP · BMP · GIF
Richiesta
| Parte | Dove | Valore |
|---|---|---|
| image | multipart/form-data | Il file raster. |
| image | corpo application/json | Lo stesso file, codificato in base64, con o senza prefisso data:. Usa uno dei due. |
| options | corpo JSON, o campo del form | Qualsiasi sottoinsieme delle opzioni sottostanti. I campi omessi assumono i valori del preset indicato. |
| format | stringa di query | Cosa esportare. La query prevale sul corpo. |
| Accept | intestazione della richiesta | application/json restituisce il documento e le sue statistiche invece del file. |
Esempi
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)Corpo JSON
POST /api/v1/vectorize?format=svg
Content-Type: application/json
Accept: application/json
{
"image": "iVBORw0KGgoAAAANSUhEUgAA…",
"options": { "preset": "logo", "colors": 8 }
}Opzioni
Ogni campo è opzionale. Un preset compila il resto; un campo che imposti prevale sul preset. Sono gli stessi controlli dell'ispettore del convertitore, e la stessa tabella letta dal motore Rust.
| Campo | Valori | Predefinito | Note |
|---|---|---|---|
| preset | logo · line-art · photo · embroidery · vinyl · laser | logo | Insiemi di opzioni predefiniti. Stessa tabella dell'app e del motore Rust. |
| mode | color · binary | color | Binario traccia un solo inchiostro; colore raggruppa prima una tavolozza. |
| colors | 2 – 64 | 16 | Dimensione della tavolozza dopo il clustering. Ignorato in modalità binaria. |
| filterSpeckle | pixel di area | 4 | Le regioni più piccole di questo valore vengono scartate. |
| cornerThreshold | 0 – 180 gradi | 60 | Le svolte più brusche di questa soglia restano angoli vivi invece di curve. |
| pathPrecision | 0 – 4 | 2 | Decimali scritti nei dati del tracciato. |
| curveFitting | pixel · polygon · spline | spline | Pixel mantiene la scalettatura, poligono adatta linee, spline adatta cubiche. |
| hierarchical | stacked · cutout | stacked | Impilata sovrappone le regioni tra loro; ritaglio rende ogni regione disgiunta. |
| spliceThreshold | 0 – 180 gradi | 45 | Angolo al quale una curva adattata viene divisa in due. |
| lengthThreshold | pixel | 4 | Bordo poligonale più corto mantenuto prima della semplificazione. |
| maxIterations | 1 – 100 | 10 | Budget di raffinamento dell'adattamento curve per sotto-tracciato. |
Risposte ed errori
Successo
| Stato | Content-Type | Corpo |
|---|---|---|
| 200 | image/svg+xml | Il file SVG esportato, inline, con un nome file derivato dal server. |
| 200 | application/pdf | Il file PDF esportato, inline, con un nome file derivato dal server. |
| 200 | application/postscript | Il file EPS esportato, inline, con un nome file derivato dal server. |
| 200 | image/vnd.dxf | Il file DXF esportato, inline, con un nome file derivato dal server. |
| 200 | image/png | Il file PNG esportato, inline, con un nome file derivato dal server. |
| 200 | application/json | Il documento vettoriale e le sue statistiche, 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 }
}Ogni risposta porta le intestazioni di limite di frequenza, rifiutata o no. X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
Busta di errore
Una busta, sempre. Basa la logica sul codice, mai sul testo — il codice è stabile e il messaggio no.
{ "error": { "code": "IMAGE_TOO_LARGE", "message": "…" } }| Stato | Codice | Quando |
|---|---|---|
| 400 | DECODE_FAILED | I byte sono in un formato che accettiamo ma non è stato possibile decodificarli. |
| 400 | VALIDATION_ERROR | Il corpo o un campo non corrispondeva al contratto. |
| 401 | UNAUTHORIZED | Un'intestazione Authorization non leggibile, o una chiave che non conosciamo. |
| 413 | IMAGE_TOO_LARGE | L'immagine supera il limite di pixel per questa classe di chiamante. |
| 413 | PAYLOAD_TOO_LARGE | Il corpo supera il limite di byte per questa classe di chiamante. |
| 415 | UNSUPPORTED_FORMAT | Il formato di output richiesto non ha un esportatore in questa build. |
| 415 | UNSUPPORTED_INPUT_FORMAT | I byte non corrispondono a uno dei raster accettati. |
| 429 | RATE_LIMITED | Budget orario esaurito. Retry-After indica quando ritornare. |
| 500 | ENGINE_ERROR | Il tracciatore è stato eseguito ed è fallito su questa immagine. |
| 500 | INTERNAL_ERROR | Colpa nostra. Riprova una volta, poi segnalacelo. |
Limiti di frequenza
| Livello | Corpo massimo | Pixel massimi | Richieste | Conteggiato per |
|---|---|---|---|---|
| Anonimo | 2 MB | 1 MP | 20 / ora | IP del client |
| Con chiave | 20 MB | 16 MP | 600 / ora | Identificativo della chiave |
Un'immagine oltre il limite di pixel viene rifiutata, non ridimensionata. Il convertitore nel tuo browser riduce le opere sovradimensionate perché l'alternativa è un'allocazione di un quarto di gigabyte nella tua stessa scheda; qui il tetto è un budget, e restituire coordinate che non corrispondono all'opera inviata sarebbe peggio di un errore.
OpenAPI
Il riferimento qui sopra è generato dagli stessi schemi zod con cui valida il server, quindi non esiste una specifica scritta a mano che possa disallinearsi. Punta un generatore di client verso di essa.
GET https://vectortrace.app/api/openapi.json
llms.txt
Un riepilogo in testo semplice del prodotto, delle pagine e di questo endpoint, scritto per modelli linguistici e agenti. La versione completa aggiunge l'indice delle pagine e la tabella dei preset.
GET https://vectortrace.app/llms.txt GET https://vectortrace.app/llms-full.txt
CLI
settimana 10Il motore come comando. Stessi preset, stesso output, nessun server nel ciclo.
npx @vectortrace/cli in.png -o out.svg --preset laser
MCP
settimana 10Un server MCP che espone il motore agli agenti su stdio o streamable HTTP. Tre strumenti:
| Strumento | Fa |
|---|---|
| vectorize_image | Traccia un'immagine e restituisce un handle al documento più le statistiche. |
| list_presets | Restituisce la tabella dei preset con ogni valore di opzione. |
| export_document | Serializza un handle in uno dei formati di esportazione. |