cURL · API de maniquí invisible
API de maniquí invisible con cURL
En una frase
Exporta PHOTTA_API_KEY, haz un POST a https://api.photta.app/api/v1/api/v1/ghost-mannequin con el cuerpo JSON documentado, captura el ID de generación y luego ejecuta un bucle de GET en /api/v1/ghost-mannequin/{id} cada 3 segundos hasta que data.status sea completed. Combínalo con jq para extraer la URL de salida.
- Tiempo típico: 1.5–4 min
- Credits: 4 credits a 2K · 5 credits a 4K
- Procesamiento: asíncrono, polling
- Límites: 600 requests/min
- Autenticación: Bearer key
Cada cifra de esta página proviene de la documentación de la API de Photta · verificado
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/ghost-mannequin \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')
# $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed".
for i in $(seq 1 120); do
RESULT=$(curl -s "https://api.photta.app/api/v1/ghost-mannequin/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY")
STATUS=$(echo "$RESULT" | jq -r '.data.status')
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && echo "generation failed" && exit 1
sleep 3
done
echo "$RESULT" | jq -r '.data.output_url'const res = await fetch("https://api.photta.app/api/v1/ghost-mannequin", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
}),
});
const { data } = await res.json(); // data.id, data.status
async function waitFor(id) {
for (let attempt = 0; attempt < 120; attempt++) {
const res = await fetch(`https://api.photta.app/api/v1/ghost-mannequin/${id}`, { headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}` } });
const { data } = await res.json();
if (data.status === "completed") return data.output_url;
if (data.status === "failed") throw new Error(data.error_message ?? "generation failed");
await new Promise((r) => setTimeout(r, 3000));
}
throw new Error("timed out after 6 minutes");
}import os, requests
res = requests.post(
"https://api.photta.app/api/v1/ghost-mannequin",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_image": "https://cdn.yourstore.com/products/jacket-front.jpg",
"back_image": "https://cdn.yourstore.com/products/jacket-back.jpg",
"image_side": "front",
"angle": "side",
"style": "3d",
"background_color": "white",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "closed front, cream interior lining",
"brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67"
},
)
data = res.json()["data"] # data["id"], data["status"]
import time
def wait_for(job_id):
for _ in range(120):
res = requests.get(f"https://api.photta.app/api/v1/ghost-mannequin/{job_id}", headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"})
data = res.json()["data"]
if data["status"] == "completed":
return data["output_url"]
if data["status"] == "failed":
raise RuntimeError(data.get("error_message", "generation failed"))
time.sleep(3)
raise TimeoutError("timed out after 6 minutes")De un vistazo
De un vistazo
- Endpoint
- POST /api/v1/ghost-mannequin
- Autenticación
- Bearer API key
- Procesamiento
- Asíncrono — realiza polling al endpoint de estado
- Tiempo típico
- 1.5–4 min
- Credits
- 4 credits a 2K · 5 credits a 4K
- Relaciones de aspecto
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Límites de entrada
- Hasta 10 MB por imagen; JPEG, PNG, WebP
- Idempotente
- No
Cómo funciona
Cinco pasos en terminal, cero dependencias más allá de curl y jq.
Paso 1
Regístrate y genera una clave
Ve a ai.photta.app, abre la pestaña Developers y haz clic en Generate API key. Las claves en producción comienzan con `photta_live_`.
Paso 2
Exportar la clave
Añade `export PHOTTA_API_KEY="photta_live_xxx"` en tu perfil de shell o en un archivo `.envrc` para que cada llamada posterior de curl la detecte automáticamente.
curl --version # macOS, Linux, WSL and Windows 10+ ship it export PHOTTA_API_KEY="photta_live_xxxxx"Paso 3
Fijar la URL base
`export PHOTTA_BASE_URL="https://api.photta.app/api/v1"` mantiene los comandos de curl breves.
export PHOTTA_BASE_URL="https://api.photta.app/api/v1" export AUTH_HEADER="Authorization: Bearer $PHOTTA_API_KEY"Paso 4
Enviar y hacer polling
Haz un POST a `$PHOTTA_BASE_URL/api/v1/ghost-mannequin` para obtener un ID, luego ejecuta en bucle `curl $PHOTTA_BASE_URL/api/v1/ghost-mannequin/{id}` cada 3 segundos. Pasa la respuesta por pipe a jq para extraer `.data.status` de forma limpia.
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/ghost-mannequin \ -H "Authorization: Bearer $PHOTTA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "product_image": "https://cdn.yourstore.com/products/jacket-front.jpg", "back_image": "https://cdn.yourstore.com/products/jacket-back.jpg", "image_side": "front", "angle": "side", "style": "3d", "background_color": "white", "resolution": "2K", "aspect_ratio": "3:4", "user_instruction": "closed front, cream interior lining", "brand_label_id": "7cc9f988-068b-44cd-8004-22f486b10e67" }') ID=$(echo "$RESPONSE" | jq -r '.data.id') # $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed". for i in $(seq 1 120); do RESULT=$(curl -s "https://api.photta.app/api/v1/ghost-mannequin/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY") STATUS=$(echo "$RESULT" | jq -r '.data.status') [ "$STATUS" = "completed" ] && break [ "$STATUS" = "failed" ] && echo "generation failed" && exit 1 sleep 3 done echo "$RESULT" | jq -r '.data.output_url'Paso 5
Guardar el resultado
Cuando el trabajo termine, extrae `.data.output_url` con jq y haz `curl -o` de los bytes al almacenamiento local — listo para el siguiente paso de tu pipeline.
Errores
- 400
invalid_request_error - The request is malformed or contains invalid parameters.
- 401
authentication_error - The API key is missing, invalid, or expired.
- 402
insufficient_credits_error - Your account does not have enough credits.
- 404
not_found_error - The requested resource does not exist.
- 409
conflict_error - The request conflicts with current state — e.g. your concurrent-batch cap is reached.
- 429
rate_limit_error - Too many requests. Slow down and retry.Retry-After: 30
- 500
api_error - An internal server error occurred. Retry later.
case "$STATUS_CODE" in
402) echo "insufficient_credits_error — top up before retrying" ;;
429) echo "rate_limit_error — wait the Retry-After seconds (30 by default)" ;;
4??) echo "$BODY" | jq '.error.type, .error.message' ;;
5??) echo "api_error — retry with backoff" ;;
esacLímites
- 600 solicitudes por minuto por API key (Ventana fija; el límite es el mismo en todos los planes)
- Un 429 incluye Retry-After: 30 segundos
- Hasta 10 MB por imagen
- Formatos: JPEG, PNG, WebP
- Lotes simultáneos por plan: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Solo polling — la API no envía webhooks.
Por qué cURL sigue siendo la forma más rápida de verificar una API
- Cero instalación: cURL viene integrado en todos los sistemas operativos principales
- Se combina con jq para pipelines automatizados (CI, cron, hooks de shell)
- La forma más rápida de hacer un smoke test de un endpoint antes de integrarlo en el código
- Cada comando de esta página se puede pegar en cualquier shell POSIX
Lo que no hace
- El bucle de polling bloquea la terminal — migra a Node o Python para usar workers en paralelo
- El polling es la única señal de finalización; la API no envía webhooks
- Los usuarios del Símbolo del sistema de Windows deben ejecutar WSL o el curl.exe de PowerShell
Preguntas frecuentes de desarrolladores
¿Existe una herramienta de CLI de Photta?
Aún no — pero cURL junto con un wrapper en bash de quince líneas resuelve la mayor parte. La documentación prioriza ejemplos con cURL porque cualquier lenguaje puede ejecutar un subproceso, y la shell es el común denominador en los pipelines de CI.
¿Necesito jq para usar la API?
No estrictamente — pero los pipelines con scripts son mucho más fáciles con él. jq te permite extraer `.data.id`, `.data.status` y `.data.output_url` de la respuesta JSON sin tener que parsearla a mano. Instálalo con `brew install jq` en macOS o `apt install jq` en Debian/Ubuntu.
¿Cómo me autentico con curl?
Añade `-H "Authorization: Bearer $PHOTTA_API_KEY"` a cada petición. Mantén la clave en una variable de entorno, nunca la incluyas directamente en un script que subas a un repositorio. `curl --oauth2-bearer` también funciona, pero la forma con cabecera explícita es más clara en la documentación y en los logs.
¿Puedo usar scripts basados en curl en producción?
Para backfills por lotes puntuales y cron jobs, sí — miles de equipos actualizan catálogos de esta forma. Para una aplicación de larga duración, un lenguaje real suele ser mejor porque obtienes un manejo adecuado de errores, reintentos y observabilidad. Los ejemplos con curl de esta página siguen siendo válidos incluso después de portarlos a Node o Python; la estructura de la petición es la misma.
¿Cómo hago polling desde un bucle de bash?
Usa `for i in $(seq 1 120); do … ; sleep 3; done` con la comprobación de estado dentro del cuerpo del bucle. Sal del bucle cuando `.data.status` sea `completed` o `failed`. El ejemplo de código de esta página muestra el patrón exacto, incluyendo un límite máximo estricto para que un trabajo atascado no cuelgue el script para siempre.
¿Cómo leo las respuestas de error en curl?
Usa `curl -w "\n%{http_code}"` para capturar el código de estado HTTP junto con el cuerpo JSON. Aplica condiciones según el estado: 402 para credits insuficientes, 429 para rate limits (respeta el valor de Retry-After), 5xx para errores transitorios del servidor. El cuerpo del error siempre incluye los campos `error.code` y `error.message`.
Páginas relacionadas
Node.js
API de maniquí invisible en Node.js
Llama a aPI de maniquí invisible de Photta desde un backend de Node.js con fetch nativo. Sin SDKs: guarda tu key, envía el trabajo y haz polling para obtener el resultado.
LeerPython
API de maniquí invisible en Python
Llama a aPI de maniquí invisible de Photta en Python con la biblioteca requests. Wrapper de treinta líneas, compatible con async mediante httpx, funciona en Django, FastAPI y Celery.
LeerCapacidades
API de maniquí invisible para fotos de producto con efecto maniquí invisible
Endpoint de maniquí invisible con IA. Elimina el maniquí de una foto de la prenda y preserva el detalle interior. 3D o flat-lay, procesamiento por lotes, 4 credits a 2K.
LeerConstruir
Automatiza la extracción de ghost mannequin para tu catálogo
Receta de automatización nocturna de catálogo: extrae las actualizaciones de productos de ayer, envíalas por lotes a la API de ghost-mannequin de Photta, haz polling del lote principal y persiste los datos en tu base de datos.
LeerGuía rápida
Tu primera imagen de Photta en menos de cinco minutos.
Regístrate, genera una API key, ejecuta tu primera llamada cURL, haz polling hasta que se complete y guarda el resultado. Cinco pasos, documentados de principio a fin.
LeerReferencia
Precios de la API de Photta
Cuánto cuesta en credits cada endpoint de Photta API a 2K y 4K, cómo funcionan los cobros y reembolsos, y qué endpoints son gratuitos. Sin precio monetario por imagen.
Leer
Cada cifra de esta página proviene de la documentación de la API de Photta · verificado
Prueba la API en cinco minutos
Genera una API key de Photta, pega el snippet de cURL de arriba y tendrás tu primera imagen con modelo antes de que termine de prepararse el café.
- 1.5–4 min
- 4 credits a 2K · 5 credits a 4K
- asíncrono, polling
- 600 requests/min
- Bearer key