# Webhook Track File | Docs de AudioDN

> El webhook Track File notifica a tu aplicación sobre track files individuales a medida que se crean o fallan — un archivo a la vez, en lugar de desempaquetar el payload completo de la pista.

Source: https://audiodeliverynetwork.com/es/docs/webhooks/track-files/

---

# Webhook Track File

El webhook Track File permite que tu aplicación reaccione a [track files](/docs) individuales a medida que se producen. Cada track file es el resultado de aplicar una variante (receta) a una pista. En lugar de recibir el array completo `files[]` en cada [cambio de estado de pista](/docs/webhooks/track-processing), este webhook entrega **un track file a la vez** — lo cual es más fácil de manejar cuando una pista tiene muchas variantes.

#### Se configura en el panel

La URL del webhook Track File se establece en el panel **Settings → Webhook** del dashboard, no vía la API. Una vez guardada una URL, cada evento de track file de tu organización se entrega a ella. Déjala en blanco para desactivarlo. Es independiente de los webhooks [Track Processing](/docs/webhooks/track-processing) y [Collection Sync](/docs/webhooks/collection-sync) — habilita los que necesites.

## Cuándo se dispara

Una pista normalmente produce varios track files (uno por variante). Este webhook se dispara **una vez por track file** en lugar de una vez por pista. Cada track file — tanto si tiene éxito como si falla — se registra, así que siempre obtienes exactamente un evento por archivo. Cada payload lleva un `status` (`success` o `failed`) y un `event` coincidente:

| Resultado | Evento | Estado | Significado |
| --- | --- | --- | --- |
| Creado con éxito | track\_file.created | success | Un track file terminó de procesarse y se almacenó. La subida al almacenamiento ya se ha completado, así que este evento marca el archivo como disponible. El objeto file tiene file.is\_success = true. |
| Fallido | track\_file.failed | failed | Una variante falló al procesarse. Aun así se entrega una fila de file para que el mapeo se mantenga 1:1, pero con file.is\_success = false, sin url y el motivo en message. |

-   Se envía como un HTTP `POST` con `Content-Type: application/json`.
-   Incluye una cabecera `X-ADN-Event` con el nombre del evento (`track_file.created` o `track_file.failed`).
-   Ramifica según el `status` de nivel superior (`success` / `failed`) o según `file.is_success`.
-   La entrega es fire-and-forget / al menos una vez — diseña tu manejador para que sea idempotente (clave en `file_id`, o en `track_id` + `variant.index`).
-   No se garantiza el orden de eventos entre archivos.
-   Las solicitudes actualmente no están firmadas. Trata la URL del webhook como un secreto y, si hace falta, verifica el `track_id` contra la API.
-   Responde con prontitud con un código de estado `2xx` para acusar recibo.

#### Track File vs Track Processing

Usa el [webhook Track Processing](/docs/webhooks/track-processing) para reaccionar al ciclo de vida general de una pista (`processing` → `ready`). Usa el webhook Track File cuando te importe cada archivo de salida individual a medida que llega — por ejemplo, para desbloquear una descarga lossless comprada en el momento en que esté lista, sin esperar a que termine toda la pista.

## Esquema del payload

El objeto `file` coincide con una sola entrada del array `files[]` entregado por el webhook Track Processing, incluyendo la `variant` anidada (receta) que lo produjo, más `is_success`. Tanto el éxito como el fallo entregan un objeto `file`. En caso de fallo, `file.is_success` es `false`, `file.url` es `null` (no se almacenó ningún objeto) y el motivo está en el `message` de nivel superior (reflejado en `file.status_text`).

```
{
"event": "track_file.created | track_file.failed",
"status": "success | failed",
"organization_id": "uuid",
"creator_id": "uuid | null",
"collection_id": "uuid",
"track_id": "uuid",
"file_id": "uuid",
"message": "string | null",
"file": {
  "id": "uuid",
  "path": "string",
  "url": "string | null",
  "size": "number | null",
  "content_type": "string | null",
  "file_name": "string",
  "is_public": "boolean",
  "is_success": "boolean",
  "status_text": "string | null",
  "data": "object | null",
  "props": "object | null",
  "variant": {
    "id": "uuid",
    "index": "string",
    "variant_type": {
      "id": "string",
      "viewer_id": "string",
      "title": "string"
    }
  }
}
}
```

Lee la variante que produjo (o habría producido) el archivo desde `file.variant`. En caso de éxito, `message` es `null` y `file.url` apunta al objeto almacenado. En caso de fallo, `message` contiene el error, `file.url` es `null`, y `file.size` / `file.content_type` pueden ser `null`.

## Ejemplos de payload

### Creado con éxito

Se envía cuando un track file termina de procesarse y se almacena.

```
{
"event": "track_file.created",
"status": "success",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"track_id": "33333333-3333-3333-3333-333333333333",
"file_id": "55555555-5555-5555-5555-555555555555",
"message": null,
"file": {
  "id": "55555555-5555-5555-5555-555555555555",
  "path": "org/collection/track/transcode.aac",
  "url": "https://cdn.audiodn.com/org/collection/track/transcode.aac",
  "size": 17012344,
  "content_type": "audio/aac",
  "file_name": "transcode.aac",
  "is_public": true,
  "is_success": true,
  "status_text": "OK",
  "data": null,
  "props": null,
  "variant": {
    "id": "66666666-6666-6666-6666-666666666666",
    "index": "transcode-default",
    "variant_type": {
      "id": "transcode",
      "viewer_id": "audio",
      "title": "Transcoded Audio"
    }
  }
}
}
```

### Fallido (error de variante)

Se envía cuando una variante falla al procesarse. Aun así se entrega una fila `file` (para que el mapeo se mantenga 1:1), pero con `is_success: false`, sin `url` y el motivo en `message`.

```
{
"event": "track_file.failed",
"status": "failed",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"track_id": "33333333-3333-3333-3333-333333333333",
"file_id": "77777777-7777-7777-7777-777777777777",
"message": "ffmpeg exited with code 1: unsupported sample format",
"file": {
  "id": "77777777-7777-7777-7777-777777777777",
  "path": "org/collection/track/preview-30s.aac",
  "url": null,
  "size": null,
  "content_type": "audio/aac",
  "file_name": "preview-30s.aac",
  "is_public": false,
  "is_success": false,
  "status_text": "ffmpeg exited with code 1: unsupported sample format",
  "data": null,
  "props": null,
  "variant": {
    "id": "66666666-6666-6666-6666-666666666666",
    "index": "preview-30s",
    "variant_type": {
      "id": "preview",
      "viewer_id": "audio",
      "title": "Preview Clip"
    }
  }
}
}
```

#### Verificar la entrega

Cada intento de entrega se registra en el lado de AudioDN, incluyendo el código de estado HTTP devuelto por tu endpoint. Si dejas de recibir eventos, confirma que tu endpoint responde con `2xx` rápidamente y que la URL del webhook Track File en Settings es correcta.

## Manejar webhooks

Ramifica según `status` (o `file.is_success`). Como la entrega es al menos una vez y sin orden garantizado, basa tu lógica en `file_id` (o `track_id` + `file.variant.index`) en lugar del orden de recepción.

```
app.post('/webhooks/audiodn/track-files', (req, res) => {
// Acknowledge quickly, then process asynchronously.
res.sendStatus(200)

const { status, track_id, file, message } = req.body
if (status === 'success') {
  // A single track file is ready — store or unlock it.
  saveTrackFile(track_id, file)
} else {
  // A variant failed — file.is_success is false and file.url is null.
  flagVariantFailure(track_id, file.variant, message)
}
})
```
