HiAPI
Blog

Tutorial

Cómo usar 851-labs/background-remover a través de la API de hiapi: curl, Python y una solicitud ejecutable

Sep 5, 2026
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:

  1. 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.
  2. Los campos sobrantes se rechazan, no se ignoran. Si arrastras un campo format o size desde el payload de otro modelo, la tarea devolverá 400 INVALID_REQUEST: <root>: additional properties 'format' not allowed antes 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

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 →

Empieza a crear con artefactos de IA persistentes

Consigue tu API key y llama a modelos de imagen, vídeo y audio a través de una única API basada en tasks.

Leer la documentación de la API