Passer au contenu principal
D1 Arena

D1 Arena

Loading...

D1 Arena

API développeur

Communauté

API développeur

Créez des robots, des superpositions, des outils de diffusion et des intégrations avec les données D1Arena.

Authentification

Toutes les requêtes API nécessitent une clé API transmise dans l'en-tête X-API-Key / Authorization: Bearer.

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

Pour créer une clé API, accédez à Paramètres du développeur dans votre tableau de bord. Vous pouvez avoir jusqu'à 5 clés.

Les requêtes API sont limitées en débit par clé API. Lorsque vous dépassez la limite, les requêtes renvoient 429 Too Many Requests avec un en-tête Retry-After.

URL de base

https://d1arena.com/api/v1

Tous les points de terminaison renvoient JSON. Les points de terminaison paginés incluent un objet meta avec current_page, last_page et total.

Flux

GET /streams
Répertoriez les diffusions en direct actuellement. Prend en charge la pagination et le filtrage des catégories.
ParamètreTapezDescriptif
category_idintegerFiltrer par ID de jeu/catégorie
limitintegerRésultats par page (par défaut : 20)
pageintegerNuméro de page
Réponse
{ "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}
Obtenez le statut en direct d'un seul streamer et diffusez les détails par nom d'utilisateur ou slug.
Réponse
{ "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" } }

Catégories

GET /categories
Répertoriez toutes les catégories de jeux. Prend en charge la recherche et la pagination.
ParamètreTapezDescriptif
searchstringFiltrer les catégories par nom
limitintegerRésultats par page (par défaut : 50)
Réponse
{ "data": [ { "id": 5, "name": "Call of Duty", "slug": "call-of-duty", "image": "categories/cod.png" } ], "meta": { "total": 24 } }

Utilisateurs

GET /users/{slug}
Obtenez le profil public d'un joueur et les statistiques de compétition par nom d'utilisateur ou slug.
Réponse
{ "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 } } }

Extraits

GET /clips
Répertoriez les clips publics. Prend en charge le filtrage par streamer et par catégorie.
ParamètreTapezDescriptif
streamer_idintegerFiltrer les clips par ID utilisateur du streamer
category_idintegerFiltrer par ID de jeu/catégorie
limitintegerRésultats par page (par défaut : 20)
Réponse
{ "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}
Obtenez les détails d’un seul clip par slug.
Réponse
{ "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" } } }

Tournois

