Tareas
Resumen
Las tareas permiten que una IA como ChatGPT o Claude ejecute trabajo en su propio servidor (un worker). Diga "Haz un pedido de 30 unidades de A-1042 en nuestro ERP" y la IA envía el trabajo a su worker y le muestra el resultado en la conversación.
- 3Min API solo entrega la tarea y registra su estado; el trabajo real lo hace el worker
- Un worker es un servidor HTTP que usted mismo opera
Cuándo usarlo
- Para que sistemas internos hagan algo — registrar un pedido en el ERP, consultar stock, buscar en una base de datos interna
- Trabajo que lleva tiempo — generar informes, conversiones masivas (hasta 24 horas)
- Scripts que solo funcionan en su propio equipo — añada una URL pública con un túnel (ver abajo)
Si el objetivo es guardar y recopilar datos, use un endpoint.
¿No se siente cómodo escribiendo el código del worker? Pídaselo a la IA que ya usa: "Hazme un worker de tareas de 3minapi". La IA lee el mismo contrato que esta página desde la herramienta
helpy escribe el código.
Cómo llegar aquí
- Registrar un worker: Panel → Tareas → pestaña Workers →
Registrar worker - Ver ejecuciones: Panel → Tareas → pestaña Ejecuciones
Cómo funciona
① Registrar un worker en la web (una sola vez)
② IA → task_create tarea creada, estado working
③ 3Min API → POST al worker solicitud firmada (incluye callback_url)
④ Worker → 2xx de inmediato solo significa "recibido", no es un resultado
⑤ Worker → callback_url mensajes de progreso (opcional) → completed o failed
⑥ IA → task_get lee el resultado
| Dónde | Qué se hace |
|---|---|
| Panel web | Registrar, editar y eliminar workers; ver y renovar secretos; ver ejecuciones |
| Chat con la IA | Listar workers, enviar tareas, consultar estado y resultados, cancelar |
| Servidor del worker | Recibir solicitudes, hacer el trabajo, informar el resultado |
La IA no puede ver la URL ni los secretos de un worker. Ambos se gestionan solo en la web.
Registrar un worker (web)
| Campo | Descripción | Límite |
|---|---|---|
| Nombre | Obligatorio. El nombre que usa la IA. Único sin distinguir mayúsculas, no se puede cambiar | 50 caracteres |
| Descripción | Obligatorio. La IA elige el worker a partir de esta descripción | 500 caracteres |
| URL del worker | Obligatorio. La dirección que recibe las tareas por POST | 2.048 bytes |
| Encabezado de autorización / Valor de autorización | Opcional. Para la autenticación propia del worker. Con solo el valor, el encabezado es Authorization |
128 / 8.192 bytes |
- Escriba una descripción concreta. La IA solo ve el nombre y la descripción, nunca la URL. En lugar de
erp-1, escriba algo como "Registra un pedido en nuestro ERP y devuelve el número de pedido" — qué recibe y qué devuelve — para que la IA pueda elegirlo
Dos secretos en direcciones opuestas
Al registrarse se generan dos secretos automáticamente. Consúltelos en la página del worker (Panel → Tareas → pestaña Workers → seleccione un worker) con Mostrar secreto · Copiar secreto.
| Secreto | Formato | Dirección | Uso |
|---|---|---|---|
| Secreto de firma | whsec_... |
3Min API → worker | Verificar que una solicitud viene realmente de 3Min API |
| Clave de respuesta | tm_task_... |
worker → 3Min API | Se envía como Authorization: Bearer al informar |
- Los dos valores son distintos y no intercambiables. Una clave de API de endpoint (
tm_live_·tm_test_) tampoco sirve como clave de respuesta
| Cambio | Qué ocurre | Qué debe hacer el worker |
|---|---|---|
Rotar secreto de firma |
Durante 48 horas, las tareas nuevas llevan la firma nueva y la anterior. Los reintentos de tareas creadas antes de la rotación (hasta unas 5 horas) llevan solo la anterior | Conservar el secreto anterior al menos 6 horas y cambiar dentro de las 48 horas |
Regenerar clave de respuesta |
La clave anterior deja de funcionar de inmediato (incluidas las tareas en curso) | Cambiarla de inmediato |
Si vuelve a rotar dentro de las 48 horas, el secreto original deja de funcionar de inmediato. El panel solo muestra el secreto actual, así que cópielo antes de rotar si su worker debe seguir aceptando el anterior.
Implementar un worker
Cinco reglas para workers
- Devuelva 2xx en menos de 15 segundos. Haga el trabajo después de responder
- Acepte la solicitud con 2xx aunque su trabajo falle. Informe el fallo en su lugar (5xx se reintenta, otros 4xx hacen fallar la tarea al instante — vea los códigos de respuesta)
- Elimine duplicados por
task_id. La misma tarea puede llegar dos veces (at-least-once) - La verificación de la firma es opcional, pero recomendable. Sin ella, cualquiera que conozca la URL del worker puede enviar tareas falsas (verificación de firma)
- Informe el resultado a
callback_url. Envíecompletedofaileduna vez. Sin informe, la tarea pasa afaileda las 24 horas (API de informe de estado)
Solicitud de entrega
La solicitud que 3Min API envía a la URL del worker.
POST https://worker.example.com/tasks
Content-Type: application/json
webhook-id: 0199a1b2-...
webhook-timestamp: 1757650867
webhook-signature: v1,K3XkZ1n0...
X-3minapi-Task-Id: 0199a1b2-...
X-3minapi-Delivery-Attempt: 1
Authorization: Bearer xxx
| Encabezado | Contenido |
|---|---|
webhook-id |
ID de la tarea (mismo valor que task_id) |
webhook-timestamp |
Hora de envío (segundos Unix). Nueva en cada intento |
webhook-signature |
Firma. Dos valores separados por espacio durante una rotación (verificación de firma) |
X-3minapi-Task-Id |
ID de la tarea (mismo valor que webhook-id) |
X-3minapi-Delivery-Attempt |
Número de intento de entrega (desde 1) |
| Su encabezado de autorización | Solo si introdujo un encabezado y valor de autorización al registrar |
Cuerpo:
{
"type": "task.created",
"timestamp": "2026-09-12T04:21:07.123Z",
"data": {
"task_id": "0199a1b2-...",
"input": { "sku": "A-1042", "qty": 30 },
"callback_url": "https://api.3minapi.com/api/v1/tasks/0199a1b2-.../result"
}
}
| Campo | Contenido |
|---|---|
task_id |
ID de la tarea. Úselo para eliminar duplicados |
input |
El objeto JSON que envió la IA (mismos valores; el orden de las claves puede variar) |
callback_url |
La URL de informe de esta tarea. Envíe aquí el estado y los resultados |
Códigos de respuesta del worker
Solo cuenta el código de estado; el cuerpo de la respuesta se ignora.
| Respuesta | Resultado |
|---|---|
| 2xx | Aceptada. La tarea sigue en working hasta que llega un informe |
| 5xx (excepto 501 · 505), 429, tiempo de espera de 15 s, error de red | Reintento a los 30 s · 2 min · 10 min · 1 h · 4 h — 6 intentos en total (unas 5 horas). El Retry-After de un 429 solo se aplica si es más largo |
| Otros 4xx (401 · 404 · 409, …), 501, 505 | failed al instante, sin reintento |
- Devuelva 401 cuando falle la verificación de la firma. Si el secreto se introdujo mal, la primera tarea falla de inmediato y detecta el problema de configuración enseguida
Verificación de firma (opcional)
El encabezado webhook-signature es la firma. 3Min API la calcula con el secreto de firma del worker, y el worker repite el cálculo para comprobar que coincide.
contenido firmado = "{webhook-id}.{webhook-timestamp}.{cuerpo original}"
clave = el secreto de firma sin whsec_, decodificado en base64
firma = "v1," + base64( HMAC-SHA256(clave, contenido firmado) )
- Con una biblioteca oficial de Standard Webhooks bastan unas líneas (código de ejemplo). Para paquetes por lenguaje e implementación manual, consulte Verificar la firma del webhook (mismo esquema)
- Verifique sobre los bytes originales del cuerpo. Analizar el JSON y volver a serializarlo siempre falla
- La biblioteca rechaza un
webhook-timestampdesfasado más de 5 minutos (bloquea solicitudes reenviadas) - Si llegan dos firmas, basta con que cualquiera coincida (reglas de rotación)
- Si no verifica, compruebe al menos que
callback_urlempiece porhttps://api.3minapi.com/— su clave de respuesta se envía a esa dirección
API de informe de estado
Envíe el estado a la callback_url de la solicitud de entrega. Los mensajes de progreso pueden enviarse muchas veces; completed o failed se envía una vez.
POST https://api.3minapi.com/api/v1/tasks/{task_id}/result
Authorization: Bearer tm_task_...
Content-Type: application/json
- URL:
callback_urlllega con este formato y el ID de la tarea ya incluido. No la construya usted — úsela tal cual - Clave de respuesta: Clave de respuesta en la página del worker →
Copiar secreto. Guárdela en las variables de entorno del servidor del worker o similar
En curso — la tarea sigue en working y la IA ve el mensaje con task_get
{ "status": "working", "status_message": "1/2 Comprobando stock" }
Completada
{
"status": "completed",
"result": { "order_id": "PO-20260912-001" },
"status_message": "Pedido PO-20260912-001 registrado"
}
Fallida
{
"status": "failed",
"error": { "code": 1001, "message": "Sin stock", "data": { "available": 12 } }
}
| Campo | Regla |
|---|---|
status |
Uno de working · completed · failed |
status_message |
Obligatorio para working, opcional en los demás. Se recorta a partir de 256 caracteres. En failed sin mensaje se usa error.message |
result |
Obligatorio para completed. Cualquier JSON excepto null |
error |
Obligatorio para failed. code (entero) + message (cadena); data es opcional |
- El cuerpo completo debe ser de 100 KB o menos.
resultyerrornunca se recortan, así que un cuerpo mayor se rechaza con 413 - Cada informe aceptado cuenta como una llamada a la API. Envíe mensajes de progreso solo en pasos significativos
Códigos de respuesta de la API de informe de estado
| Código | Significado | Qué debe hacer el worker |
|---|---|---|
| 202 | Aceptado. Normalmente se aplica en unos segundos | — |
| 400 | Cuerpo mal formado, ID de tarea no válido, carácter NUL en una cadena | Corregir el código |
| 401 | Clave de respuesta ausente o incorrecta (incluidas claves de API de endpoint) | Revisar la clave |
| 404 | No es una tarea de este worker | Revisar callback_url |
| 409 | La tarea ya terminó (completada · fallida · cancelada) | Dejar de informar |
| 413 | Cuerpo mayor de 100 KB. No se registró nada | Si la tarea sigue en working, reducir y reenviar |
| 415 | Content-Type no es JSON | Corregir el encabezado |
| 503 | Interrupción temporal | Reenviar en breve |
Código de ejemplo (Node.js)
Requiere Node.js 18 o posterior y "type": "module" en package.json.
// npm i express standardwebhooks
import express from 'express';
import { Webhook } from 'standardwebhooks';
// El secreto de firma (whsec_...) y la clave de respuesta (tm_task_...) son valores distintos
const wh = new Webhook(process.env.TASK_SIGNING_SECRET.replace('whsec_', ''));
const CALLBACK_KEY = process.env.TASK_CALLBACK_KEY;
// task_id aceptados — en producción guárdelos en una base de datos o Redis
const seen = new Set();
const app = express();
// La firma cubre los bytes originales. Analizar el JSON antes hace fallar la verificación.
app.post('/tasks', express.raw({ type: 'application/json' }), (req, res) => {
let envelope;
try {
envelope = wh.verify(req.body, {
'webhook-id': req.header('webhook-id'),
'webhook-timestamp': req.header('webhook-timestamp'),
'webhook-signature': req.header('webhook-signature')
});
} catch {
return res.sendStatus(401);
}
const { task_id, input, callback_url } = envelope.data;
// Regla 3 — no procesar una tarea ya aceptada
if (seen.has(task_id)) return res.sendStatus(202);
seen.add(task_id);
// Regla 1 — responder primero, trabajar después
res.sendStatus(202);
run(input, callback_url);
});
async function run(input, callbackUrl) {
try {
// Mensaje de progreso — la tarea sigue en working; la IA lo ve con task_get
await report(callbackUrl, { status: 'working', status_message: '1/2 Comprobando stock' });
await checkStock(input); // ← su trabajo real
await report(callbackUrl, { status: 'working', status_message: '2/2 Registrando el pedido' });
const orderId = await createOrder(input);
// Completada — el resultado y un resumen
await report(callbackUrl, {
status: 'completed',
result: { order_id: orderId },
status_message: `Pedido ${orderId} registrado`
});
} catch (err) {
// Regla 2 — si el trabajo o un informe falla, informar failed
await report(callbackUrl, {
status: 'failed',
error: { code: 1001, message: String(err?.message ?? err) },
status_message: 'No se pudo registrar el pedido'
}).catch(console.error);
}
}
// callbackUrl — la callback_url de la solicitud de entrega, usada tal cual
async function report(callbackUrl, body) {
for (let attempt = 1; attempt <= 3; attempt++) {
const res = await fetch(callbackUrl, {
method: 'POST',
headers: {
Authorization: `Bearer ${CALLBACK_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
}).catch(() => null);
// 202 aceptado, 409 tarea ya terminada — no hace falta enviar más
if (res?.status === 202 || res?.status === 409) return;
// 400 · 401 · 404 · 413 dan el mismo resultado al reenviar
if (res && res.status !== 503) throw new Error(`report rejected: HTTP ${res.status}`);
// Solo 503 y los errores de red se reintentan tras una pausa
if (attempt < 3) await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
}
throw new Error('report failed: service unavailable');
}
app.listen(8080);
Ejecutar un worker en su propio equipo
Un worker necesita una URL pública accesible desde internet. Si el equipo está detrás de un router, use un túnel para asignar una dirección HTTPS pública a un puerto local.
cloudflared tunnel --url http://localhost:8080
ngrok http 8080
- Instalación y uso: Cloudflare Quick Tunnels · Primeros pasos con ngrok
- Añada su ruta a la dirección que se muestra (p. ej.
https://xxxx.trycloudflare.com/tasks) y regístrela como URL del worker - Las direcciones temporales sin cuenta cambian en cada ejecución. Actualice la URL del worker cada vez o use la opción de dirección fija del servicio
- Si el equipo está apagado o el túnel caído, la tarea suele pasar a
failedtras los reintentos (unas 5 horas). Un servicio que devuelve 404 para una dirección desconectada la hace fallar al instante
Enviar tareas (IA)
Con un worker registrado, puede usarlo directamente desde un chat con la IA. No necesita conocer los nombres de las herramientas.
- "Haz un pedido de 30 unidades de A-1042 en nuestro ERP"
- "¿Qué pasó con el pedido que envié antes?"
- "Cancela la tarea que acabo de enviar"
| Herramienta | Qué hace |
|---|---|
worker_list |
Nombres y descripciones de los workers registrados (sin URL ni secretos) |
task_create |
Crea una tarea a partir del nombre de un worker y un input (objeto JSON, hasta 100 KB) |
task_get |
Estado, mensaje y resultado o error de una tarea |
task_list |
Tareas recientes (sin el cuerpo de los resultados) |
task_cancel |
Cancela tareas en curso (hasta 100) |
- El mismo worker y el mismo
inputen menos de 2 minutos (hasta unos 4 minutos según el momento) devuelven la tarea existente. Las tareas completadas y canceladas se devuelven tal cual; solo una tarea fallida se crea de nuevo - Cancelar no avisa al worker. Solo se detienen los intentos de entrega pendientes; los informes posteriores de un worker que ya recibió la tarea obtienen 409
Consultar el estado
| Estado | Significado | ¿Puede cambiar? |
|---|---|---|
working |
En entrega o en proceso en el worker | Sí |
completed |
El worker informó que terminó | Final |
failed |
El worker informó un fallo, la entrega falló o pasaron 24 horas | Final |
cancelled |
Cancelada | Final |
El motivo de failed queda en status_message.
| Causa | Ejemplo de status_message |
|---|---|
| El worker informó un fallo | El mensaje del worker (o error.message si no hay) |
| Reintentos agotados | The task could not be delivered to the worker after 6 attempts (no response within 15s). |
| Respuesta de fallo inmediato | The task could not be delivered to the worker after 1 attempt (HTTP 401). |
| Pasaron 24 horas | Worker did not respond within 24 hours. |
Dónde consultarlo:
- IA —
task_get·task_list. Elresultdel worker se entrega tal cual, sin resumir - Web — pestaña Ejecuciones. Filtre por periodo (7 · 30 · 60 días; 7 en Free) y estado, y haga clic en una fila para ver entrada, resultado, error y entrega. Si la entrega falló definitivamente, Entrega muestra intentos, última respuesta y motivo
Límites
| Elemento | Valor |
|---|---|
| Workers | 1 en Free / ilimitados en planes de pago |
| Tareas · ejecuciones simultáneas | Ilimitadas (dentro de su cuota mensual de llamadas a la API) |
| Plazo | 24 horas desde la creación — después, failed (se comprueba cada hora, así que hasta unas 25 horas) |
| Conservación del historial | Al menos 60 días en planes de pago / en Free, los workers y sus ejecuciones se eliminan 7 días después de registrar el worker |
Tamaño de input |
100 KB |
| Cuerpo del informe | 100 KB (status_message se recorta a 256 caracteres) |
| Tiempo de espera de entrega · reintentos | 15 segundos · 6 intentos en unas 5 horas |
| Gracia de rotación del secreto de firma | 48 horas |
| Regeneración de la clave de respuesta | La clave anterior deja de funcionar de inmediato |
| Cómputo de llamadas a la API | Una llamada correcta a una herramienta de tareas y un informe aceptado cuentan 1 cada uno. Entregas y reintentos cuentan 0. Los informes se aceptan aunque se supere la cuota |
| Garantía de entrega | At-least-once (la misma tarea puede llegar dos veces) |
Privacidad
- El
resulty elerrorde un worker llegan a la conversación con la IA sin enmascarar, tal cual - 3Min API no detecta datos personales dentro de JSON libre, así que no incluya en los resultados más datos personales de los necesarios
Solución de problemas
- Todas las tareas fallan de inmediato: revise Entrega → Última respuesta en el detalle de la ejecución. Un 401 suele indicar que se pegó la clave de respuesta en lugar del secreto de firma, o que se eliminó el secreto anterior justo después de una rotación
- Una tarea sigue en
working: el worker devuelve 2xx pero nunca informa. Revise en los registros del worker los códigos de respuesta de la API de informe de estado - Los informes reciben 401: asegúrese de usar la clave de respuesta que empieza por
tm_task_y no una clave anterior a una regeneración - Los informes reciben 409: la tarea ya terminó o fue cancelada. No hace falta enviar más
- Los informes reciben 413: el cuerpo supera 100 KB. Reduzca
resulty reenvíe - Enviar la misma solicitud no crea una tarea nueva: el mismo
inputen menos de 2 minutos devuelve la tarea existente. Añada algo como una fecha ainputpara distinguirlas