API y MCP
Envía una imagen PNG o JPEG desde un script, un plugin o un agente de IA y recibe un SVG. La API usa el cálculo en el servidor de Homotope: mismo motor, misma cola, mismos créditos y mismo límite de imagen que el taller.
Descripción completa (OpenAPI 3.1): /api/v1/openapi.json.
El motor es de código abierto (MIT): paquete @homotope/engine en npm, código fuente en GitHub.
Empezar en 3 pasos
-
Crea una clave en el taller, «Mi cuenta» → «Claves
de API». Empieza por
hmt_live_y solo se muestra una vez: guárdala en un gestor de secretos, nunca en un repositorio ni en una URL. -
Envía una imagen:
POST /api/v1/jobsresponde enseguida con202y el identificador del cálculo, sin esperar a que termine. -
Consulta y luego descarga: pregunta a
GET /api/v1/jobs/{id}cada 2 a 5 segundos hasta que el estado seadoney después recuperaGET /api/v1/jobs/{id}/svg, oGET /api/v1/jobs/{id}/result?format=pdf(svg,pdf,dxfoeps).
Ejemplos con curl
La clave va en la cabecera Authorization: Bearer …, y solo ahí.
export HOMOTOPE_KEY="hmt_live_…"
# Comprobar la clave
curl -sS https://homotope.example/api/v1/me \
-H "Authorization: Bearer $HOMOTOPE_KEY"
# Enviar una imagen (opciones opcionales: preajuste, nombre, ajustes)
curl -sS https://homotope.example/api/v1/jobs \
-H "Authorization: Bearer $HOMOTOPE_KEY" \
-F [email protected] \
-F 'options={"preset":"logo","name":"Logo","options":{"export":{"precision":2}}}'
# → 202 {"id":"…","state":"queued","links":{…}}
# Paleta impuesta: trazar con TUS colores (de 2 a 64, distintos), no se inventa ningún otro color
curl -sS https://homotope.example/api/v1/jobs \
-H "Authorization: Bearer $HOMOTOPE_KEY" \
-F [email protected] \
-F 'options={"preset":"logo","palette":["#E30613","#0057B8","#FFFFFF"]}'
# Consultar hasta "state": "done"
curl -sS https://homotope.example/api/v1/jobs/ID \
-H "Authorization: Bearer $HOMOTOPE_KEY"
# Descargar el SVG
curl -sS -o logo.svg https://homotope.example/api/v1/jobs/ID/svg \
-H "Authorization: Bearer $HOMOTOPE_KEY"
# El mismo resultado en PDF, EPS o DXF (recorte; tolerance: curvas aplanadas, en px)
curl -sS -OJ "https://homotope.example/api/v1/jobs/ID/result?format=dxf&tolerance=0.05" \
-H "Authorization: Bearer $HOMOTOPE_KEY"
# Separaciones: una capa por color (SVG por capas, capas DXF; ZIP para PDF y EPS)
curl -sS -OJ "https://homotope.example/api/v1/jobs/ID/result?format=svg&layers=1" \
-H "Authorization: Bearer $HOMOTOPE_KEY"
# … o un archivo por color, en un ZIP
curl -sS -OJ "https://homotope.example/api/v1/jobs/ID/result?format=pdf&layers=zip" \
-H "Authorization: Bearer $HOMOTOPE_KEY"
# ¿Listo para el recorte? Comprobar el DXF (herramienta de 0,3 mm, bordes compartidos fusionados)
curl -sS "https://homotope.example/api/v1/jobs/ID/cutcheck?tool_mm=0.3&merge_shared=true" \
-H "Authorization: Bearer $HOMOTOPE_KEY"
# → {"id":"…","report":{"blocking":0,"check":2,"totals":{…},"issues":[…],…}}
# Últimos cálculos (20 por defecto, 100 como máximo; "nextCursor" para la página siguiente)
curl -sS "https://homotope.example/api/v1/jobs?limit=50" \
-H "Authorization: Bearer $HOMOTOPE_KEY"
# Cancelar un cálculo en cola, o eliminar un resultado
curl -sS -X DELETE https://homotope.example/api/v1/jobs/ID \
-H "Authorization: Bearer $HOMOTOPE_KEY"
Preajustes: logo, illustration, pixel-art,
line-art, centerline (trazo único: trazados stroke de
una sola pasada, para láser, plóter o bordado), photo. Los ajustes aceptados y
sus límites son los del panel «Avanzado» del taller, descritos en el documento OpenAPI
(JobOptions).
Formatos de resultado
- Cada formato se produce al vuelo a partir del SVG del cálculo: misma geometría, mismos colores, mismo orden. 1 px = 1 pt (1/72 de pulgada).
- PDF 1.4 y EPS 3.0: vectoriales, página del tamaño de la imagen. El EPS no admite transparencia.
-
DXF R12 (corte láser, plóteres, Cricut): contornos cerrados, agujeros
incluidos, una capa por color con nombre en hexadecimal (
FF8800), en milímetros. El DXF no tiene relleno: para el corte cuenta el contorno; mejor el modo «Recortado» (sin superposición). El rectángulo de fondo se omite (haría un marco):include_background=truelo conserva.merge_shared=truefusiona los bordes compartidos: un borde compartido por dos formas vecinas se escribe, y por tanto se corta, una sola vez. -
Separaciones (
layers):layers=1da una capa por color (SVG con capas de Inkscape e Illustrator, DXF con capas, un ZIP de un archivo por color para PDF y EPS);layers=zipda siempre un ZIP de un archivo por color, con el nombre<name>-<hex>.<ext>. Cada archivo es la zona VISIBLE de su color (archivos disjuntos): el cálculo debe usar el modo «Recortado», si no422(stacked_separations). El SVG por capas sigue el orden de pintado (una capa por cada serie de formas del mismo color). -
Paleta impuesta (
paletteenoptions): de 2 a 64 colores hexadecimales distintos; cada píxel toma el más cercano (OKLab). Tramado y umbral de cobertura:options.quantize.fixedPalette(documento OpenAPI). No se proporciona ninguna tabla de colores: envía la tuya. -
Conversión limitada a 4 MB de SVG; por encima, descarga el SVG. 60 conversiones (PDF, DXF,
EPS) por hora y por clave, 120 por cuenta;
503(busy) si ya hay una conversión de la cuenta en curso.
¿Listo para el recorte?
GET /api/v1/jobs/{id}/cutcheck analiza el DXF que produciría
…/result?format=dxf (mismos tolerance,
include_background, merge_shared), en solo lectura, y devuelve un
informe JSON:
-
Bloqueante (
blocking): contorno abierto, dos contornos que se cruzan (crossing), un contorno que se corta a sí mismo (self-intersection), contornos superpuestos. -
A revisar (
check): detalle más fino que la herramienta (thin,tool_mm, 0,2 mm por defecto), islote pequeño (island, por debajo deisland_mm2, 1 mm² por defecto), contorno de más de 1000 nodos (nodes). -
Cada problema tiene una posición (
box, en px de la imagen, con la Y hacia abajo), una medida (value, en mm, mm², nodos o puntos) y un mensaje legible en el idioma de la cabeceraAccept-Language(inglés por defecto). Los trazos de línea central (preajustecenterline) son abiertos por naturaleza: nunca se señalan. -
Información (
info, fuera deblockingycheck): un borde compartido por dos formas vecinas cortado dos veces (overlap), que se corrige conmerge_shared=true. -
Mismos límites y mismas plazas que las conversiones (usa el mismo hilo). Un análisis muy
pesado se detiene limpiamente:
200contruncated: true(totales mínimos), o422(too_complex).
Derechos
- No hay prueba gratuita por la API ni por el MCP: las pruebas de cálculo del mes están reservadas al taller.
- Cada cálculo consume primero la cuota Pro del mes y después un crédito (ver tarifas). Un cálculo que falla, o que se cancela antes de empezar, se devuelve.
-
Sin cuota Pro ni créditos restantes, el envío se rechaza con
402(payment_required) antes de leer la imagen. Una cuenta gratuita puede crear una clave: sus envíos reciben402hasta que tenga Pro o créditos. - Mismos formatos (PNG, JPEG, 80 MB como máximo) y mismo límite de píxeles que el taller.
Límites
- 60 solicitudes por minuto por clave (todas las rutas) y 120 solicitudes por minuto por cuenta, sumando todas las claves.
-
30 cálculos por hora por clave: por encima,
429con la cabeceraRetry-After(segundos). Un envío rechazado no cuenta. -
1 cálculo en curso y 3 en cola por clave: por encima,
429(too_many_jobs) conRetry-After: 10; espera a que termine un cálculo. -
30 rechazos
401por dirección IP en 15 minutos (clave ausente o no válida): por encima,429. Comprueba tu clave antes de reintentar. - 10 claves activas como máximo por cuenta; una clave revocada queda revocada para siempre.
Errores
Todo error tiene la forma {"error": {"code": "…", "message": "…"}}, con un
mensaje legible en el idioma de la cabecera Accept-Language (inglés por
defecto); básate en el code.
| Estado | Códigos | Qué hacer |
|---|---|---|
| 401 | invalid_api_key |
Clave ausente, desconocida o revocada. |
| 402 | payment_required |
Sin cuota Pro ni créditos restantes: compra un paquete o pásate a Pro. |
| 404 | not_found |
Cálculo desconocido (o de otra cuenta). |
| 408 | upload_timeout |
Envío demasiado largo o demasiado lento: el límite es max(60 s, tamaño anunciado ÷ 256 KB/s) y el caudal debe mantenerse en 32 KB/s como mínimo. Comprueba la conexión y vuelve a intentarlo. |
| 409 | not_ready |
SVG pedido demasiado pronto: consulta hasta done. |
| 410 | gone |
Resultado eliminado (conservación o eliminación). |
| 413 |
payload_too_large, too_large,
quota_exceeded
|
Archivo demasiado pesado, imagen demasiado grande o almacenamiento lleno. |
| 415 | unsupported_media_type |
Ni PNG ni JPEG (firma del archivo, nunca su nombre ni su tipo declarado). |
| 422 |
stacked_separations, too_complex,
unconvertible
|
Un archivo por color pedido sobre un resultado apilado (elige el modo «Recortado»); conversión o comprobación de recorte demasiado larga o pesada (simplifica el trazado); resultado que no se puede convertir. Reintentar tal cual no servirá de nada. |
| 429 |
rate_limited, too_many_jobs,
too_many_uploads
|
Espera el plazo de Retry-After, sin reintentar en bucle. |
| 503 | busy, storage_unavailable, unavailable |
Plazas de conversión ocupadas (busy, con Retry-After) o
servicio no disponible temporalmente: vuelve a intentarlo más tarde.
|
Servidor MCP (agentes de IA)
Homotope expone un servidor MCP (Model Context Protocol), una fachada fina de esta API, sobre el transporte «Streamable HTTP»:
-
URL:
https://homotope.example/mcp - Cabecera:
Authorization: Bearer hmt_live_…(tu clave de API) - Mismos derechos, mismos límites y mismos créditos que la API.
Ejemplo de configuración para un cliente MCP (la clave se queda contigo):
{
"mcpServers": {
"homotope": {
"type": "http",
"url": "https://homotope.example/mcp",
"headers": { "Authorization": "Bearer hmt_live_…" }
}
}
}
Herramientas ofrecidas al agente:
-
vectorize_image: una imagen enimage_base64(unos 6 MB como máximo) o unaimage_urlhttps pública, másfilename,preset,palette(colores impuestos, en hexadecimal) yoptionsopcionales; devuelve{ job_id, state }enseguida, sin esperar a que termine el cálculo. get_job: el estado de un cálculo (job_id).-
get_svg: el SVG de un cálculo terminado (image/svg+xml), o un error claro si no está listo. -
get_result: el resultado ensvg,pdf,dxfoeps(format, ytolerancepara DXF);layers: separaciones (true, o"zip"para un archivo por color); PDF y ZIP llegan codificados en base64. -
check_cut: «¿listo para el recorte?», el informe de comprobación del DXF (tool_mm,island_mm2,merge_shared…), comoGET /api/v1/jobs/{id}/cutcheck. list_vectorizations: los últimos cálculos (limit).
Un error de herramienta lleva el estado y el código de la API (402, 413, 429…) y un mensaje
legible. Una image_url debe ser pública: https, puerto 443, sin dirección
privada ni local, 3 redirecciones como máximo, leída en 15 segundos.
Sin OAuth: basta con la clave de API. Sin transporte stdio: el servidor es
remoto. El servidor no conserva ninguna sesión entre dos solicitudes.