GET /tournaments
Liste des tournois. Prend en charge le filtrage par statut et ligue.
ParamètreTapezDescriptif
statusstringFiltrer par statut (par exemple open, in_progress, completed)
league_idintegerFiltrer par identifiant de ligue
limitintegerRésultats par page (par défaut : 20)
Réponse
{ "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}
Obtenez les détails du tournoi et le nombre de participants.
Réponse
{ "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 } }

Classement ELO

GET /elo/leaderboard
Obtenez le classement ELO. Filtrez éventuellement par catégorie de jeu.
ParamètreTapezDescriptif
category_idintegerFiltrer par ID de jeu/catégorie
limitintegerNombre de résultats (par défaut : 50)
Réponse
{ "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 } }

Ligues

GET /leagues
Répertoriez les ligues avec des filtres de statut et de catégorie facultatifs.
ParamètreTapezDescriptif
statusstringFiltrer par statut de ligue
category_idintegerFiltrer par ID de jeu/catégorie
limitintegerRésultats par page (par défaut : 20)
Réponse
{ "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
Obtenez le classement de la ligue (classement des joueurs par points).
Réponse
{ "data": [ { "id": 1, "points": 2400, "wins": 12, "losses": 3, "user": { "id": 42, "name": "ProGamer99", "user_slug": "progamer99" } } ], "meta": { "total": 48 } }

Réponses aux erreurs

Toutes les erreurs renvoient une enveloppe JSON cohérente. L'objet error contient toujours un code lisible par machine et un message lisible par l'homme.

Format de réponse d'erreur
{ "success": false, "error": { "code": "not_found", "message": "The requested resource could not be found." } }
Format d'erreur de validation (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."] } } }

Codes d'état

200
D'accord — La demande a réussi. La réponse contient les données demandées.
400
Mauvaise demande — La demande est mal formée ou il manque des paramètres requis. Vérifiez le error.message pour plus de détails.
401
Non autorisé — Missing or invalid API key. Ensure you're passing a valid key in the X-API-Key header.
403
Interdit — Votre clé API a été désactivée ou ne dispose pas d'autorisations pour cette ressource. Vérifiez votre Paramètres du développeur.
404
Non trouvé — La ressource demandée n'existe pas. Vérifiez le chemin du slug, de l’ID ou du point de terminaison.
422
Erreur de validation — La validation des paramètres de la demande a échoué. L'objet error.errors mappe les noms de champs à leurs problèmes spécifiques.
429
Tarif Limité — Trop de demandes. L'en-tête Retry-After indique combien de secondes attendre avant de réessayer.
500
Erreur serveur — Une erreur inattendue s'est produite de notre côté. Si cela persiste, contacter l'assistance.

Référence des codes d'erreur

CodeStatut HTTPDescriptif
invalid_api_key401La clé API est manquante, mal formée ou n'existe pas
api_key_disabled403La clé API a été révoquée ou désactivée
not_found404La ressource demandée est introuvable
validation_error422Un ou plusieurs paramètres de requête ne sont pas valides
rate_limited429Limite de taux de requête dépassée pour cette clé API
server_error500Erreur de serveur interne : veuillez réessayer ou contacter l'assistance.

Limites de taux

Les requêtes API sont limitées en débit par clé API. Lorsque vous dépassez la limite, les requêtes renvoient 429 Too Many Requests avec un en-tête Retry-After.

Limites par niveau

NiveauDemandes/minute (Défaut)Nombre maximum de clés
Démarreur (Gratuit)605
PRO605
Ultime605
Partenaire605

En-têtes de limite de débit

Les requêtes API sont limitées en débit par clé API. Lorsque vous dépassez la limite, les requêtes renvoient 429 Too Many Requests avec un en-tête Retry-After.

En-têteDescriptif
Retry-AfterSecondes à attendre avant de réessayer (présent uniquement sur 429 réponses)

Meilleures pratiques

Conseils pour respecter les limites :
  • Cache responses locally — stream and tournament data doesn't change every second.
  • Abonnez-vous à webhooks pour les événements en temps réel au lieu d'interroger les points de terminaison.
  • Requêtes par lots lorsque cela est possible : utilisez les paramètres de filtre pour obtenir exactement ce dont vous avez besoin en moins d'appels.

Webhooks (EventSub)

Abonnez-vous aux notifications push en temps réel au lieu des sondages. Lorsqu'un événement se produit, D1Arena envoie un HTTP POST à ​​votre URL de rappel avec une charge utile JSON signée avec HMAC-SHA256.

Configuration

Créez des abonnements webhook dans Paramètres du développeur. Chaque abonnement nécessite :

  • URL de rappel — Un point de terminaison HTTPS accessible publiquement sur votre serveur.
  • Événements — Un ou plusieurs types d'événements auxquels s'abonner.

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

Format de charge utile

Chaque livraison de webhook envoie un corps JSON avec cette structure :

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

En-têtes

Chaque livraison comprend les en-têtes suivants pour le routage et la vérification :

En-têteDescriptif
Content-Typeapplication/json
X-D1Arena-EventType d'événement (par exemple stream.online)
X-D1Arena-SignatureRésumé hexadécimal HMAC-SHA256 du corps brut de la requête
X-D1Arena-Signature-VersionFormat de clé de signature : v2 pour les abonnements actuels ou v1-hashed-secret pour les anciens abonnements
X-D1Arena-Delivery-IdUUID de livraison unique — à utiliser pour la déduplication
X-D1Arena-TimestampHorodatage Unix du moment où l'événement a été envoyé

Vérification des signatures

Vérifiez toujours l’en-tête X-D1Arena-Signature avant de traiter un webhook. La signature est calculée comme HMAC-SHA256(raw_body, webhook_secret).

Pour les diffusions v2, utilisez le secret whsec_ affiché lors de la création de l'abonnement. Pour une livraison v1-hashed-secret préalable à la mise à niveau, calculez d'abord SHA256(whsec_secret) à partir de ce secret d'origine et utilisez le résumé hexadécimal minuscule résultant comme clé HMAC. Recréez l’abonnement lorsque cela est possible pour passer à 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);
Noeud.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'); });
Python
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)

Événements disponibles

ÉvénementDescriptif
stream.onlineUn streamer est passé en direct
stream.offlineUn streamer s'est déconnecté
channel.followUn utilisateur a suivi une chaîne
channel.subscribeNouvel abonnement de supporter sur une chaîne
channel.tipUn pourboire a été envoyé à un streamer
tournament.startedUn match play de tournoi a commencé
tournament.endedUn tournoi s'est terminé
tournament.match.completedUn résultat de match a été enregistré
clip.createdUn nouveau clip a été créé à partir d'une diffusion en direct
overdrive.startedD1 Frenzy a démarré sur une chaîne
overdrive.level_upD1 Frenzy passe au niveau supérieur
overdrive.endedD1 Frenzy terminé ou expiré

Exemples de charge utile d'événement

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 } }

Politique de livraison et de nouvelle tentative

TentativeRetardRemarques
1er (initiale)ImmédiatEnvoyé quelques secondes après l'événement
2ème (réessayer)30 secondesSi la première tentative échoue ou expire
3ème (réessayer)2 minutesRetard exponentiel
4ème (finale)10 minutesDernière tentative avant de marquer comme échec
Important: Your endpoint must respond with a 2xx status within 10 secondes. Non-2xx responses or timeouts trigger a retry. After 10 échecs consécutifs, the subscription is automatically disabled. You'll receive an email notification and can re-enable it in Paramètres du développeur.

Meilleures pratiques

  • Vérifiez toujours les signatures avant de traiter les charges utiles pour éviter les événements usurpés.
  • Utiliser le Delivery-Id pour la déduplication — les nouvelles tentatives envoient le même identifiant, stockez donc les identifiants traités pour éviter le double traitement.
  • Répondez rapidement, traitez de manière asynchrone — return 200 OK immédiatement et gère la logique métier dans un travail en arrière-plan.
  • Utiliser uniquement les points de terminaison HTTPS — Les URL de webhook doivent utiliser TLS. Les rappels HTTP sont rejetés.
  • Gérez les événements inconnus avec élégance — de nouveaux types d’événements peuvent être ajoutés. Renvoyez 200 pour les événements non reconnus plutôt que les erreurs.

Frénésie D1

D1 Frenzy est déclenché par des conseils et des abonnements rapides pendant qu'un streamer est en direct. Il progresse à travers 5 niveaux avec des objectifs croissants.

GET /api/overdrive/{streamerId}

Obtenez le D1 Frenzy actif pour un streamer. Renvoie {"active": false} s’il n’y en a pas.

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

Objectifs de niveau

NiveauPoints
1100
2250
3500
41,000
52,000

Frénésie D1 — Points: Pourboire $1 → 100; Abonnement 500 × Niveau. Durée: 5 Procès-verbal; Temps de recharge: 30 Procès-verbal.

SDK d'extension

Créez des panneaux personnalisés et des extensions de superposition que les streamers peuvent installer sur les pages de leurs chaînes. Les extensions s'exécutent dans des iframes en bac à sable et communiquent avec la page hôte via postMessage.

Commencer

  1. Créez une clé API dans Paramètres du développeur.
  2. Créez votre extension en tant que page HTML autonome hébergée sur votre domaine (HTTPS requis).
  3. Soumettez-le pour examen dans la section Mes extensions.
  4. Une fois approuvé, les streamers peuvent l’installer à partir d’Extension Marketplace.

Types d'extensions

TapezEmplacementComportement
panelSous le lecteur de fluxVisible lorsque le flux est en direct. Carte pleine largeur, hauteur par défaut de 300 px.
overlaySur le lecteur vidéoVisible en direct. Position/taille contrôlée par le streamer via l'outil de positionnement de superposition.

API postMessage

Votre extension reçoit automatiquement les données contextuelles lors de son chargement. Implémentez ces événements :

Utilisez l’origine exacte du parent D1Arena pour chaque message. Le SDK officiel dérive et valide automatiquement cette origine à partir de la page d'intégration.

Étant donné que les iframes d’extension utilisent intentionnellement une origine sandbox opaque, l’hôte D1Arena authentifie exactement la fenêtre iframe enregistrée. Le code d'extension doit toujours authentifier la fenêtre parent et exacte l'origine D1Arena avant d'accepter le contexte.

1. Préparation du signal

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

2. Recevoir le contexte

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. Envoyer des actions (facultatif)

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

Portées des autorisations

Déclarez les données dont votre extension a besoin. Les réviseurs vérifient que votre code correspond à vos autorisations déclarées.

PortéeAccorde l'accès à
read:streamStatut du flux, titre, catégorie
read:viewersNombre de spectateurs et liste
read:chatMessages de chat (via le canal Pusher)
read:clipsCanaliser les clips via /api/clips/{slug}
read:tournamentsInformations sur le match actif via /api/active-match/{id}
read:channelProfil de la chaîne, abonnés, calendrier

Exigences de sécurité

Les extensions s'exécutent dans un iframe en bac à sable avec sandbox="allow-scripts". Votre extension ne peux pas accède aux cookies, à localStorage ou effectue des demandes authentifiées à d1arena.com.
  • Public HTTPS requis — Votre URL iframe doit utiliser TLS et être résolue uniquement en adresses de réseau public.
  • Source lisible par l'homme — Pas de JavaScript obscurci ou réduit uniquement. Les réviseurs doivent être capables de lire votre code.
  • Pas de chargement de script externe sauf indication contraire dans votre soumission. Les bibliothèques CDN (jQuery, Chart.js, etc.) conviennent.
  • Pas d'exfiltration de données — Les extensions ne doivent pas envoyer les données des spectateurs à des services d'analyse ou de suivi tiers.
  • Politique de contenu — Pas de publicité, de contenu NSFW, d'extraction de crypto-monnaie ou de comportement malveillant.

Processus d'examen

StatutSignification
pendingSoumis, en attente d'examen par l'administrateur (généralement 1 à 3 jours ouvrables).
approvedApprouvé et visible sur Extension Marketplace.
rejectedRejeté avec raison. Résolvez les problèmes et soumettez à nouveau.
suspendedTemporairement supprimé pour non-respect des règles. Contactez l'assistance.

Mises à jour des versions

Pour mettre à jour une extension approuvée, supprimez la version actuelle et soumettez-en une nouvelle avec un numéro de version incrémenté. La nouvelle version est à nouveau révisée.

Journal des modifications

Suivez les modifications de l'API et les nouvelles fonctionnalités. Nous suivons le versioning sémantique et annonçons les modifications majeures au moins 30 jours à l'avance.

v1.0mars 2026
  • Version initiale de l'API publique avec authentification par clé API.
  • Flux : répertoriez les flux en direct et obtenez les détails des streamers par slug.
  • Catégories : recherchez et répertoriez toutes les catégories de jeux.
  • Utilisateurs : profils publics avec statistiques de compétition, classement ELO et nombre de médailles.
  • Clips : parcourez et récupérez les détails des clips avec les informations du streamer/créateur.
  • Tournois : Liste, filtrez par statut/ligue, obtenez le nombre de participants.
  • Classement ELO : classements mondiaux et par catégorie.
  • Ligues : répertoriez les ligues avec leur classement et leur répartition par points.
  • D1 Frenzy : Statut Frenzy en temps réel pour n'importe quel streamer.
  • Webhooks (EventSub) : 12 types d'événements, notamment les événements de flux, de chaîne, de tournoi, de clip et de Frenzy.
  • Limites de taux

Besoin d'aide ?

Des questions sur le API ? Contactez-nous.