Guías principales

API de gestión de Webhooks

Configure notificaciones de tareas a través del Dashboard, la API o MCP, verifique firmas y solucione problemas de entrega.

Los webhooks notifican a su aplicación cuando una tarea asíncrona se completa, falla o agota su tiempo de espera. Configúrelos en Dashboard → API → Webhooks, a través de la API de gestión o mediante el perfil full de TokenLab MCP. Comparten los mismos endpoints de espacio de trabajo e historial de entrega.

Qué credencial utilizar

CredencialPropósitoDónde se utiliza
Management Token mt-…Crear, listar, actualizar, eliminar, probar y rotar webhooksAuthorization: Bearer mt-… en /v1/management/webhooks*
API key sk-…Enviar solicitudes de modelos y consultar el estado de tareasAPIs de modelos y /v1/tasks/{id}
Signing secret whsec_…Verificar que una notificación recibida sea auténticaSu receptor; nunca lo use como un token Bearer de API

Cree un Management Token en Dashboard → API → Management Tokens. Los tokens tienen el alcance del espacio de trabajo: elija el mismo espacio de trabajo que la API key que envía las tareas. Un token no puede leer ni modificar los endpoints de otro espacio de trabajo. Las API keys y los signing secrets son rechazados por la API de gestión. La configuración del Dashboard utiliza su sesión de administrador del espacio de trabajo iniciada.

Almacene mt-… y whsec_… en su backend. No los incruste en código de navegador, prompts, archivos de repositorio o URLs. Los Management Tokens también autorizan otras operaciones de gestión del espacio de trabajo; no son credenciales exclusivas para webhooks.

Configurar un endpoint

export TOKENLAB_MANAGEMENT_TOKEN="mt-your-management-token"
curl https://api.tokenlab.sh/v1/management/webhooks \
  -H "Authorization: Bearer $TOKENLAB_MANAGEMENT_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://your-app.example/webhooks/tokenlab","events":["task.completed","task.failed","task.timeout"],"description":"Production task results"}'

La respuesta 201 incluye un id y un secret de un solo uso que comienza con whsec_. Almacene el secreto antes de salir de este paso. Las respuestas de listar/obtener/actualizar nunca lo exponen. Se pueden configurar hasta 10 endpoints por espacio de trabajo. Las URLs deben usar HTTPS público y no pueden contener credenciales, cadenas de consulta o fragmentos. Las redirecciones no se siguen.

OperaciónEndpoint
Listar / CrearGET / POST /v1/management/webhooks
Obtener / Actualizar / EliminarGET / PATCH / DELETE /v1/management/webhooks/{webhookId}
Rotar signing secretPOST /v1/management/webhooks/{webhookId}/rotate-secret
Enviar pruebaPOST /v1/management/webhooks/{webhookId}/test
Historial de entregaGET /v1/management/webhooks/{webhookId}/deliveries?page=1&limit=50

Pause con PATCH {"is_active":false}; reanude con PATCH {"is_active":true}. Reanudar restablece el contador de fallos consecutivos. La rotación devuelve un nuevo secreto una sola vez; configúrelo en su receptor inmediatamente. Las solicitudes que ya están en curso pueden seguir llevando la firma anterior, por lo que debe aceptar brevemente ambos secretos durante la rotación. La rotación no es reversible.

Eventos y payloads

Las suscripciones cubren futuros eventos de tareas asíncronas terminales; los resultados síncronos y las tareas históricas no se retransmiten. Reciba todas las tareas del espacio de trabajo para los tipos de eventos seleccionados y haga coincidir data.taskId con el ID devuelto cuando creó la tarea. Los campos de callback utilizan camelCase; los campos de respuesta de gestión utilizan snake_case.

{
  "id": "event-unique-id",
  "type": "task.completed",
  "created": 1790000000,
  "data": {
    "taskType": "video",
    "taskId": "ldtask_0123456789abcdef0123456789abcdef",
    "model": "your-selected-model",
    "durationMs": 42000,
    "resultUrls": ["https://api.tokenlab.sh/v1/media-results/7c9e6679-7425-40de-944b-e07fc1f90ae7.mp4?token=…"],
    "settledCost": 0.12
  }
}
EventoDatos
task.completedtaskType, taskId, model opcional, durationMs, resultUrls, settledCost
task.failedtaskType, taskId, error, errorCode, retryable, refundOutcome
task.timeouttaskType, taskId, expectedTimeoutMs, actualWaitMs, refundIssued, resolutionSource, refundOutcome
webhook.testMensaje de prueba y suscripciones configuradas; enviado solo por la operación de prueba

Cada entrada de resultUrls es una URL de resultado multimedia de TokenLab válida durante 30 días. Consulte Retención de datos.

Para task.timeout, expectedTimeoutMs es el umbral de tiempo de espera configurado y actualWaitMs es la espera transcurrida, ambos en milisegundos. refundIssued: true significa que el reembolso se realizó con éxito o ya se había emitido; false no descarta un reembolso posterior. refundOutcome describe el resultado del procesamiento del reembolso. Los eventos de tiempo de espera no contienen durationMs.

