Tutorial
Cómo usar 851-labs/background-remover a través de la API de hiapi: curl, Python y una solicitud ejecutable
851-labs/background-remover convierte fotos de productos, retratos o mascotas en un PNG transparente con una sola llamada a la API: sin prompt, sin máscara y sin ajustes de relación de aspecto. Este artículo presenta la estructura exacta de la solicitud, un comando curl ejecutable, un script de Python listo para usar en tu backend y el error de esquema en el que es más fácil tropezar.
Preparación
- Una cuenta de hiapi y una API key obtenida desde la consola.
- Una imagen alojada en una URL HTTPS pública. La API de tareas recibe una URL, no una carga de archivo; si tu imagen de origen solo existe localmente, primero súbela a cualquier CDN o almacenamiento de objetos.
Todas las solicitudes se envían al endpoint unificado de tareas:
POST https://api.hiapi.ai/v1/tasks
Authorization: Bearer sk-<your-key>
Content-Type: application/json
Estructura de la solicitud (y la única regla que debes recordar)
El id del modelo es 851-labs/background-remover; pásalo tal cual. Su esquema de input tiene un solo campo:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
image_url |
string | Sí | Debe coincidir con ^https?://[^\s]+$: una URL http(s) accesible directamente. |
Eso es todo el esquema. Antes de escribir cualquier código, hay dos cosas que conviene saber:
- No hay campos de prompt, mask, background-color ni aspect-ratio. Este endpoint hace una sola cosa: separar primer plano y fondo, y nada más. Si después necesitas recolorear o cambiar el tamaño, tendrás que llamar a otro modelo.
- Los campos sobrantes se rechazan, no se ignoran. Si arrastras un campo
formatosizedesde el payload de otro modelo, la tarea devolverá400 INVALID_REQUEST: <root>: additional properties 'format' not allowedantes incluso de comenzar.
Ejemplo mínimo ejecutable: curl
Crear la tarea:
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "851-labs/background-remover",
"input": {
"image_url": "https://your-cdn.example.com/product-shot.jpg"
}
}'
Cuando el envío se realiza correctamente, se devuelve un id de tarea dentro de data:
{"code": 200, "data": {"taskId": "tk-hiapi-..."}}
Consultar el resultado:
curl https://api.hiapi.ai/v1/tasks/tk-hiapi-... \
-H "Authorization: Bearer sk-<your-key>"
Mientras se ejecuta, data.status pasa por queued → handling → archiving. Cuando termina, cambia a "success" y el PNG transparente aparece en data.output:
{
"code": 200,
"data": {
"status": "success",
"output": [{"url": "https://.../result.png", "expireAt": "..."}]
}
}
La URL de salida tiene validez temporal (fíjate en expireAt). Descarga los bytes del archivo inmediatamente después de que la tarea tenga éxito; no hagas hotlinking ni guardes la URL original de forma permanente.
Python listo para producción: enviar, consultar, descargar
import time
import requests
API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def remove_background(image_url: str) -> bytes:
# 1. Crear la tarea
resp = requests.post(API_BASE, headers=HEADERS, json={
"model": "851-labs/background-remover",
"input": {"image_url": image_url},
}, timeout=60)
body = resp.json()
if resp.status_code != 200 or not (body.get("data") or {}).get("taskId"):
raise RuntimeError(f"create failed [{resp.status_code}]: {body}")
task_id = body["data"]["taskId"]
# 2. Consultar hasta alcanzar un estado terminal
deadline = time.time() + 300
while time.time() < deadline:
task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS,
timeout=30).json().get("data") or {}
if task.get("status") == "success":
outputs = task.get("output") or []
if not outputs or not outputs[0].get("url"):
raise RuntimeError(f"task {task_id} succeeded but returned no output URL")
# 3. Descargar de inmediato: la URL caduca
png = requests.get(outputs[0]["url"], timeout=120)
png.raise_for_status()
return png.content
if task.get("status") == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(3)
raise TimeoutError(f"task {task_id} still running after 300s")
if __name__ == "__main__":
png = remove_background("https://your-cdn.example.com/product-shot.jpg")
with open("cutout.png", "wb") as f:
f.write(png)
print(f"saved cutout.png ({len(png)} bytes)")
La eliminación de fondo es una tarea de imagen ligera y normalmente termina mucho antes del límite de 300 segundos; ese tiempo de espera es solo una red de seguridad, no el tiempo de ejecución esperado.
Usar callback en lugar de sondeo
Para backends web, se recomienda registrar un callback al crear la tarea en lugar de sondear dentro del manejador de la solicitud. El objeto callback va en el nivel superior, al mismo nivel que model:
{
"model": "851-labs/background-remover",
"input": { "image_url": "https://your-cdn.example.com/product-shot.jpg" },
"callback": {
"url": "https://your-app.example.com/hooks/hiapi",
"when": "final"
}
}
callback.when solo admite "final": recibirás exactamente un POST cuando la tarea entre en success o fail, y no eventos de progreso. El manejador debe usar taskId como clave para evitar procesar dos veces un webhook entregado de forma duplicada, y conviene revisar periódicamente GET /v1/tasks/<id> para detectar ids que tu endpoint nunca confirmó.
Manejo de errores: los que realmente importan
400 INVALID_REQUEST al crear: el mensaje de error indica el campo exacto:
| Mensaje | Causa |
|---|---|
invalid input: image_url: missing required field "image_url" |
input está vacío o el nombre de la clave está mal escrito |
image_url: 'not-a-url' does not match pattern '^https?://[^\s]+$' |
El valor no es una URL http(s) con formato correcto |
<root>: additional properties 'format' not allowed |
Enviaste un campo que este modelo no acepta |
Estos errores son permanentes: reintentar el mismo payload fallará siempre. Corrige el campo y vuelve a enviar.
401 permission_denied al crear: el problema está en la key, no en el cuerpo de la solicitud:
{"error": {"code": "permission_denied", "message": "...", "request_id": "...", "type": "hiapi_error"}}
Revisa en la consola los permisos de modelo de esa key.
La tarea devuelve status: "fail": la creación tuvo éxito pero la ejecución en sí falló (normalmente porque el backend no pudo obtener image_url). Lee data.error.code / message; este tipo de fallo se puede reintentar de forma segura una vez con retroceso exponencial.
Hacer GET de un id de tarea desconocido o caducado devuelve 404 con {"code": 404, "data": null, "message": "task not found"}: en cualquier barrido de reconciliación debe tratarse como estado terminal, no como "aún en espera".
Siguientes pasos
- Página del modelo 851-labs/background-remover: ejemplos en vivo y precios actuales.
- Eliminar el fondo de una imagen con edición basada en prompts: alternativa basada en Seedream para casos en los que no solo quieras quitar el fondo, sino cambiarlo.
- Documentación de la API de tareas asíncronas de hiapi: referencia completa de creación, sondeo y callbacks.
- Documentación de autenticación de hiapi: configuración de la API key y formato de las cabeceras.
- Precios: tarifas actuales por imagen.
Preguntas frecuentes
¿Necesito un prompt?
No. Basta con proporcionar una image_url; el modelo separa por sí mismo el primer plano del fondo.
¿La salida es realmente transparente? Sí: el resultado es un PNG con canal alfa, listo para componerse sobre cualquier fondo.
¿Puedo cambiar la relación de aspecto, el color o el fondo en la misma llamada? No. Este endpoint solo elimina el fondo. Si necesitas recolorear, cambiar el tamaño o reemplazar el fondo, usa este PNG transparente como entrada y encadena una llamada a un modelo de edición de imágenes.
¿Por qué recibo "additional properties '...' not allowed"?
El esquema solo acepta un campo, image_url. Cualquier campo arrastrado desde el payload de otro modelo (format, size, background_color, el que sea) se rechaza directamente en lugar de ignorarse en silencio.
¿Cómo debo guardar el resultado?
Descárgalo inmediatamente después de que la tarea alcance status: "success". La URL de salida es una URL firmada con expireAt; no sirve para hotlinking a largo plazo.
¿Cuánto cuesta? Se cobra por uso, por imagen. Consulta las tarifas actuales en la página de precios.
Artículos relacionados
Ver todos los artículos →-
Tutorial
Cómo llamar a hailuo-2.3-fast/image-to-video a través de la API de HiAPI: práctica con curl y Python
La primera solicitud ejecutable del nivel rápido y de bajo coste de imagen a vídeo: del ID del modelo a la descarga del MP4
-
Tutorial
Cómo llamar a hailuo-2.3/text-to-video mediante la API de HiAPI: curl, Python y ejemplos de solicitud ejecutables
-
Tutorial
Uso de Kandinsky 6.0 Pro texto a video en HiAPI: tutorial con curl y Python
Demostración práctica centrada en la solicitud: construir la llamada de prompt a clip de video, enviar la solicitud, sondear el estado de finalización y descargar el resultado