Cargando…
Consultando la base de datos usando api/list.php.
Detalle ISRC
Selecciona un endpoint para consultar y ver la respuesta.
Base: https://v2.rebelmusic.dev · BD: api_luminatedata_v2.
Los campos marcados con ★ v2 son nuevos o cambiaron respecto a la versión 1.
Para tiempo real (WebSocket) ver pestaña Documentación WS.
★ v2 — Nuevos endpoints REST: POST api/submit_batch.php POST api/retrack_isrc.php POST api/retrack_all.php GET api/retrack_job.php POST api/delete_isrc.php POST api/delete_all_isrc.php ★ v2 — Campos nuevos en respuestas: ingest_mode, progress (en list.php) activity_complete (en activity_over_time.php) job.kind = retrack_from_date (retrack masivo)
En todos los endpoints se documenta: 1) Cómo enviar correctamente (método, headers, params/body) 2) Respuesta exitosa real (status y estructura) 3) Errores posibles reales (status + código + mensaje) 4) cURL listo para copiar y pegar (Postman / terminal)
api/submit.php
v2
Registra un ISRC en cola BOT1 (ingest_mode=single). Si ya existe, no duplica registro.
Método: POST
Headers:
Accept: application/json
Content-Type: application/json
Body JSON:
{
"isrc": "US-CM5-16-00028",
"tracked": true
}
Notas:
- isrc es obligatorio (12 alfanuméricos, guiones opcionales)
- tracked es opcional (default true)
- También acepta formulario POST (isrc/tracked)
- ★ v2: asigna ingest_mode=single internamente (BOT1); no se envía en el body
Ver respuesta exitosa
{
"success": true,
"message": "Registro aceptado. La ingesta se completará en segundo plano.",
"isrc": "US-CM5-16-00028",
"isrc_normalized": "USCM51600028",
"id": 42,
"duplicate": false,
"tracked": true,
"created_at": "2026-03-27 12:34:56.000000-04"
}
Ver errores posibles
405 · Method Not Allowed
{
"success": false,
"error": "Método no permitido"
}
422 · Unprocessable Entity
{
"success": false,
"error": "ISRC inválido. Debe tener 12 caracteres alfanuméricos (puedes incluir guiones)."
}
500 · Internal Server Error
{
"success": false,
"error": "Error al guardar. Verifica PostgreSQL y el esquema (sql/schema.sql)."
}
api/submit_batch.php
Nuevo v2
Registra varios ISRC en cola BOT2 (ingest_mode=batch). Máximo 500 por petición.
Método: POST
Headers:
Accept: application/json
Content-Type: application/json
Body JSON:
{
"isrcs": ["US-CM5-16-00028", "TLREW2210595"],
"tracked": true
}
Notas:
- isrcs: array obligatorio, no vacío, máx. 500
- tracked: opcional (default true)
- ★ v2: cada ISRC nuevo recibe ingest_mode=batch
Ver respuesta exitosa
{
"success": true,
"total": 2,
"inserted": 1,
"duplicates": 1,
"errors": 0,
"results": [
{
"isrc": "US-CM5-16-00028",
"isrc_normalized": "USCM51600028",
"success": true,
"duplicate": false,
"id": 43
},
{
"isrc": "TL-REW-22-10595",
"isrc_normalized": "TLREW2210595",
"success": true,
"duplicate": true,
"id": 12
}
]
}
api/list.php
v2
Lista paginada de ISRC registrados, con progreso por fases y cola de bot.
Método: GET Headers: Accept: application/json Query params (opcionales): - status: pending | syncing | ready | error - limit: int (1..200, default 50) - page: int (>=1, default 1) - min_id: int (>=1) ★ v2 — solo registros con id >= min_id Ejemplo: GET /api/list.php?status=ready&limit=25&page=1
Ver respuesta exitosa
{
"success": true,
"total": 142,
"page": 1,
"limit": 25,
"data": [
{
"id": 1,
"isrc": "US-CM5-16-00028",
"isrc_normalized": "USCM51600028",
"name": "One Dance",
"luminate_id": "SG67B20476A9EB4318BE350C4404209083",
"entity_type": "SONG",
"image_url": "http://...",
"score": "2.416687",
"status": "ready",
"error_message": null,
"tracked": true,
"ingest_mode": "single",
"progress": {
"percent": 83,
"percent_remaining": 17,
"phases_total": 6,
"phases_completed": 5,
"phases_pending": 1,
"completed": ["search", "metadata", "kpi", "activity", "location"],
"pending": ["recordings"],
"current_phase": "recordings",
"current_phase_label": "Related recordings",
"is_complete": false,
"has_artist_phases": false
},
"created_at": "2026-03-25 17:25:19.541009-04",
"updated_at": "2026-03-25 17:49:35.76688-04"
}
]
}
★ v2 en cada item de data: ingest_mode (single | batch | retrack) · progress (objeto con percent, is_complete, fases). En la raíz: min_id si se usó el filtro.
Ver errores posibles
405 · Method Not Allowed
{
"success": false,
"error": "Método no permitido"
}
422 · Unprocessable Entity
{
"success": false,
"error": "status inválido. Valores aceptados: pending, syncing, ready, error"
}
500 · Internal Server Error
{
"success": false,
"error": "Error al consultar la base de datos."
}
api/detail.php
Detalle completo del ISRC (meta, estado, KPI, location y recordings).
Método: GET Headers: Accept: application/json Query params: - isrc (obligatorio): 12 alfanuméricos, con o sin guiones Ejemplo: GET /api/detail.php?isrc=USCM51600028
Ver respuesta exitosa
{
"success": true,
"meta-info": {
"luminate_id": "SG67B20476A9EB4318BE350C4404209083",
"title": "One Dance",
"artist_display_name": "Drake, Kyla, Wizkid",
"image_url": "http://akamai-b.cdn.cddbp.net/cds/2.0/image/C0D1/6EB7/E5BD/464B_xlarge_front.jpg",
"release_date": "2016-04-01",
"main_genre": "R&B/Hip-Hop",
"imprint": "Cash Money / Republic Records",
"distributors_text": "Digital: Universal Music Distribution",
"owners_text": "Cash Money",
"included_in_text": "One Dance; Views",
"duration": "00:02:54.987",
"popularity": "19.9999"
},
"isrc-info": {
"id": 6,
"isrc_normalized": "USCM51600028",
"isrc_display": "US-CM5-16-00028",
"luminate_id": "SG67B20476A9EB4318BE350C4404209083"
},
"estado-info": {
"status": "ready",
"error_message": null,
"created_at": "2026-03-25 17:25:19.541009-04",
"updated_at": "2026-03-25 17:49:35.76688-04"
},
"kpi-info": {
"album_equivalent": { "current": 3357, "atd": 1635542, "growth_percentage": "4.95" },
"streams": {
"current": 3882029,
"atd": 2284976095,
"growth_percentage": "4.01",
"ad_supported_percentage": "19.54",
"premium_percentage": "80.46",
"ad_supported_streams": 758490,
"premium_streams": 3123539
},
"song_sales": { "current": 40, "atd": 2211588, "growth_percentage": "8.11" },
"airplay_audience": { "current": 1390100, "atd": 6269879700, "growth_percentage": "4.08" },
"airplay_spins": { "current": 496, "atd": 1215603, "growth_percentage": "-1.20" }
},
"location-info": [
{
"location_name": "NATIONAL",
"location_type": "COUNTRY",
"total_streams": 3882029,
"ad_supported_streams": 758490,
"premium_streams": 3123539,
"share_worldwide_percentage": 28.49
}
],
"recordings-info": [
{
"recording_luminate_id": "MR1D7D6FE55A1E4BDE8CBD98A55A3B5B2A",
"isrc": "USCM51600028",
"title": "One Dance",
"release_date": "2016-04-01",
"recording_type": "Audio",
"rank_order": 1,
"total_streams": 3882009,
"ad_supported_streams": 758490,
"premium_streams": 3123519,
"provider_code": "30920569",
"duration": 0
}
]
}
Ver errores posibles
405 · Method Not Allowed
{
"success": false,
"error": "Método no permitido"
}
422 · Unprocessable Entity
{
"success": false,
"error": "isrc inválido. Debe tener 12 caracteres alfanuméricos."
}
404 · Not Found
{
"success": false,
"error": "ISRC no encontrado"
}
500 · Internal Server Error
{
"success": false,
"error": "Error al consultar detalle."
}
api/activity_over_time.php
v2
Serie diaria de streams por ISRC, con rango opcional. success solo es true cuando el bot marcó la carga completa (★ v2: activity_complete); hasta entonces puede haber filas parciales.
Método: GET Headers: Accept: application/json Query params: - isrc (obligatorio) - start_date (opcional, YYYY-MM-DD) - end_date (opcional, YYYY-MM-DD) Regla: - Si envías start_date debes enviar end_date (y viceversa). - start_date no puede ser mayor que end_date.
Ver respuesta exitosa
{
"success": true,
"activity_complete": true,
"isrc": "USCM51600028",
"start_date": "2026-03-13",
"end_date": "2026-03-20",
"count": 2,
"activity_over_time": [
{
"date": "2026-03-13",
"week": 11,
"year": 2026,
"total_streams": 830046,
"ad_supported_streams": 164072,
"premium_streams": 665974
}
]
}
Ver errores posibles
405 · Method Not Allowed
{
"success": false,
"error": "Método no permitido"
}
422 · Unprocessable Entity
{
"success": false,
"error": "isrc inválido. Debe tener 12 caracteres alfanuméricos."
}
422 · Unprocessable Entity
{
"success": false,
"error": "Debes enviar start_date y end_date juntos (YYYY-MM-DD)."
}
422 · Unprocessable Entity
{
"success": false,
"error": "start_date inválido. Formato YYYY-MM-DD."
}
422 · Unprocessable Entity
{
"success": false,
"error": "end_date inválido. Formato YYYY-MM-DD."
}
422 · Unprocessable Entity
{
"success": false,
"error": "start_date no puede ser mayor que end_date."
}
500 · Internal Server Error
{
"success": false,
"error": "Error al consultar activity_over_time."
}
api/retrack_isrc.php
Nuevo v2
Retrack individual: borra datos Luminate del ISRC y encola re-ingesta completa en BOT3 (ingest_mode=retrack).
Método: POST
Body JSON:
{
"isrc": "TL-REW-22-10595",
"tracked": true
}
Notas:
- El ISRC debe existir previamente (404 si no)
- ★ v2: guarda restore_ingest_mode (single o batch) para restaurar al terminar
{
"success": true,
"message": "ISRC reseteado y encolado para re-ingesta completa (bot3).",
"isrc": "TL-REW-22-10595",
"isrc_normalized": "TLREW2210595",
"id": 12,
"status": "pending",
"ingest_mode": "retrack",
"restore_ingest_mode": "single",
"created_at": "2026-03-25 17:25:19.541009-04"
}
★ v2 en respuesta: ingest_mode · restore_ingest_mode · status vuelve a pending
404 · ISRC no encontrado 422 · ISRC inválido 500 · Error al retrack
api/retrack_all.php
Nuevo v2
Retrack masivo desde una fecha: borra activity >= start_date y recarga solo desde esa fecha. Lo ejecuta BOT5 (job retrack_from_date).
Método: POST
Headers:
Accept: application/json
Content-Type: application/json
Body JSON:
{
"start_date": "2026-07-07"
}
Notas:
- start_date obligatorio (YYYY-MM-DD)
- No puede ser fecha futura
- Solo un job pending/running a la vez
{
"success": true,
"message": "Job retrack masivo encolado. BOT5 borrará activity >= start_date...",
"job": {
"id": 12,
"kind": "retrack_from_date",
"start_date": "2026-07-07",
"status": "pending",
"created_at": "2026-07-14 12:00:00-04"
}
}
★ v2 en job: kind = retrack_from_date (antes no existía este tipo de job)
409 · Conflict
{
"success": false,
"error": "Ya hay un job retrack masivo en cola o en ejecución..."
}
422 · start_date inválido o fecha futura
500 · Error al encolar
api/retrack_job.php?id={job_id}
Nuevo v2
Consulta el estado de un job retrack_from_date encolado por retrack_all.php.
GET /api/retrack_job.php?id=12
{
"success": true,
"job": {
"id": 12,
"kind": "retrack_from_date",
"start_date": "2026-07-07",
"status": "running",
"error_message": null,
"created_at": "2026-07-14 12:00:00-04",
"updated_at": "2026-07-14 12:05:00-04"
}
}
★ v2 status: pending · running · completed · failed
422 · id inválido 404 · Job no encontrado 500 · Error al consultar
El WebHub es un servicio de solo lectura que emite eventos en tiempo real sobre el estado de los bots y el progreso de los ISRC.
Complementa la API REST: encolas con POST api/submit.php y sigues el avance por WebSocket.
Producción: WebSocket: wss://hub.rebelmusic.dev/ws Health: https://hub.rebelmusic.dev/health.txt Snapshot: https://hub.rebelmusic.dev/api/snapshot.php Prueba UI: https://hub.rebelmusic.dev/test_client.html Local (detrás de IIS): WebSocket: ws://127.0.0.1:8765 Sin autenticación en la configuración actual.
wss://hub.rebelmusic.dev/ws
Nuevo v2
Abre una conexión WebSocket segura. Al conectar recibes un mensaje hello y luego envías JSON para suscribirte a canales.
1) POST api/submit.php → encolar ISRC (ingest_mode=single, BOT1) 2) Conectar wss://hub.rebelmusic.dev/ws 3) Enviar subscribe con canal isrc:CODIGO 4) Recibir isrc_progress hasta isrc_completed 5) GET api/detail.php cuando is_complete = true
{
"event": "hello",
"hub": "RebelMusic WebHub",
"version": "0.1.0",
"ts": "2026-07-14T18:00:00+00:00",
"poll_seconds": 3.0,
"auth_required": false,
"subscribe_example": {
"action": "subscribe",
"channels": ["bots", "all_isrc", "isrc:TLREW2210595"]
}
}
Mensajes del cliente (JSON)
Nuevo v2
Todos los mensajes del cliente son texto JSON con campo action.
{"action":"subscribe","channels":["bots"]}
{"action":"subscribe","channels":["all_isrc"]}
{"action":"subscribe","channels":["isrc:TLREW2210595"]}
{"action":"subscribe","channels":["bots","all_isrc","isrc:USUM71912345"]}
{"action":"unsubscribe","channels":["bots"]}
{"action":"ping"} → respuesta {"event":"pong","ts":"..."}
Canales disponibles:
bots — estado de colas BOT1..BOT5 (~cada 3 s)
all_isrc — solo cuando un ISRC termina (is_complete: true)
isrc:CODIGO — progreso y finalización de un ISRC concreto
{
"event": "subscribed",
"channels": ["bots", "isrc:TLREW2210595"],
"ts": "2026-07-14T18:00:01+00:00"
}
bots_status
Nuevo v2
Estado de ocupación de los bots. Se emite cada ~3 s si estás suscrito a bots.
{
"event": "bots_status",
"ts": "2026-07-14T18:00:03+00:00",
"bots": [
{
"bot": "BOT1",
"label": "Single",
"queue": "single",
"pending": 2,
"running": 1,
"occupancy_percent": 30
},
{
"bot": "BOT2",
"label": "Batch",
"queue": "batch",
"pending": 0,
"running": 0,
"occupancy_percent": 0
},
{
"bot": "BOT3",
"label": "Retrack individual",
"queue": "retrack",
"pending": 1,
"running": 1,
"occupancy_percent": 30
},
{
"bot": "BOT4",
"label": "Daily update",
"queue": "daily",
"pending": 0,
"running": 0,
"occupancy_percent": 0,
"note": "Ejecucion programada; no usa cola ISRC"
},
{
"bot": "BOT5",
"label": "Retrack masivo por fecha",
"queue": "retrack_from_date",
"pending": 0,
"running": 1,
"occupancy_percent": 20
}
],
"summary": {
"total_pending": 3,
"tracked_isrc": 142,
"completed_isrc": 98
}
}
Relación con ingest_mode (API REST):
single → BOT1 · batch → BOT2 · retrack → BOT3
retrack_from_date (job) → BOT5 · BOT4 = daily programado
isrc_progress · isrc_completed
Nuevo v2
Progreso por fases de ingesta. isrc_progress solo en canal isrc:CODIGO. isrc_completed en isrc:CODIGO y all_isrc.
{
"event": "isrc_progress",
"ts": "2026-07-14T18:01:00+00:00",
"isrc": "TL-REW-22-10595",
"isrc_normalized": "TLREW2210595",
"status": "syncing",
"ingest_mode": "single",
"progress": {
"percent": 50,
"percent_remaining": 50,
"phases_total": 6,
"phases_completed": 3,
"phases_pending": 3,
"completed": ["search", "metadata", "kpi"],
"pending": ["activity", "location", "recordings"],
"completed_detail": [
{"key": "search", "label": "Busqueda ISRC"},
{"key": "metadata", "label": "Metadata cancion"}
],
"pending_detail": [
{"key": "activity", "label": "Activity over time"}
],
"current_phase": "activity",
"current_phase_label": "Activity over time",
"is_complete": false,
"has_artist_phases": true
}
}
{
"event": "isrc_completed",
"ts": "2026-07-14T18:05:00+00:00",
"isrc": "TL-REW-22-10595",
"isrc_normalized": "TLREW2210595",
"status": "ready",
"ingest_mode": "single",
"progress": {
"percent": 100,
"is_complete": true,
"current_phase": null,
"current_phase_label": null
}
}
Importante: all_isrc no recibe isrc_progress; solo notifica cuando progress.is_complete pasa a true.
WebHub/api/snapshot.php
Nuevo v2
Alternativa HTTP sin WebSocket: snapshot puntual de bots e ISRC tracked (misma lógica de progreso que el hub).
GET https://hub.rebelmusic.dev/api/snapshot.php Headers: Accept: application/json
{
"success": true,
"ts": "2026-07-14T18:00:00+00:00",
"websocket": {
"url": "wss://hub.rebelmusic.dev/ws",
"subscribe": {
"action": "subscribe",
"channels": ["bots", "all_isrc"]
}
},
"bots": [ ... ],
"isrcs": [
{
"id": 42,
"isrc": "TL-REW-22-10595",
"isrc_normalized": "TLREW2210595",
"status": "syncing",
"ingest_mode": "single",
"progress": { "percent": 50, "is_complete": false }
}
]
}
JavaScript · Python
const ws = new WebSocket("wss://hub.rebelmusic.dev/ws");
ws.onopen = () => {
ws.send(JSON.stringify({
action: "subscribe",
channels: ["bots", "isrc:TLREW2210595"]
}));
};
ws.onmessage = (ev) => {
const data = JSON.parse(ev.data);
if (data.event === "isrc_completed") {
console.log("ISRC listo:", data.isrc_normalized);
}
};
import asyncio, json, websockets
async def main():
async with websockets.connect("wss://hub.rebelmusic.dev/ws") as ws:
await ws.recv() # hello
await ws.send(json.dumps({
"action": "subscribe",
"channels": ["bots", "all_isrc"]
}))
async for msg in ws:
print(json.loads(msg))
asyncio.run(main())
Arquitectura de bots (v2)
BOT | Cola / job | ingest_mode | API relacionada ----|---------------------|------------------|--------------------------- BOT1| single | single (default) | POST api/submit.php BOT2| batch | batch | POST api/submit_batch.php BOT3| retrack individual | retrack | POST api/retrack_isrc.php BOT4| daily programado | — | (sin cola ISRC) BOT5| retrack_from_date | job masivo | POST api/retrack_all.php Notas: - Mientras BOT5 tiene un job running, BOT1/BOT2/BOT3 pausan su cola. - Retrack individual (BOT3) hace re-ingesta completa del ISRC. - Retrack masivo (BOT5) borra activity >= start_date y recarga desde esa fecha.