Webhook Collection Sync
El webhook Collection Sync permite que tu aplicación se mantenga sincronizada con tus colecciones de AudioDN. Cada vez que se crea, actualiza o elimina una colección, AudioDN envía una solicitud HTTP POST a la URL de webhook de colección configurada para tu organización. Esto es independiente del webhook Track Processing, que cubre los cambios de estado de las pistas.
Se configura en el panel
La URL del webhook de colección se establece en el panel Settings → Webhook del dashboard, no vía la API. Una vez guardada una URL, cada create/update/delete de colección de tu organización se entrega a ella. Déjala en blanco para desactivar los webhooks de colección.
Cuándo se dispara
Se entrega un webhook cada vez que una colección cambia de estado:
- Se envía como un HTTP
POSTconContent-Type: application/json. - Incluye una cabecera
X-ADN-Eventcon el nombre del evento (por ejemplocollection.updated). - La entrega es fire-and-forget / al menos una vez — diseña tu manejador para que sea idempotente.
- No se garantiza el orden de eventos; usa el
eventy el campoupdated_atde la colección en lugar de asumir el orden de llegada. - Las solicitudes actualmente no están firmadas. Trata la URL del webhook como un secreto y, si hace falta, verifica el
collection_idcontra la API. - Responde con prontitud con un código de estado
2xxpara acusar recibo.
Eventos
| Evento | Significado |
|---|---|
| collection.created | Se creó una nueva colección. Se envía una vez, cuando se inserta por primera vez la fila de la colección. |
| collection.updated | Una colección existente cambió — por ejemplo su título, metadatos, portada o ajustes del player. |
| collection.deleted | Se eliminó una colección. Se envía cuando se quita la colección (sus pistas y archivos se eliminan con ella). |
Esquema del payload
Cada evento entrega el mismo sobre. El objeto collection contiene los campos actuales de la colección; en un evento collection.deleted refleja la fila eliminada (con deleted_at establecido).
{
"event": "collection.created | collection.updated | collection.deleted",
"organization_id": "uuid",
"creator_id": "uuid | null",
"collection_id": "uuid",
"collection": {
"id": "uuid",
"organization_id": "uuid",
"creator_id": "uuid | null",
"title": "string | null",
"organization_index": "string | null",
"metadata": "object | null",
"theme": "array | null",
"player_color": "string | null",
"player_color_light": "string | null",
"player_color_dark": "string | null",
"player_subtitle": "string | null",
"is_cover_overridable": "boolean",
"is_theme_overridable": "boolean",
"cloudflare_image_id": "uuid | null",
"cover_image": {
"icon": { "type": "icon", "width": 80, "height": 80, "url": "string" },
"small": { "type": "small", "width": 200, "height": 200, "url": "string" },
"regular": { "type": "regular", "width": 400, "height": 400, "url": "string" },
"large": { "type": "large", "width": 800, "height": 800, "url": "string" }
},
"created_at": "string",
"updated_at": "string",
"deleted_at": "string | null"
}
} Imágenes de portada
Cuando una colección tiene arte de portada, collection.cover_image proporciona URLs listas para usar en cada tamaño disponible (y collection.cloudflare_image_id almacena el ID de imagen si lo necesitas). Ambos son null cuando no hay portada. Prefiere las URLs ya preparadas; si solo tienes el ID de imagen, construye cualquier tamaño tú mismo con el patrón de abajo, donde <variant> es icon (80x80), small (200x200), regular (400x400) o large (800x800):
https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/{cloudflare_image_id}/{variant} Consulta Track Processing → Cover images para la referencia completa de variantes. El mismo esquema se usa en las respuestas cover_image de la API.
Ejemplos de payload
Creada
Se envía cuando se crea una nueva colección.
{
"event": "collection.created",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"collection": {
"id": "22222222-2222-2222-2222-222222222222",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"title": "Season 1",
"organization_index": "your-collection-id-001",
"metadata": null,
"theme": null,
"player_color": "#1DB954",
"player_color_light": "#1BAA4D",
"player_color_dark": "#1DB954",
"player_subtitle": "Acme Media",
"is_cover_overridable": true,
"is_theme_overridable": true,
"cloudflare_image_id": null,
"cover_image": null,
"created_at": "2026-07-02T10:00:00.000Z",
"updated_at": "2026-07-02T10:00:00.000Z",
"deleted_at": null
}
} Actualizada
Se envía cuando cambian los campos de una colección.
{
"event": "collection.updated",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"collection": {
"id": "22222222-2222-2222-2222-222222222222",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"title": "Season 1 (Remastered)",
"organization_index": "your-collection-id-001",
"metadata": { "genre": "podcast" },
"theme": null,
"player_color": "#1DB954",
"player_color_light": "#1BAA4D",
"player_color_dark": "#1DB954",
"player_subtitle": "Acme Media",
"is_cover_overridable": true,
"is_theme_overridable": true,
"cloudflare_image_id": "99999999-9999-9999-9999-999999999999",
"cover_image": {
"icon": { "type": "icon", "width": 80, "height": 80, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/99999999-9999-9999-9999-999999999999/icon" },
"small": { "type": "small", "width": 200, "height": 200, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/99999999-9999-9999-9999-999999999999/small" },
"regular": { "type": "regular", "width": 400, "height": 400, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/99999999-9999-9999-9999-999999999999/regular" },
"large": { "type": "large", "width": 800, "height": 800, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/99999999-9999-9999-9999-999999999999/large" }
},
"created_at": "2026-07-02T10:00:00.000Z",
"updated_at": "2026-07-02T12:30:00.000Z",
"deleted_at": null
}
} Eliminada
Se envía cuando se elimina una colección. El campo deleted_at está poblado.
{
"event": "collection.deleted",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"collection_id": "22222222-2222-2222-2222-222222222222",
"collection": {
"id": "22222222-2222-2222-2222-222222222222",
"organization_id": "11111111-1111-1111-1111-111111111111",
"creator_id": null,
"title": "Season 1 (Remastered)",
"organization_index": "your-collection-id-001",
"metadata": { "genre": "podcast" },
"theme": null,
"player_color": "#1DB954",
"player_color_light": "#1BAA4D",
"player_color_dark": "#1DB954",
"player_subtitle": "Acme Media",
"is_cover_overridable": true,
"is_theme_overridable": true,
"cloudflare_image_id": "99999999-9999-9999-9999-999999999999",
"cover_image": {
"icon": { "type": "icon", "width": 80, "height": 80, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/99999999-9999-9999-9999-999999999999/icon" },
"small": { "type": "small", "width": 200, "height": 200, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/99999999-9999-9999-9999-999999999999/small" },
"regular": { "type": "regular", "width": 400, "height": 400, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/99999999-9999-9999-9999-999999999999/regular" },
"large": { "type": "large", "width": 800, "height": 800, "url": "https://imagedelivery.net/iVHDyjXAr_lt5UUJaLbk1Q/99999999-9999-9999-9999-999999999999/large" }
},
"created_at": "2026-07-02T10:00:00.000Z",
"updated_at": "2026-07-02T13:00:00.000Z",
"deleted_at": "2026-07-02T13:00:00.000Z"
}
} 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 de colección en Settings es correcta.
Manejar webhooks
Un manejador mínimo lee el campo event y mantiene sincronizada tu copia local de la colección. Como la entrega es al menos una vez y sin orden garantizado, basa tu lógica en collection_id y el updated_at de la colección en lugar del orden de recepción.
app.post('/webhooks/audiodn/collections', (req, res) => {
// Acknowledge quickly, then process asynchronously.
res.sendStatus(200)
const { event, collection_id, collection } = req.body
switch (event) {
case 'collection.created':
case 'collection.updated':
// Upsert your local copy of the collection.
upsertCollection(collection_id, collection)
break
case 'collection.deleted':
// Remove your local copy.
removeCollection(collection_id)
break
}
})