Saltar al contenido principal
D1 Arena

D1 Arena

Loading...

D1 Arena

API de Desarrollador

Comunidad

API de Desarrollador

Cree bots, superposiciones, herramientas de transmisión e integraciones con datos de D1Arena.

Autenticación

Todas las solicitudes de API requieren una clave API pasada en el encabezado X-API-Key / Authorization: Bearer.

# Example request curl -H "X-API-Key: d1_your_api_key_here" \ https://d1arena.com/api/v1/streams

Para crear una clave API, vaya a Configuración del desarrollador en su panel de control. Puedes tener hasta 5 llaves.

Las solicitudes de API tienen una tasa limitada por clave de API. Cuando excede el límite, las solicitudes regresan 429 Too Many Requests con un encabezado Retry-After.

URL base

https://d1arena.com/api/v1

Todos los puntos finales devuelven JSON. Los puntos finales paginados incluyen un objeto meta con current_page, last_page y total.

Transmisiones

GET /streams
Lista de transmisiones en vivo actualmente. Admite paginación y filtrado de categorías.
ParámetroTipoDescripción
category_idintegerFiltrar por ID de juego/categoría
limitintegerResultados por página (predeterminado: 20)
pageintegerNúmero de página
Respuesta
{ "data": [ { "id": 42, "name": "ProGamer99", "user_slug": "progamer99", "profile_img": "profile/abc123.jpg", "stream_title": "Ranked Grind - Road to Champion", "stream_category_id": 5, "is_vertical_stream": false, "platform_tier": "pro" } ], "meta": { "current_page": 1, "last_page": 1, "total": 3 } }
GET /streams/{slug}
Obtenga el estado en vivo de un solo transmisor y los detalles de la transmisión por nombre de usuario o slug.
Respuesta
{ "data": { "user_id": 42, "name": "ProGamer99", "slug": "progamer99", "is_live": true, "stream_title": "Ranked Grind", "category_id": 5, "is_vertical": false, "platform_tier": "pro", "profile_img": "profile/abc123.jpg" } }

Categorías

GET /categories
Enumera todas las categorías de juegos. Soporta búsqueda y paginación.
ParámetroTipoDescripción
searchstringFiltrar categorías por nombre
limitintegerResultados por página (predeterminado: 50)
Respuesta
{ "data": [ { "id": 5, "name": "Call of Duty", "slug": "call-of-duty", "image": "categories/cod.png" } ], "meta": { "total": 24 } }

Usuarios

GET /users/{slug}
Obtenga el perfil público de un jugador y estadísticas competitivas por nombre de usuario o slug.
Respuesta
{ "data": { "user": { "id": 42, "name": "ProGamer99", "user_slug": "progamer99", "profile_img": "profile/abc.jpg", "bio": "Competitive FPS player", "platform_tier": "pro", "is_live": "1", "stream_title": "Ranked", "gold": 3, "silver": 1, "bronze": 0 }, "stats": { "elo_rating": 1842, "total_tournaments": 27, "win_rate": 64.5, "total_earnings": 1250.00 } } }

clips

GET /clips
Listar clips públicos. Admite filtrado por transmisor y categoría.
ParámetroTipoDescripción
streamer_idintegerFiltrar clips por ID de usuario del transmisor
category_idintegerFiltrar por ID de juego/categoría
limitintegerResultados por página (predeterminado: 20)
Respuesta
{ "data": [ { "id": 99, "streamer_id": 42, "stream_category_id": 5, "title": "Insane 1v4 clutch", "slug": "insane-1v4-clutch-abc", "duration": 28, "view_count": 412, "is_auto_clip": false, "created_at": "2026-03-15T18:30:00.000000Z", "streamer": { "id": 42, "name": "ProGamer99", "user_slug": "progamer99" } } ], "meta": { "total": 156 } }
GET /clips/{slug}
Obtenga los detalles de un solo clip mediante slug.
Respuesta
{ "data": { "id": 99, "title": "Insane 1v4 clutch", "slug": "insane-1v4-clutch-abc", "description": "Final round comeback", "duration": 28, "view_count": 412, "streamer": { "id": 42, "name": "ProGamer99" }, "creator": { "id": 55, "name": "ClipMaster" }, "stream_category": { "id": 5, "name": "Call of Duty" } } }

