Clasificacion por lotes
Endpoint de clasificacion por lotes - clasifique hasta 1 000 productos en una sola solicitud con seguimiento de progreso en tiempo real.
El endpoint de clasificacion por lotes permite clasificar hasta 1 000 productos en una sola solicitud. Al igual que la clasificacion individual, el procesamiento es asincrono con seguimiento de progreso en tiempo real.
Crear un lote de clasificacion
POST
/v1/classify/batchParametros del cuerpo (JSON)
| Parametro | Tipo | Requerido | Descripcion |
|---|---|---|---|
items | object[] | Si | Lista de productos a clasificar (1 a 1 000) |
items[].id | string | No | Identificador personalizado para correlacionar resultados |
items[].content | string | Si | Descripcion del producto |
items[].image_urls | string[] | No | URLs de imagenes del producto |
locale | "fr" | "en" | "es" | No | Idioma de las respuestas (por defecto: "fr") |
Ejemplo de solicitud
curl -X POST https://api.thetradehub.eu/v1/classify/batch \
-H "X-API-Key: th_live_su_clave_api" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"id": "SKU-001",
"content": "Auriculares Bluetooth inalambricos con cancelacion activa de ruido"
},
{
"id": "SKU-002",
"content": "Camiseta de algodon organico para hombre, talla L"
},
{
"id": "SKU-003",
"content": "Aceite de oliva virgen extra, botella de vidrio 750ml, origen Espana"
}
],
"locale": "es"
}'import httpx
client = httpx.Client(
base_url="https://api.thetradehub.eu",
headers={"X-API-Key": "th_live_su_clave_api"},
)
response = client.post("/v1/classify/batch", json={
"items": [
{"id": "SKU-001", "content": "Auriculares Bluetooth inalambricos con cancelacion activa de ruido"},
{"id": "SKU-002", "content": "Camiseta de algodon organico para hombre, talla L"},
{"id": "SKU-003", "content": "Aceite de oliva virgen extra, botella de vidrio 750ml, origen Espana"},
],
"locale": "es",
})
batch = response.json()
print(f"Lote creado: {batch['id']} - {batch['total']} productos")const response = await fetch("https://api.thetradehub.eu/v1/classify/batch", {
method: "POST",
headers: {
"X-API-Key": "th_live_su_clave_api",
"Content-Type": "application/json",
},
body: JSON.stringify({
items: [
{ id: "SKU-001", content: "Auriculares Bluetooth inalambricos con cancelacion activa de ruido" },
{ id: "SKU-002", content: "Camiseta de algodon organico para hombre, talla L" },
{ id: "SKU-003", content: "Aceite de oliva virgen extra, botella de vidrio 750ml, origen Espana" },
],
locale: "es",
}),
});
const batch = await response.json();
console.log(`Lote creado: ${batch.id} - ${batch.total} productos`);Respuesta (202 Accepted)
{
"id": "batch_f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"status": "processing",
"total": 3,
"completed": 0,
"failed": 0,
"progress": 0,
"created_at": "2026-02-24T10:30:00Z",
"updated_at": "2026-02-24T10:30:00Z"
}Obtener el estado de un lote
GET
/v1/classify/batch/{batch_id}Parametros de ruta
| Parametro | Tipo | Descripcion |
|---|---|---|
batch_id | string (UUID) | Identificador del lote devuelto en la creacion |
Estados posibles
| Estado | Descripcion |
|---|---|
processing | El lote esta siendo procesado |
completed | Todos los elementos han sido procesados |
partial | El lote termino pero algunos elementos fallaron |
failed | El lote completo fallo |
Ejemplo de polling
curl https://api.thetradehub.eu/v1/classify/batch/batch_f1e2d3c4-b5a6-7890-abcd-ef1234567890 \
-H "X-API-Key: th_live_su_clave_api"import httpx
import time
client = httpx.Client(
base_url="https://api.thetradehub.eu",
headers={"X-API-Key": "th_live_su_clave_api"},
)
batch_id = "batch_f1e2d3c4-b5a6-7890-abcd-ef1234567890"
delay = 2
while True:
response = client.get(f"/v1/classify/batch/{batch_id}")
batch = response.json()
print(f"Progreso: {batch['progress'] * 100:.0f}% ({batch['completed']}/{batch['total']})")
if batch["status"] in ("completed", "partial"):
for item in batch["items"]:
if item["status"] == "completed":
hs = item["result"]["classification"]["rankings"][0]["hs_code"]
print(f" {item['id']} → {hs}")
else:
print(f" {item['id']} → Error: {item.get('error')}")
break
elif batch["status"] == "failed":
print(f"Error del lote: {batch.get('error')}")
break
time.sleep(delay)
delay = min(delay * 1.5, 10)const API_KEY = "th_live_su_clave_api";
const batchId = "batch_f1e2d3c4-b5a6-7890-abcd-ef1234567890";
async function pollBatch(batchId) {
let delay = 2000;
while (true) {
const response = await fetch(
`https://api.thetradehub.eu/v1/classify/batch/${batchId}`,
{ headers: { "X-API-Key": API_KEY } }
);
const batch = await response.json();
console.log(`Progreso: ${Math.round(batch.progress * 100)}% (${batch.completed}/${batch.total})`);
if (batch.status === "completed" || batch.status === "partial") {
for (const item of batch.items) {
if (item.status === "completed") {
const hs = item.result.classification.rankings[0].hs_code;
console.log(` ${item.id} → ${hs}`);
} else {
console.log(` ${item.id} → Error: ${item.error}`);
}
}
return batch;
}
if (batch.status === "failed") {
throw new Error(batch.error);
}
await new Promise((r) => setTimeout(r, delay));
delay = Math.min(delay * 1.5, 10000);
}
}
const result = await pollBatch(batchId);Respuesta completa (status: completed)
Cada elemento contiene la misma estructura de resultado que la clasificacion individual.
{
"id": "batch_f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"status": "completed",
"total": 3,
"completed": 3,
"failed": 0,
"progress": 1.0,
"items": [
{
"id": "SKU-001",
"status": "completed",
"result": {
"classification": {
"rankings": [
{
"rank": 1,
"hs_code": "8518.30.00",
"description": "Auriculares y cascos",
"confidence": 0.94,
"gri_justification": "RGI 1 - La posicion 8518 cubre expresamente los auriculares y cascos.",
"validated": true
}
]
},
"text": "Segun las decisiones IVO de la UE y la nomenclatura TARIC...",
"session_id": "sess_abc123"
}
},
{
"id": "SKU-002",
"status": "completed",
"result": {
"classification": {
"rankings": [
{
"rank": 1,
"hs_code": "6109.10.00",
"description": "Camisetas de algodon",
"confidence": 0.97,
"gri_justification": "RGI 1 - El producto es una camiseta de algodon, expresamente cubierta por la posicion 6109.",
"validated": true
}
]
},
"text": "Clasificacion en la posicion 6109 para articulos de punto...",
"session_id": "sess_def456"
}
},
{
"id": "SKU-003",
"status": "completed",
"result": {
"classification": {
"rankings": [
{
"rank": 1,
"hs_code": "1509.10.90",
"description": "Aceite de oliva virgen",
"confidence": 0.96,
"gri_justification": "RGI 1 - La posicion 1509 cubre el aceite de oliva. Subposicion 1509.10: aceite virgen.",
"validated": true
}
]
},
"text": "Clasificacion en la posicion 1509 para aceites de oliva...",
"session_id": "sess_ghi789"
}
}
],
"created_at": "2026-02-24T10:30:00Z",
"updated_at": "2026-02-24T10:30:45Z"
}Estructura de la respuesta
| Campo | Tipo | Descripcion |
|---|---|---|
id | string | Identificador unico del lote |
status | string | Estado global del lote |
total | number | Numero total de elementos |
completed | number | Numero de elementos procesados exitosamente |
failed | number | Numero de elementos con error |
progress | number | Ratio de avance (0.0 a 1.0) |
items | object[] | Resultados por elemento - misma estructura que la clasificacion individual |
Resultados persistentes
Los resultados son accesibles de forma permanente mediante el mismo endpoint:
GET /v1/classify/batch/{batch_id}- Durante el procesamiento / primeras 24h - servido desde cache, progreso en tiempo real
- Despues de 24h - respaldo transparente a la base de datos, resultados siempre disponibles
No es necesario almacenar resultados en el cliente. Recupere cualquier batch pasado usando el batch_id original.
Buenas practicas
| Recomendacion | Detalle |
|---|---|
| Tamano del lote | Maximo 1 000 elementos por solicitud |
| Polling | Comenzar con intervalo de 2s, aumentar progresivamente |
| Identificadores | Use items[].id para correlacionar con sus datos |
| Gestion de errores parciales | Verifique el status de cada elemento en items |
| Timeout | Prever 30s + 5s por elemento para lotes grandes |
| Almacenamiento de resultados | No necesario - resultados accesibles permanentemente via batch_id |
Última actualización