GET api/list.php

Cargando…

Consultando la base de datos usando api/list.php.

Novedades API v2 Actualizado

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)
Estándar de documentación aplicado
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)
POST api/submit.php v2

Registra un ISRC en cola BOT1 (ingest_mode=single). Si ya existe, no duplica registro.

Cómo enviar correctamente
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
Respuesta exitosa 200 · OK
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"
}
Errores posibles Estandarizado
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)."
}
POST api/submit_batch.php Nuevo v2

Registra varios ISRC en cola BOT2 (ingest_mode=batch). Máximo 500 por petición.

Cómo enviar correctamente
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
Respuesta exitosa 200 · OK
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
    }
  ]
}
GET api/list.php v2

Lista paginada de ISRC registrados, con progreso por fases y cola de bot.

Cómo enviar correctamente
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
Respuesta exitosa 200 · OK
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.

Errores posibles Estandarizado
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."
}
GET api/detail.php

Detalle completo del ISRC (meta, estado, KPI, location y recordings).

Cómo enviar correctamente
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
Respuesta exitosa 200 · OK
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
    }
  ]
}
Errores posibles Estandarizado
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."
}
GET 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.

Cómo enviar correctamente
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.
Respuesta exitosa 200 · OK
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
    }
  ]
}
Errores posibles Estandarizado
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."
}
POST api/retrack_isrc.php Nuevo v2

Retrack individual: borra datos Luminate del ISRC y encola re-ingesta completa en BOT3 (ingest_mode=retrack).

Cómo enviar correctamente
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
Respuesta exitosa 200 · OK
{
  "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

Errores posibles
404 · ISRC no encontrado
422 · ISRC inválido
500 · Error al retrack
POST 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).

Cómo enviar correctamente
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
Respuesta exitosa 200 · OK
{
  "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)

Errores posibles
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
GET api/retrack_job.php?id={job_id} Nuevo v2

Consulta el estado de un job retrack_from_date encolado por retrack_all.php.

Cómo enviar correctamente
GET /api/retrack_job.php?id=12
Respuesta exitosa 200 · OK
{
  "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

Errores posibles
422 · id inválido
404 · Job no encontrado
500 · Error al consultar
WebHub RebelMusic · Tiempo real (v2) Nuevo v2

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.
WS 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.

Flujo recomendado
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
Mensaje inicial (servidor → cliente) event: hello
{
  "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"]
  }
}
WS Mensajes del cliente (JSON) Nuevo v2

Todos los mensajes del cliente son texto JSON con campo action.

Suscribirse / desuscribirse
{"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_isrcsolo cuando un ISRC termina (is_complete: true)
isrc:CODIGO — progreso y finalización de un ISRC concreto

Confirmación de suscripción
{
  "event": "subscribed",
  "channels": ["bots", "isrc:TLREW2210595"],
  "ts": "2026-07-14T18:00:01+00:00"
}
EVENT bots_status Nuevo v2

Estado de ocupación de los bots. Se emite cada ~3 s si estás suscrito a bots.

Payload
{
  "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

EVENT 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.

isrc_progress (canal isrc:CODIGO)
{
  "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
  }
}
isrc_completed (canales all_isrc e isrc:CODIGO)
{
  "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.

GET 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).

Cómo enviar
GET https://hub.rebelmusic.dev/api/snapshot.php
Headers: Accept: application/json
Respuesta exitosa 200 · OK
{
  "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 }
    }
  ]
}
EJEMPLO JavaScript · Python
JavaScript
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);
  }
};
Python
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())
INFO 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.