Le même moteur, côté serveur.
Transformez n'importe quelle image en tracé vectoriel propre et modifiable — de vrais chemins, un fond par région de couleur. L'API exécute le même moteur WebAssembly que le convertisseur dans le navigateur, sur notre machine plutôt que la vôtre, si bien que le SVG obtenu est celui que l'application aurait produit.
curl -X POST "https://vectortrace.app/api/v1/vectorize?format=svg" \ -F image=@logo.png \ -o logo.svg
Une requête, un fichier en retour. Aucune clé nécessaire pour les limites anonymes ci-dessous.
Authentification
Les requêtes anonymes fonctionnent, avec des limites strictes. Une clé les relève et se transmet comme jeton porteur (bearer). Une clé non reconnue — y compris une clé révoquée — est refusée avec un 401 plutôt que rétrogradée silencieusement vers le niveau anonyme, et le refus est décompté du budget de votre IP : une rétrogradation silencieuse transformerait une faute de frappe en erreur de limite de débit une heure plus tard.
Authorization: Bearer $VECTORTRACE_KEY
Les clés se créent sur la page de votre compte et ne s'affichent qu'une fois ; seul un hachage est conservé. Elles font partie de Pro : 500 images par mois sont incluses, et chaque image supplémentaire coûte 0,02 €, facturée via votre abonnement. Révoquez une clé sur la page de votre compte et elle cesse de fonctionner dès la requête suivante. La gestion des clés est une surface navigateur, authentifiée par le cookie de session et vérifiée par origine — elle est documentée dans le fichier OpenAPI pour qu'un client puisse en voir les formes, mais elle n'est pas destinée à être scriptée.
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
Vectorisez une image raster. Envoyez-la comme partie multipart ou en base64 dans un corps JSON. La réponse est le fichier vectoriel lui-même, ou le document en JSON si vous le demandez.
PNG · JPG · JPEG · WebP · BMP · GIF
Requête
| Partie | Où | Valeur |
|---|---|---|
| image | multipart/form-data | Le fichier raster. |
| image | corps application/json | Le même fichier, encodé en base64, avec ou sans préfixe data:. Utilisez l'un ou l'autre. |
| options | corps JSON, ou champ de formulaire | N'importe quel sous-ensemble des options ci-dessous. Les champs omis prennent les valeurs du preset nommé. |
| format | chaîne de requête | Le format à exporter. La chaîne de requête l'emporte sur le corps. |
| Accept | en-tête de requête | application/json renvoie le document et ses statistiques au lieu du fichier. |
Exemples
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)Corps JSON
POST /api/v1/vectorize?format=svg
Content-Type: application/json
Accept: application/json
{
"image": "iVBORw0KGgoAAAANSUhEUgAA…",
"options": { "preset": "logo", "colors": 8 }
}Options
Chaque champ est optionnel. Un preset renseigne le reste ; un champ défini l'emporte sur le preset. Ce sont les mêmes réglages que l'inspecteur du convertisseur, et la même table que celle lue par le moteur Rust.
| Champ | Valeurs | Par défaut | Remarques |
|---|---|---|---|
| preset | logo · line-art · photo · embroidery · vinyl · laser | logo | Ensembles d'options nommés. Même table que l'application et que le moteur Rust. |
| mode | color · binary | color | Le mode binaire trace une seule encre ; le mode couleur groupe d'abord une palette. |
| colors | 2 – 64 | 16 | Taille de la palette après regroupement. Ignoré en mode binaire. |
| filterSpeckle | pixels de surface | 4 | Les régions plus petites que ce seuil sont supprimées. |
| cornerThreshold | 0 – 180 degrés | 60 | Les angles plus vifs que ce seuil restent des coins durs plutôt que des courbes. |
| pathPrecision | 0 – 4 | 2 | Nombre de décimales écrites dans les données de chemin. |
| curveFitting | pixel · polygon · spline | spline | Pixel conserve l'effet d'escalier, polygone ajuste des droites, spline ajuste des courbes cubiques. |
| hierarchical | stacked · cutout | stacked | Empilé superpose les régions ; découpe rend chaque région disjointe. |
| spliceThreshold | 0 – 180 degrés | 45 | Angle auquel une courbe ajustée est scindée en deux. |
| lengthThreshold | pixels | 4 | Longueur minimale d'arête de polygone conservée avant simplification. |
| maxIterations | 1 – 100 | 10 | Budget d'affinage de l'ajustement de courbe par sous-chemin. |
Réponses et erreurs
Succès
| Statut | Content-Type | Corps |
|---|---|---|
| 200 | image/svg+xml | Le fichier SVG exporté, en ligne, avec un nom de fichier dérivé côté serveur. |
| 200 | application/pdf | Le fichier PDF exporté, en ligne, avec un nom de fichier dérivé côté serveur. |
| 200 | application/postscript | Le fichier EPS exporté, en ligne, avec un nom de fichier dérivé côté serveur. |
| 200 | image/vnd.dxf | Le fichier DXF exporté, en ligne, avec un nom de fichier dérivé côté serveur. |
| 200 | image/png | Le fichier PNG exporté, en ligne, avec un nom de fichier dérivé côté serveur. |
| 200 | application/json | Le document vectoriel et ses statistiques, avec 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 }
}Chaque réponse porte les en-têtes de limite de débit, refusée ou non. X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
Enveloppe d'erreur
Une seule enveloppe, toujours. Décidez sur le code, jamais sur le texte — le code est stable et le message ne l'est pas.
{ "error": { "code": "IMAGE_TOO_LARGE", "message": "…" } }| Statut | Code | Quand |
|---|---|---|
| 400 | DECODE_FAILED | Les octets sont dans un format accepté mais n'ont pas pu être décodés. |
| 400 | VALIDATION_ERROR | Le corps ou un champ ne correspond pas au contrat. |
| 401 | UNAUTHORIZED | Un en-tête Authorization illisible, ou une clé inconnue. |
| 413 | IMAGE_TOO_LARGE | L'image dépasse la limite de pixels de cette classe d'appelant. |
| 413 | PAYLOAD_TOO_LARGE | Le corps dépasse la limite d'octets de cette classe d'appelant. |
| 415 | UNSUPPORTED_FORMAT | Le format de sortie demandé n'a pas d'exportateur dans cette version. |
| 415 | UNSUPPORTED_INPUT_FORMAT | Les octets ne correspondent à aucun raster accepté. |
| 429 | RATE_LIMITED | Budget horaire épuisé. Retry-After indique quand revenir. |
| 500 | ENGINE_ERROR | Le traceur s'est exécuté et a échoué sur cette image. |
| 500 | INTERNAL_ERROR | Notre faute. Réessayez une fois, puis dites-le-nous. |
Limites de débit
| Niveau | Corps max. | Pixels max. | Requêtes | Décompté par |
|---|---|---|---|---|
| Anonyme | 2 MB | 1 MP | 20 / heure | IP client |
| Avec clé | 20 MB | 16 MP | 600 / heure | Identifiant de clé |
Une image dépassant la limite de pixels est refusée, non réduite. Le convertisseur de votre navigateur réduit les visuels trop grands parce que l'alternative est une allocation d'un quart de gigaoctet dans votre propre onglet ; ici le plafond est un budget, et renvoyer des coordonnées qui ne correspondent pas au visuel envoyé serait pire qu'une erreur.
OpenAPI
La référence ci-dessus est générée à partir des mêmes schémas zod que ceux utilisés pour la validation côté serveur, donc il n'existe aucune spécification écrite à la main susceptible de se désynchroniser. Pointez un générateur de client dessus.
GET https://vectortrace.app/api/openapi.json
llms.txt
Un résumé en texte brut du produit, des pages et de cet endpoint, rédigé pour les modèles de langage et les agents. La version complète ajoute l'index des pages et la table des presets.
GET https://vectortrace.app/llms.txt GET https://vectortrace.app/llms-full.txt
CLI
semaine 10Le moteur sous forme de commande. Mêmes presets, même sortie, aucun serveur dans la boucle.
npx @vectortrace/cli in.png -o out.svg --preset laser
MCP
semaine 10Un serveur MCP exposant le moteur aux agents via stdio ou HTTP en flux continu. Trois outils :
| Outil | Fait |
|---|---|
| vectorize_image | Trace une image et renvoie un identifiant de document ainsi que des statistiques. |
| list_presets | Renvoie la table des presets avec chaque valeur d'option. |
| export_document | Sérialise un identifiant vers l'un des formats d'export. |