DOJPUBLICAPI · V1
API 文書
DOJの公開ユーザー・問題・コンテスト・レーティングデータをJSONで取得できます。問題文と非公開の運用データは公開されません。
https://doj.kr/api/v1クイックスタート
現在のv1読み取りAPIにAPIキーは不要で、ブラウザーやサーバーから呼び出せます。
const response = await fetch("https://doj.kr/api/v1/users/dadas08/rating-history?limit=200");
if (!response.ok) throw new Error(`DOJ API: ${response.status}`);
const { points } = await response.json();
const chartData = points.map(({ occurredAt, newRating }) => ({
x: new Date(occurredAt),
y: newRating
}));共通規則
- 応答形式
- UTF-8JSON
- CORS
Access-Control-Allow-Origin: *- 日時
- UTCのISO 8601形式の文字列
- リクエスト回数制限
- IPアドレスごとに1分あたり約120リクエスト
レスポンスヘッダーの X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset を確認してください。複数のサーバーインスタンスで処理するため、制限は概算になる場合があります。
非公開の問題・コンテスト、閲覧が制限されたコンテスト問題一覧、メールアドレス、Discordアカウント、権限、提出ソースコードは返しません。プロフィール画像には公開配信用URLを使用し、旧形式のBase64画像は省略する場合があります。
エンドポイント概要
| メソッド | パス | 説明 |
|---|---|---|
| GET | /api/v1/tags | アルゴリズムタグカタログ |
| GET | /api/v1/users | ユーザーを検索 |
| GET | /api/v1/users/{handle} | 公開ユーザープロフィール |
| GET | /api/v1/users/{handle}/contest-participations | 終了したコンテスト参加 |
| GET | /api/v1/users/{handle}/virtual-participations | 終了したカテゴリーバーチャル参加履歴 |
| GET | /api/v1/users/{handle}/rating-history | グラフのレーティング履歴 |
| GET | /api/v1/problems | 公開問題を検索 |
| GET | /api/v1/problems/{displayId} | 公開問題のメタデータ |
| GET | /api/v1/contests | 閲覧可能なコンテストを検索 |
| GET | /api/v1/contests/{slug} | コンテストのメタデータ |
ユーザー
すべてのユーザーAPIエンドポイントで、ハンドルの大文字と小文字を区別します。検索語とパス内のハンドルは、保存されたハンドルと大文字・小文字を一致させてください。
/api/v1/usersユーザーを検索| 名前 | 形式 | デフォルト | 説明 |
|---|---|---|---|
q | string | "" | ハンドルの部分一致(大文字・小文字を区別) |
limit | 1..100 | 20 | 1ページあたりの結果数 |
cursor | string | - | 前のレスポンスのnextCursor |
GET /api/v1/users?q=dadas&limit=20
{
"users": [{
"handle": "dadas08",
"rating": 1542,
"contestsCount": 12,
"solvedProblemCount": 84,
"certified": true,
"avatarUrl": "/api/storage-assets/...",
"countryCode": "KR",
"organization": null
}],
"nextCursor": null
}/api/v1/users/{handle}公開ユーザープロフィール検索結果の項目に自己紹介、アカウント作成日時、フォロワー数とフォロー数を追加します。存在しないアカウントや非公開のアカウントは404を返します。
/api/v1/users/{handle}/contest-participationsコンテスト参加終了済みの公開・招待制コンテストを開催日時の降順で返します。開催中および非公開のコンテストは含みません。limitとcursorに対応しています。
/api/v1/users/{handle}/virtual-participationsカテゴリーバーチャル参加履歴公開カテゴリーで終了したバーチャル参加履歴を返します。チーム記録は実際のメンバーを基準に検索し、問題別スコアと提出は含みません。
| 名前 | 形式 | デフォルト | 説明 |
|---|---|---|---|
limit | 1..200 | 100 | 1ページあたりの履歴データ数 |
cursor | string | - | 前のレスポンスのnextCursor |
{
"user": { "handle": "dadas08" },
"participations": [{
"category": {
"path": "algorithm/graphs",
"contents": [
{ "locale": "en", "name": "Graphs" },
{ "locale": "ko", "name": "그래프" }
]
},
"mode": "TEAM",
"team": { "handle": "graph-team" },
"startedAt": "2026-09-12T09:00:00.000Z",
"endedAt": "2026-09-12T11:00:00.000Z",
"totalScore": 420,
"penaltySeconds": 3510
}],
"nextCursor": null
}/api/v1/users/{handle}/rating-historyレーティンググラフデータ古いデータから順に返します。横軸にはoccurredAt、縦軸にはnewRatingを使用してください。非公開コンテストによる変動も数値の連続性を保ちますが、contestはnullになります。
| 名前 | 形式 | デフォルト | 説明 |
|---|---|---|---|
limit | 1..200 | 100 | 1ページあたりの履歴データ数 |
cursor | string | - | 前のレスポンスのnextCursor |
{
"user": { "handle": "dadas08" },
"points": [{
"id": "...",
"occurredAt": "2026-07-21T09:00:00.000Z",
"oldRating": 1501,
"newRating": 1542,
"delta": 41,
"kind": "CONTEST",
"contest": {
"slug": "doj-contest-1",
"title": "DOJ Contest 1",
"startAt": "2026-07-21T09:00:00.000Z"
}
}],
"nextCursor": null
}問題
/api/v1/problems公開問題を検索| 名前 | 形式 | デフォルト | 説明 |
|---|---|---|---|
q | string | "" | 問題一覧と同じ検索構文: 表示ID、slug、タイトル、@handle、#tag、範囲、論理式 |
difficultyMin | integer | - | 最低難度値 |
difficultyMax | integer | - | 最大難度値 |
tags | CSV | "" | すべて一致する必要があるタグ(最大10個) |
sort | enum | display_id_asc | 下記の並べ替え値のいずれか |
limit | 1..100 | 20 | 1ページあたりの結果数 |
cursor | string | - | 前のレスポンスのnextCursor |
display_id_asc display_id_desc difficulty_asc difficulty_desc solves_desc published_desc
GET /api/v1/problems?tags=dp,graphs&difficultyMin=6&sort=solves_desc
{
"problems": [{
"displayId": 95,
"slug": "95",
"titles": { "ko": "문제 제목", "en": "Problem title" },
"difficulty": 12,
"solveCount": 37,
"timeLimitMs": 2000,
"pythonTimeLimitMs": 4000,
"memoryLimitMb": 512,
"problemType": "STANDARD",
"tags": ["dp", "graphs"],
"authors": ["setter"],
"reviewers": [],
"publishedAt": "2026-08-01T00:00:00.000Z"
}],
"nextCursor": null
}/api/v1/problems/{displayId}公開問題のメタデータ1つの問題について同じメタデータを返します。問題文、入出力の説明、制約、サンプル、解説、採点データは含みません。
コンテスト
/api/v1/contestsコンテストを検索| 名前 | 形式 | デフォルト | 説明 |
|---|---|---|---|
q | string | "" | slugまたはタイトルで検索 |
status | enum | all | すべて・開催予定・開催中・終了済み |
limit | 1..100 | 20 | 1ページあたりの結果数 |
cursor | string | - | 前のレスポンスのnextCursor |
/api/v1/contests/{slug}コンテストのメタデータ開催日時、個別開始型の設定、レーティング対象かどうか、問題数、説明、ルールを返します。非公開のコンテストは404を返します。
ページ分割
nextCursor が null でない場合は、解釈・変更せず次のリクエストの cursor に渡してください。フィルターや並び順を変更したら再利用しないでください。
GET /api/v1/problems?limit=20&cursor=eyJvZmZzZXQiOjIwfQエラーとキャッシング
| HTTP | エラー | 意味 |
|---|---|---|
| 400 | invalid_request | クエリの形式または範囲が不正 |
| 400 | invalid_cursor | カーソルが不正 |
| 404 | not_found | リソースが存在しないか非公開 |
| 429 | rate_limit_exceeded | リクエスト回数制限を超過 |
| 502/503 | api_unavailable | バックエンドの一時的な障害 |
{ "error": "not_found" }Cache-Controlヘッダーに従い、同じデータを繰り返し取得することは避けてください。互換性を失う変更は、新しいバージョンのパスで提供します。
DOJ全般のガイドはこちら: DOJ ガイド。