Torneos

GET /tournaments
Listar torneos. Admite filtrado por estado y liga.
ParámetroTipoDescripción
statusstringFiltrar por estado (por ejemplo, open, in_progress, completed)
league_idintegerFiltrar por ID de liga
limitintegerResultados por página (predeterminado: 20)
Respuesta
{ "data": [ { "id": 15, "title": "Friday Night Frenzy", "tournament_type": "single_elimination", "status": "open", "registration_fee": "5.00", "no_player": 32, "team": 0, "category": { "id": 5, "name": "Call of Duty" }, "start_date": "2026-03-28T20:00:00.000000Z" } ], "meta": { "current_page": 1, "last_page": 2, "total": 24 } }
GET /tournaments/{id}
Obtenga detalles del torneo y recuento de participantes.
Respuesta
{ "data": { "id": 15, "title": "Friday Night Frenzy", "tournament_type": "single_elimination", "status": "open", "registration_fee": "5.00", "no_player": 32, "team": 0 }, "meta": { "participant_count": 18 } }

Clasificaciones ELO

GET /elo/leaderboard
Obtén la tabla de clasificación clasificada por ELO. Opcionalmente filtrar por categoría de juego.
ParámetroTipoDescripción
category_idintegerFiltrar por ID de juego/categoría
limitintegerNúmero de resultados (predeterminado: 50)
Respuesta
{ "data": [ { "rank": 1, "user_id": 42, "name": "ProGamer99", "user_slug": "progamer99", "elo_rating": 2150, "wins": 45, "losses": 12, "win_rate": 78.9, "profile_img": "profile/abc123.jpg" } ], "meta": { "total": 312 } }

Ligas

GET /leagues
Enumere ligas con filtros de categoría y estado opcionales.
ParámetroTipoDescripción
statusstringFiltrar por estado de liga
category_idintegerFiltrar por ID de juego/categoría
limitintegerResultados por página (predeterminado: 20)
Respuesta
{ "data": [ { "id": 3, "name": "Spring 2026 Pro League", "status": "active", "category": { "id": 5, "name": "Call of Duty" }, "total_participants": 48, "start_date": "2026-03-01", "end_date": "2026-05-31" } ], "meta": { "current_page": 1, "last_page": 1, "total": 6 } }
GET /leagues/{id}/standings
Obtén la clasificación de la liga (clasificación de los jugadores por puntos).
Respuesta
{ "data": [ { "id": 1, "points": 2400, "wins": 12, "losses": 3, "user": { "id": 42, "name": "ProGamer99", "user_slug": "progamer99" } } ], "meta": { "total": 48 } }

Respuestas de error

Todos los errores devuelven un sobre JSON coherente. El objeto error siempre contiene un code legible por máquina y un message legible por humanos.

Formato de respuesta de error
{ "success": false, "error": { "code": "not_found", "message": "The requested resource could not be found." } }
Formato de error de validación (422)
{ "success": false, "error": { "code": "validation_error", "message": "The given data was invalid.", "errors": { "category_id": ["The category id must be an integer."], "limit": ["The limit must not be greater than 100."] } } }

Códigos de estado

200
bien — Solicitud exitosa. La respuesta contiene los datos solicitados.
400
Solicitud incorrecta — La solicitud tiene un formato incorrecto o faltan parámetros requeridos. Consulte error.message para obtener más detalles.
401
No autorizado — Missing or invalid API key. Ensure you're passing a valid key in the X-API-Key header.
403
prohibido — Su clave API ha sido deshabilitada o carece de permiso para este recurso. revisa tu Configuración del desarrollador.
404
No encontrado — El recurso solicitado no existe. Verifique la ruta del slug, ID o punto final.
422
Error de validación — Los parámetros de solicitud fallaron en la validación. El objeto error.errors asigna nombres de campos a sus problemas específicos.
429
Tarifa limitada — Demasiadas solicitudes. El encabezado Retry-After indica cuántos segundos esperar antes de volver a intentarlo.
500
Error del servidor — Se produjo un error inesperado por nuestra parte. Si esto persiste, póngase en contacto con el soporte.

