주요 콘텐츠로 건너뛰기
D1 Arena

D1 Arena

Loading...

D1 Arena

개발자 API

커뮤니티

개발자 API

봇, 오버레이, 스트리밍 도구를 구축하고 D1Arena 데이터와 통합하세요.

인증

모든 API 요청에는 X-API-Key / Authorization: Bearer 헤더에 전달된 API 키가 필요합니다.

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

API 키를 생성하려면 대시보드에서 개발자 설정로 이동하세요. 최대 5개의 키를 가질 수 있습니다.

API 요청은 API 키별로 속도가 제한됩니다. 제한을 초과하면 요청은 Retry-After 헤더와 함께 429 Too Many Requests를 반환합니다.

기본 URL

https://d1arena.com/api/v1

모든 엔드포인트는 JSON을 반환합니다. 페이지가 매겨진 엔드포인트에는 current_page, last_page 및 total이 포함된 meta 객체가 포함됩니다.

스트림

GET /streams
현재 실시간 스트림을 나열합니다. 페이지 매김 및 카테고리 필터링을 지원합니다.
매개변수유형설명
category_idinteger게임/카테고리 ID로 필터링
limitinteger페이지당 결과(기본값: 20)
pageinteger페이지 번호
응답
{ "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}
사용자 이름이나 슬러그별로 단일 스트리머의 실시간 상태와 스트림 세부 정보를 가져옵니다.
응답
{ "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" } }

카테고리

GET /categories
모든 게임 카테고리를 나열합니다. 검색 및 페이지 매김을 지원합니다.
매개변수유형설명
searchstring이름으로 카테고리 필터링
limitinteger페이지당 결과(기본값: 50)
응답
{ "data": [ { "id": 5, "name": "Call of Duty", "slug": "call-of-duty", "image": "categories/cod.png" } ], "meta": { "total": 24 } }

사용자

GET /users/{slug}
사용자 이름이나 슬러그를 통해 플레이어의 공개 프로필과 경쟁 통계를 확인하세요.
응답
{ "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 } } }

클립

GET /clips
공개 클립을 나열합니다. 스트리머 및 카테고리별 필터링을 지원합니다.
매개변수유형설명
streamer_idinteger스트리머의 사용자 ID로 클립 필터링
category_idinteger게임/카테고리 ID로 필터링
limitinteger페이지당 결과(기본값: 20)
응답
{ "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}
슬러그로 단일 클립의 세부 정보를 가져옵니다.
응답
{ "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" } } }

토너먼트