Los campos dependen de la tarea y pueden estar ausentes. Utilice GET /v1/tasks/{id} con la clave sk-… del espacio de trabajo original para obtener el resultado autorizado y el estado de facturación. El campo retryable de un evento describe el fallo de generación; no es una instrucción para consultar una tarea terminal indefinidamente o enviar automáticamente una nueva tarea facturable. En task.failed, error, errorCode y retryable son el error_details.message, code y retryable públicos de la tarea, los mismos valores que devuelve una lectura de estado.

Verificar antes de procesar

Cada POST incluye X-Webhook-ID, X-Webhook-Timestamp (segundos Unix) y X-Webhook-Signature (sha256=<hex>). Calcule HMAC-SHA256 sobre la cadena de tiempo exacta, un punto y los bytes del cuerpo de la solicitud sin procesar, utilizando el secreto whsec_… completo. No analice ni vuelva a serializar JSON antes de la verificación.

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyWebhook(rawBody, headers, secrets) {
  const timestamp = headers['x-webhook-timestamp'];
  const signature = headers['x-webhook-signature'];
  if (typeof timestamp !== 'string' || !/^\d+$/.test(timestamp)) return false;
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
  if (typeof signature !== 'string' || !/^sha256=[a-f0-9]{64}$/.test(signature)) return false;
  const received = Buffer.from(signature.slice(7), 'hex');
  return secrets.some(secret => {
    const expected = createHmac('sha256', secret).update(timestamp + '.').update(rawBody).digest();
    return timingSafeEqual(expected, received);
  });
}

Después de la verificación, compruebe que el id del cuerpo coincida con X-Webhook-ID, persista el ID del evento con su elemento de trabajo de forma atómica y devuelva 2xx rápidamente. Procese el trabajo pesado desde su propia cola. Desduplique por ID de evento dentro del endpoint receptor: las entregas pueden repetirse y el orden no está garantizado. Una tolerancia de tiempo de cinco minutos limita la antigüedad de la repetición; la desduplicación por ID evita el procesamiento repetido dentro de esa ventana.

Reintentos y recuperación

Cada ciclo de entrega realiza hasta tres intentos, esperando 1 segundo y luego 4 segundos. Cada intento HTTP tiene un tiempo de espera de 10 segundos y una marca de tiempo/firma nueva. Los fallos de red, 429 y 5xx son reintentables. Otros 4xx, redirecciones y destinos de red no válidos detienen ese ciclo sin reintentar. Los fallos transitorios pueden activar reintentos de eventos posteriores con el mismo ID de entrega. Diez ciclos fallidos consecutivos pausan automáticamente el endpoint.

Utilice la operación de prueba y el historial de entrega para ver outcome, http_status, attempts y delivered_at. Una respuesta exitosa de la API de prueba (200) solo significa que el intento fue registrado: verifique outcome == "delivered". Corrija el receptor, reanude el endpoint y luego envíe otra prueba. El historial contiene metadatos de entrega, no payloads; la repetición manual de eventos antiguos no está disponible. Mantenga los IDs de tarea y reconcilie con el estado de la tarea si su receptor estuvo pausado o no disponible.

Configuración de MCP

Las herramientas de gestión de webhooks están disponibles en el perfil full. La credencial de gestión es independiente de la clave de inferencia; la gestión de catálogos y webhooks puede funcionar sin una clave de inferencia.

{
  "mcpServers": {
    "tokenlab": {
      "command": "npx",
      "args": ["-y", "@tokenlabai/mcp-server@latest"],
      "env": {
        "TOKENLAB_MCP_TOOL_PROFILE": "full",
        "TOKENLAB_MANAGEMENT_TOKEN": "mt-your-management-token",
        "TOKENLAB_API_KEY": "sk-your-inference-key"
      }
    }
  }
}

Herramientas: list_webhooks, create_webhook, get_webhook, update_webhook, delete_webhook, rotate_webhook_secret, test_webhook, list_webhook_deliveries. Nunca pegue credenciales en un argumento de herramienta. Conceda acceso de gestión solo a clientes MCP de confianza.

Alternativa de polling

Los webhooks no eliminan el acceso a la consulta de estado ni imponen un nuevo límite de polling. Si realiza polling, utilice la poll_url de la respuesta de creación, espere mientras esté pendiente y deténgase en estados terminales. Deténgase en 401, 403, 404 o error.retryable == false; reintente el fallo transitorio 503 async_task_owner_unavailable con backoff. Una tarea faltante o expirada devuelve 404 async_task_not_found. Consultar repetidamente una tarea faltante no puede recrearla.

La callback_url de la API de compatibilidad de Seedance /api-reference/video/create-volc-compatible-seedance-task es un contrato de callback independiente por solicitud. Se puede configurar al crear esa tarea; no utiliza estos payloads de eventos del espacio de trabajo ni encabezados HMAC.

En esta página