Referencia de códigos de error

CódigoEstado HTTPDescripción
invalid_api_key401La clave API falta, está mal formada o no existe
api_key_disabled403La clave API ha sido revocada o deshabilitada
not_found404No se pudo encontrar el recurso solicitado
validation_error422Uno o más parámetros de solicitud no son válidos
rate_limited429Se superó el límite de tasa de solicitud para esta clave API
server_error500Error interno del servidor. Vuelva a intentarlo o comuníquese con el soporte.

Límites de tarifas

Las solicitudes de API tienen una tasa limitada por clave de API. Cuando excede el límite, las solicitudes regresan 429 Too Many Requests con un encabezado Retry-After.

Límites por nivel

NivelSolicitudes / Minuto (Predeterminado)Teclas máximas
Motor de arranque (Gratis)605
PROFESIONAL605
último605
Pareja605

Encabezados de límite de tasa

Las solicitudes de API tienen una tasa limitada por clave de API. Cuando excede el límite, las solicitudes regresan 429 Too Many Requests con un encabezado Retry-After.

encabezadoDescripción
Retry-AfterSegundos de espera antes de volver a intentarlo (solo presente en 429 respuestas)

Mejores prácticas

Consejos para mantenerse dentro de los límites:
  • Cache responses locally — stream and tournament data doesn't change every second.
  • Suscríbase a webhooks para eventos en tiempo real en lugar de puntos finales de sondeo.
  • Solicitudes por lotes siempre que sea posible: utilice parámetros de filtro para obtener exactamente lo que necesita en menos llamadas.

Webhooks (EventSub)

Suscríbase a notificaciones automáticas en tiempo real en lugar de realizar encuestas. Cuando ocurre un evento, D1Arena envía una POST HTTP a su URL de devolución de llamada con una carga útil JSON firmada con HMAC-SHA256.

Configurar

Cree suscripciones a webhooks en Configuración del desarrollador. Cada suscripción requiere:

  • URL de devolución de llamada — Un punto final HTTPS de acceso público en su servidor.
  • Eventos — Uno o más tipos de eventos a los que suscribirse.

You'll receive a whsec_ signing secret upon creation. Store it securely — it's shown only once.

Formato de carga útil

Cada entrega de webhook envía un cuerpo JSON con esta estructura:

{ "id": "evt_a1b2c3d4e5f6", "event": "stream.online", "created_at": "2026-03-23T14:30:00Z", "data": { // Event-specific fields (see examples below) } }

Encabezados

Cada entrega incluye los siguientes encabezados para enrutamiento y verificación:

encabezadoDescripción
Content-Typeapplication/json
X-D1Arena-EventTipo de evento (por ejemplo, stream.online)
X-D1Arena-SignatureHMAC-SHA256 resumen hexadecimal del cuerpo de solicitud sin procesar
X-D1Arena-Signature-VersionFormato de clave de firma: v2 para suscripciones actuales o v1-hashed-secret para suscripciones heredadas
X-D1Arena-Delivery-IdUUID de entrega único: uso para deduplicación
X-D1Arena-TimestampMarca de tiempo Unix de cuando se envió el evento

Verificación de firmas

Verifique siempre el encabezado X-D1Arena-Signature antes de procesar un webhook. La firma se calcula como HMAC-SHA256(raw_body, webhook_secret).

Para entregas v2, utilice el secreto whsec_ que se muestra cuando se creó la suscripción. Para una entrega de v1-hashed-secret previa a la actualización, primero calcule SHA256(whsec_secret) a partir de ese secreto original y utilice el resumen hexadecimal en minúsculas resultante como clave HMAC. Vuelva a crear la suscripción cuando sea práctico para pasar a v2.

PHP
// Get the raw body and signature header $payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_D1ARENA_SIGNATURE'] ?? ''; // Compute expected signature $expected = hash_hmac('sha256', $payload, $webhookSecret); // Constant-time comparison to prevent timing attacks if (!hash_equals($expected, $signature)) { http_response_code(401); exit('Invalid signature'); } $event = json_decode($payload, true);
Nodo.js
const crypto = require('crypto'); app.post('/webhook', (req, res) => { const payload = req.rawBody; // Ensure raw body is available const signature = req.headers['x-d1arena-signature']; const expected = crypto .createHmac('sha256', WEBHOOK_SECRET) .update(payload) .digest('hex'); if (!crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature) )) { return res.status(401).send('Invalid signature'); } const event = JSON.parse(payload); // Process event... res.status(200).send('OK'); });
pitón
import hmac, hashlib, json def handle_webhook(request): payload = request.body signature = request.headers.get('X-D1Arena-Signature', '') expected = hmac.new( WEBHOOK_SECRET.encode(), payload, hashlib.sha256 ).hexdigest() if not hmac.compare_digest(expected, signature): return HttpResponse(status=401) event = json.loads(payload) # Process event... return HttpResponse(status=200)

Eventos disponibles

EventoDescripción
stream.onlineUn transmisor se transmitió en vivo
stream.offlineUn transmisor se desconectó
channel.followUn usuario siguió un canal.
channel.subscribeNueva suscripción de seguidor en un canal
channel.tipSe envió un aviso a un transmisor
tournament.startedHa comenzado un partido de torneo
tournament.endedUn torneo ha concluido
tournament.match.completedSe registró el resultado del partido.
clip.createdSe creó un nuevo clip a partir de una transmisión en vivo.
overdrive.startedD1 Frenzy comenzó en un canal
overdrive.level_upD1 Frenzy avanzó al siguiente nivel
overdrive.endedD1 Frenzy completado o caducado

Ejemplos de carga útil de eventos

stream.online

{ "id": "evt_a1b2c3d4e5f6", "event": "stream.online", "created_at": "2026-03-23T14:30:00Z", "data": { "user_id": 42, "user_slug": "progamer99", "name": "ProGamer99", "stream_title": "Ranked Grind - Road to Champion", "category_id": 5, "category_name": "Call of Duty", "protocol": "RTMP", "started_at": "2026-03-23T14:30:00Z" } }

stream.offline

{ "id": "evt_f6e5d4c3b2a1", "event": "stream.offline", "created_at": "2026-03-23T17:45:00Z", "data": { "user_id": 42, "user_slug": "progamer99", "duration_seconds": 11700, "vod_id": 281 } }

channel.follow

{ "id": "evt_c1d2e3f4a5b6", "event": "channel.follow", "created_at": "2026-03-23T15:10:00Z", "data": { "follower_id": 88, "follower_slug": "newplayer", "followed_id": 42, "followed_slug": "progamer99" } }

channel.tip

{ "id": "evt_d1e2f3a4b5c6", "event": "channel.tip", "created_at": "2026-03-23T16:20:00Z", "data": { "streamer_id": 42, "streamer_slug": "progamer99", "tipper_id": 55, "tipper_slug": "clipmaster", "amount": "5.00", "currency": "USD", "message": "Great stream!" } }

tournament.match.completed

{ "id": "evt_e1f2a3b4c5d6", "event": "tournament.match.completed", "created_at": "2026-03-23T21:15:00Z", "data": { "tournament_id": 15, "tournament_title": "Friday Night Frenzy", "match_id": 204, "round": 2, "winner": { "id": 42, "slug": "progamer99", "name": "ProGamer99" }, "loser": { "id": 77, "slug": "rival_x", "name": "Rival_X" }, "score": "3-1" } }

clip.created

{ "id": "evt_b1c2d3e4f5a6", "event": "clip.created", "created_at": "2026-03-23T15:45:00Z", "data": { "clip_id": 99, "slug": "insane-1v4-clutch-abc", "title": "Insane 1v4 clutch", "duration": 28, "streamer_id": 42, "streamer_slug": "progamer99", "creator_id": 55, "creator_slug": "clipmaster", "category_id": 5 } }

Política de entrega y reintento

intentoRetrasoNotas
1º (inicial)InmediatoEnviado a los pocos segundos del evento.
2do (reintentar)30 segundosSi el primer intento falla o se agota el tiempo de espera
3.º (reintentar)2 minutosRetroceso exponencial
4to (final)10 minutosÚltimo intento antes de marcar como fallido
Important: Your endpoint must respond with a 2xx status within 10 segundos. Non-2xx responses or timeouts trigger a retry. After 10 fracasos consecutivos, the subscription is automatically disabled. You'll receive an email notification and can re-enable it in Configuración del desarrollador.

Mejores prácticas

  • Verificar siempre las firmas antes de procesar cargas útiles para evitar eventos falsificados.
  • Utilice el ID de entrega para la deduplicación — Los reintentos envían el mismo ID, por lo tanto, almacene los ID procesados para evitar el doble procesamiento.
  • Responda rápidamente, procese de forma asincrónica — devuelve 200 OK inmediatamente y maneja la lógica empresarial en un trabajo en segundo plano.
  • Utilice únicamente puntos finales HTTPS — Las URL de webhook deben utilizar TLS. Se rechazan las devoluciones de llamada HTTP.
  • Maneje eventos desconocidos con gracia — Se pueden agregar nuevos tipos de eventos. Devuelve 200 para eventos no reconocidos en lugar de errores.

Frenesí D1

D1 Frenzy se activa mediante suscripciones y sugerencias rápidas mientras un transmisor está en vivo. Progresa a través de 5 niveles con objetivos crecientes.

GET /api/overdrive/{streamerId}

Obtén el D1 Frenzy activo para un streamer. Devuelve {"active": false} si no hay ninguno.

{ "active": true, "level": 2, "progress": 150, "target": 250, "progress_pct": 60.0, "total_contributions": 8, "total_contributors": 5, "expires_at": "2026-03-22T15:30:00+00:00" }

Objetivos de nivel

NivelPuntos
1100
2250
3500
41,000
52,000

Frenesí D1 — Puntos: Propina $1 → 100; Suscripción 500 × Nivel. Duración: 5 Minutos; Enfriamiento: 30 Minutos.

SDK de extensión

Cree paneles personalizados y extensiones de superposición que los streamers puedan instalar en las páginas de sus canales. Las extensiones se ejecutan en iframes aislados y se comunican con la página host a través de postMessage.

Empezando

  1. Cree una clave API en Configuración del desarrollador.
  2. Cree su extensión como una página HTML independiente alojada en su dominio (se requiere HTTPS).
  3. Envíelo para su revisión en la sección Mis extensiones.
  4. Una vez aprobado, los streamers pueden instalarlo desde Extension Marketplace.

Tipos de extensión

TipoUbicaciónComportamiento
panelDebajo del reproductor de streamingVisible cuando la transmisión está en vivo. Tarjeta de ancho completo, altura predeterminada de 300 píxeles.
overlaySobre el reproductor de videoVisible en vivo. Posición/tamaño controlado por el streamer a través de la herramienta de posicionamiento de superposición.

API posterior al mensaje

Su extensión recibe datos de contexto automáticamente cuando se carga. Implemente estos eventos:

Utilice el origen padre D1Arena exacto para cada mensaje. El SDK oficial deriva y valida este origen de la página de inserción automáticamente.

Debido a que los iframes de extensión utilizan intencionalmente un origen de espacio aislado opaco, el host D1Arena autentica la ventana iframe registrada exacta. El código de extensión aún debe autenticar la ventana principal y el origen exacto D1Arena antes de aceptar el contexto.

1. Preparación de la señal

var d1ParentOrigin = 'https://d1arena.com'; // Tell the host page your extension is ready for context window.parent.postMessage({ type: 'D1_EXT_READY' }, d1ParentOrigin);

2. Recibir contexto

window.addEventListener('message', function(e) { if (e.source === window.parent && e.origin === d1ParentOrigin && e.data && e.data.type === 'D1_CONTEXT') { var ctx = e.data.payload; // ctx.channelId - Streamer's user ID // ctx.channelName - Streamer's display name // ctx.channelSlug - Streamer's URL slug // ctx.viewerId - Current viewer's ID (null if not logged in) // ctx.isLive - Whether the stream is currently live } });

3. Enviar acciones (opcional)

// Redirect the host page (e.g. for a "Storm" button) window.parent.postMessage({ type: 'D1_EXT_ACTION', action: 'storm', target: 'username-slug' }, d1ParentOrigin);

Alcances de permiso

Declare qué datos necesita su extensión. Los revisores verifican que su código coincida con sus permisos declarados.

AlcanceOtorga acceso a
read:streamEstado de la transmisión, título, categoría
read:viewersRecuento y lista de espectadores
read:chatMensajes de chat (a través del canal Pusher)
read:clipsClips de canal a través de /api/clips/{slug}
read:tournamentsInformación del partido activo a través de /api/active-match/{id}
read:channelPerfil del canal, seguidores, programación.

Requisitos de seguridad

Las extensiones se ejecutan en un iframe en espacio aislado con sandbox="allow-scripts". Su extensión no puedo accede a cookies, localStorage o realiza solicitudes autenticadas a d1arena.com.
  • Público HTTPS requerido — Su URL de iframe debe usar TLS y resolverse solo en direcciones de red públicas.
  • Fuente legible por humanos — Sin JavaScript ofuscado o minimizado. Los revisores deben poder leer su código.
  • Sin carga de script externo a menos que se declare en su presentación. Las bibliotecas CDN (jQuery, Chart.js, etc.) están bien.
  • Sin exfiltración de datos — Las extensiones no deben enviar datos de los espectadores a servicios de seguimiento o análisis de terceros.
  • Política de contenido — Sin anuncios, contenido NSFW, minería de criptomonedas ni comportamiento malicioso.

Proceso de revisión

EstadoSignificado
pendingEnviado, en espera de revisión del administrador (normalmente entre 1 y 3 días hábiles).
approvedAprobado y visible en Extension Marketplace.
rejectedRechazado con una razón. Solucione los problemas y vuelva a enviarlos.
suspendedEliminado temporalmente por infracción de política. Póngase en contacto con el soporte.

Actualizaciones de versión

Para actualizar una extensión aprobada, elimine la versión actual y envíe una nueva con un número de versión incrementado. La nueva versión pasa nuevamente por revisión.

Registro de cambios

Realice un seguimiento de los cambios de API y las nuevas funciones. Seguimos el control de versiones semántico y anunciamos cambios importantes con al menos 30 días de antelación.

v1.0marzo 2026
  • Lanzamiento inicial de API pública con autenticación de clave API.
  • Transmisiones: enumere transmisiones en vivo, obtenga detalles del transmisor por slug.
  • Categorías: busca y enumera todas las categorías de juegos.
  • Usuarios: perfiles públicos con estadísticas competitivas, clasificación ELO y recuento de medallas.
  • Clips: explora y recupera detalles del clip con información del transmisor/creador.
  • Torneos: listar, filtrar por estado/liga, obtener recuentos de participantes.
  • Tabla de clasificación ELO: tablas de clasificación clasificadas globales y por categoría.
  • Ligas: enumera las ligas con clasificaciones y desgloses de puntos.
  • D1 Frenzy: estado de Frenzy en tiempo real para cualquier transmisor.
  • Webhooks (EventSub): 12 tipos de eventos que incluyen transmisiones, canales, torneos, clips y eventos Frenzy.
  • Límites de tarifas

¿Necesitar ayuda?

¿Preguntas sobre el API? Contáctenos.