GET /tournaments
토너먼트를 나열하세요. 상태 및 리그별 필터링을 지원합니다.
매개변수유형설명
statusstring상태별로 필터링(예: open, in_progress, completed)
league_idinteger리그 ID로 필터링
limitinteger페이지당 결과(기본값: 20)
응답
{ "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}
토너먼트 세부 정보 및 참가자 수를 확인하세요.
응답
{ "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 } }

ELO 순위

GET /elo/leaderboard
ELO 순위 리더보드를 받으세요. 선택적으로 게임 카테고리별로 필터링합니다.
매개변수유형설명
category_idinteger게임/카테고리 ID로 필터링
limitinteger결과 수(기본값: 50)
응답
{ "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 } }

리그

GET /leagues
선택적 상태 및 카테고리 필터를 사용하여 리그를 나열합니다.
매개변수유형설명
statusstring리그 상태로 필터링
category_idinteger게임/카테고리 ID로 필터링
limitinteger페이지당 결과(기본값: 20)
응답
{ "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
리그 순위(포인트별 플레이어 순위)를 확인하세요.
응답
{ "data": [ { "id": 1, "points": 2400, "wins": 12, "losses": 3, "user": { "id": 42, "name": "ProGamer99", "user_slug": "progamer99" } } ], "meta": { "total": 48 } }

오류 응답

모든 오류는 일관된 JSON 봉투를 반환합니다. error 객체에는 항상 기계가 읽을 수 있는 code와 사람이 읽을 수 있는 message가 포함되어 있습니다.

오류 응답 형식
{ "success": false, "error": { "code": "not_found", "message": "The requested resource could not be found." } }
유효성 검사 오류 형식(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."] } } }

상태 코드

200
알았어 — 요청이 성공했습니다. 응답에는 요청된 데이터가 포함되어 있습니다.
400
잘못된 요청 — 요청의 형식이 잘못되었거나 필수 매개변수가 누락되었습니다. 자세한 내용은 error.message을 확인하세요.
401
인증되지 않음 — Missing or invalid API key. Ensure you're passing a valid key in the X-API-Key header.
403
권한 없음 — API 키가 비활성화되었거나 이 리소스에 대한 권한이 부족합니다. 당신의 개발자 설정.
404
찾을 수 없습니다 — 요청한 리소스가 존재하지 않습니다. 슬러그, ID 또는 엔드포인트 경로를 확인하세요.
422
검증 오류 — 요청 매개변수 검증에 실패했습니다. error.errors 객체는 필드 이름을 특정 문제에 매핑합니다.
429
요금 제한 — 요청이 너무 많습니다. Retry-After 헤더는 재시도하기 전에 기다려야 하는 시간(초)을 나타냅니다.
500
서버 오류 — 예상치 못한 오류가 발생했습니다. 이것이 지속된다면, 지원팀에 문의.

오류 코드 참조

코드HTTP 상태설명
invalid_api_key401API 키가 누락되었거나 형식이 잘못되었거나 존재하지 않습니다.
api_key_disabled403API 키가 취소되거나 비활성화되었습니다.
not_found404요청한 리소스를 찾을 수 없습니다
validation_error422하나 이상의 요청 매개변수가 잘못되었습니다.
rate_limited429이 API 키에 대한 요청 비율 제한이 초과되었습니다.
server_error500내부 서버 오류 - 다시 시도하거나 지원팀에 문의하세요.

비율 제한

API 요청은 API 키별로 속도가 제한됩니다. 제한을 초과하면 요청은 Retry-After 헤더와 함께 429 Too Many Requests를 반환합니다.

등급별 한도

계층요청/분 (기본)최대 키
기동기 (무료)605
프로605
궁극의605
파트너605

속도 제한 헤더

API 요청은 API 키별로 속도가 제한됩니다. 제한을 초과하면 요청은 Retry-After 헤더와 함께 429 Too Many Requests를 반환합니다.

헤더설명
Retry-After재시도 전 대기 시간(429개 응답에만 표시됨)

모범 사례

한도를 유지하기 위한 팁:
  • Cache responses locally — stream and tournament data doesn't change every second.
  • 엔드포인트를 폴링하는 대신 실시간 이벤트를 위해 webhooks를 구독하세요.
  • 가능한 경우 일괄 요청 — 필터 매개변수를 사용하면 더 적은 호출로 필요한 것을 정확하게 얻을 수 있습니다.

웹후크(EventSub)

폴링 대신 실시간 푸시 알림을 구독하세요. 이벤트가 발생하면 D1Arena는 HMAC-SHA256으로 서명된 JSON 페이로드와 함께 HTTP POST를 콜백 URL로 보냅니다.

설정

개발자 설정에서 웹훅 구독을 생성합니다. 각 구독에는 다음이 필요합니다.

  • 콜백 URL — 서버에서 공개적으로 액세스 가능한 HTTPS 엔드포인트.
  • 이벤트 — 구독할 하나 이상의 이벤트 유형입니다.

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

페이로드 형식

모든 웹훅 전달은 다음 구조의 JSON 본문을 보냅니다.

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

헤더

각 배송에는 라우팅 및 확인을 위한 다음 헤더가 포함됩니다.

헤더설명
Content-Typeapplication/json
X-D1Arena-Event이벤트 유형(예: stream.online)
X-D1Arena-Signature원시 요청 본문의 HMAC-SHA256 16진수 다이제스트
X-D1Arena-Signature-Version서명 키 형식: 현재 구독의 경우 v2, 레거시 구독의 경우 v1-hashed-secret
X-D1Arena-Delivery-Id고유한 전달 UUID — 중복 제거에 사용
X-D1Arena-Timestamp이벤트가 전송된 시점의 Unix 타임스탬프

서명 확인

웹훅을 처리하기 전에 항상 X-D1Arena-Signature 헤더를 확인하세요. 서명은 HMAC-SHA256(raw_body, webhook_secret)로 계산됩니다.

v2 전달의 경우 구독이 생성될 때 표시된 whsec_ 비밀을 사용합니다. 사전 업그레이드 v1-hashed-secret 전달의 경우 먼저 원래 비밀에서 SHA256(whsec_secret)를 계산하고 결과 소문자 16진수 다이제스트를 HMAC 키로 사용합니다. 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);
Node.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'); });
파이썬
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)

이용 가능한 이벤트

이벤트설명
stream.online스트리머가 생방송을 시작했습니다.
stream.offline스트리머가 오프라인 상태가 되었습니다.
channel.follow사용자가 채널을 팔로우했습니다.
channel.subscribe채널의 새로운 후원자 구독
channel.tip스트리머에게 팁이 전송되었습니다.
tournament.started토너먼트 매치 플레이가 시작되었습니다
tournament.ended토너먼트가 종료되었습니다
tournament.match.completed경기 결과가 기록되었습니다
clip.created실시간 스트림에서 새 클립이 생성되었습니다.
overdrive.startedD1 Frenzy가 채널에서 시작되었습니다.
overdrive.level_upD1 Frenzy가 다음 단계로 발전했습니다.
overdrive.endedD1 Frenzy 완료 또는 만료

이벤트 페이로드 예

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

배송 및 재시도 정책

시도지연메모
1위(이니셜)즉시이벤트 발생 후 몇 초 이내에 전송됨
2번째(재시도)30초첫 번째 시도가 실패하거나 시간 초과된 경우
3번째(재시도)2분지수 백오프
4위(최종)10분실패로 표시하기 전 마지막 시도
Important: Your endpoint must respond with a 2xx status within 10초. Non-2xx responses or timeouts trigger a retry. After 10연속 실패, the subscription is automatically disabled. You'll receive an email notification and can re-enable it in 개발자 설정.

모범 사례

  • 항상 서명을 확인하세요. 스푸핑된 이벤트를 방지하기 위해 페이로드를 처리하기 전에.
  • 중복 제거를 위해 배달 ID 사용 — 재시도 시에는 동일한 ID가 전송되므로 이중 처리를 방지하려면 처리된 ID를 저장하세요.
  • 신속한 응답, 비동기식 처리 — 즉시 200 OK를 반환하고 백그라운드 작업에서 비즈니스 로직을 처리합니다.
  • HTTPS 엔드포인트만 사용 — 웹훅 URL은 TLS를 사용해야 합니다. HTTP 콜백이 거부됩니다.
  • 알 수 없는 이벤트를 적절하게 처리 — 새로운 이벤트 유형이 추가될 수 있습니다. 오류가 아닌 인식할 수 없는 이벤트의 경우 200를 반환합니다.

D1 프렌지

D1 Frenzy는 스트리머가 생방송 중일 때 빠른 팁과 구독을 통해 촉발됩니다. 목표가 증가하면서 5단계로 진행됩니다.

GET /api/overdrive/{streamerId}

스트리머를 위한 활성 D1 Frenzy를 얻으세요. 없는 경우 {"active": false}을 반환합니다.

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

레벨 목표

레벨포인트
1100
2250
3500
41,000
52,000

D1 프렌지 — 포인트: 팁 $1 → 100; 구독 500 × 계층. 기간: 5 분; 쿨다운: 30 분.

확장 SDK

스트리머가 채널 페이지에 설치할 수 있는 맞춤형 패널 및 오버레이 확장 프로그램을 구축하세요. 확장 프로그램은 샌드박스 iframe에서 실행되며 postMessage을 통해 호스트 페이지와 통신합니다.

시작하기

  1. 개발자 설정에서 API 키를 생성합니다.
  2. 도메인에서 호스팅되는 독립형 HTML 페이지로 확장 프로그램을 구축하세요(HTTPS 필요).
  3. 검토를 위해 내 확장 프로그램 섹션에 제출하세요.
  4. 승인되면 스트리머는 Extension Marketplace에서 이를 설치할 수 있습니다.

확장 유형

유형위치행동
panel스트림 플레이어 아래스트림이 실시간일 때 표시됩니다. 전체 너비 카드, 기본 높이 300px.
overlay비디오 플레이어 위에서실시간으로 표시됩니다. 오버레이 위치 지정 도구를 통해 스트리머가 제어하는 ​​위치/크기.

포스트메시지 API

확장 프로그램은 로드될 때 자동으로 컨텍스트 데이터를 받습니다. 다음 이벤트를 구현하십시오.

모든 메시지에 대해 정확한 D1Arena 상위 원본을 사용하세요. 공식 SDK은 임베딩 페이지에서 이 출처를 자동으로 파생하고 유효성을 검사합니다.

확장 iframe은 의도적으로 불투명한 샌드박스 원본을 사용하므로 D1Arena 호스트는 등록된 iframe 창을 정확하게 인증합니다. 확장 코드는 컨텍스트를 수락하기 전에 상위 창과 정확한 D1Arena 출처를 인증해야 합니다.

1. 신호 준비

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

2. 컨텍스트 수신

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. 작업 보내기(선택 사항)

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

권한 범위

확장 프로그램에 필요한 데이터를 선언하세요. 검토자는 코드가 선언된 권한과 일치하는지 확인합니다.

범위다음에 대한 액세스 권한을 부여합니다.
read:stream스트림 상태, 제목, 카테고리
read:viewers시청자 수 및 목록
read:chat채팅 메시지(푸셔 채널을 통해)
read:clips/api/clips/{slug}를 통한 채널 클립
read:tournaments/api/active-match/{id}를 통한 활성 경기 정보
read:channel채널 프로필, 팔로어, 일정

보안 요구 사항

확장 프로그램은 sandbox="allow-scripts"을 사용하여 샌드박스 처리된 iframe에서 실행됩니다. 귀하의 확장 프로그램 할 수 없다은 쿠키, localStorage에 액세스하거나 d1arena.com에 인증된 요청을 보냅니다.
  • 공개 HTTPS 필요 — iframe URL은 TLS을 사용해야 하며 공용 네트워크 주소로만 확인되어야 합니다.
  • 사람이 읽을 수 있는 소스 — 난독화되거나 축소된 전용 JavaScript가 없습니다. 검토자는 코드를 읽을 수 있어야 합니다.
  • 외부 스크립트 로딩 없음 귀하의 제출물에 선언되지 않은 한. CDN 라이브러리(jQuery, Chart.js 등)는 괜찮습니다.
  • 데이터 유출 없음 — 확장 프로그램은 시청자 데이터를 제3자 분석 또는 추적 서비스로 전송해서는 안 됩니다.
  • 콘텐츠 정책 — 광고, NSFW 콘텐츠, 암호화폐 채굴 또는 악의적인 행동이 없습니다.

검토 과정

상태의미
pending제출되었으며 관리자 검토를 기다리고 있습니다(일반적으로 영업일 기준 1~3일).
approved확장 마켓플레이스에서 승인되고 표시됩니다.
rejected이유로 거부되었습니다. 문제를 수정하고 다시 제출하세요.
suspended정책 위반으로 인해 일시적으로 삭제되었습니다. 지원팀에 문의하세요.

버전 업데이트

승인된 확장 프로그램을 업데이트하려면 현재 버전을 삭제하고 버전 번호가 증가된 새 버전을 제출하세요. 새 버전은 다시 검토를 거칩니다.

변경 내역

API 변경 사항 및 새로운 기능을 추적합니다. 의미 체계 버전 관리를 따르고 주요 변경 사항을 최소 30일 전에 발표합니다.

v1.02026년 3월
  • API 키 인증이 포함된 최초 공개 API 릴리스입니다.
  • 스트림: 실시간 스트림을 나열하고 슬러그별로 스트리머 세부정보를 가져옵니다.
  • 카테고리: 모든 게임 카테고리를 검색하고 나열합니다.
  • 사용자: 경쟁 통계, ELO 등급 및 메달 개수가 포함된 공개 프로필입니다.
  • 클립: 스트리머/크리에이터 정보가 포함된 클립 세부정보를 탐색하고 검색합니다.
  • 토너먼트: 목록을 작성하고, 상태/리그별로 필터링하고, 참가자 수를 확인하세요.
  • ELO 리더보드: 글로벌 및 카테고리별 순위 리더보드입니다.
  • 리그: 순위 및 포인트 분석이 포함된 리그를 나열합니다.
  • D1 Frenzy: 모든 스트리머의 실시간 Frenzy 상태입니다.
  • 웹후크(EventSub): 스트림, 채널, 토너먼트, 클립, Frenzy 이벤트를 포함한 12가지 이벤트 유형입니다.
  • 비율 제한

도움이 필요하신가요?

API에 대한 질문이 있으신가요? 문의하기.