DOJ logoDOJ
Problems
Recently added problemsSaved problems
CategoriesDLCContestsGroupsTeamsBoard
Ranking
Solved Problem RankingStreak rankingDOJ Power ranking
Status
Call for TasksLoginRegister
DOJ logoDOJ

Community online judge with OI-style subtask scoring, Elo ratings, and Discord-backed certification.

Problems
ProblemsCategories
Community
ContestsRankingBoardNoticesHost an external contestGuide
Account
LoginRegisterJudge Status
Policy
Terms of ServiceDLC RulesPrivacyAPI documentationLanguage runtimesContest rank rewardsRating and performance
© 2026 DOJ
All rights reserved

Policy

  • Terms of Service
  • DLC Rules
  • Privacy
  • API documentation
  • Language runtimes
  • Contest rank rewards
  • Rating and performance

DOJ PUBLIC API · V1

API documentation

Read public DOJ user, problem, contest, and rating data as JSON. Statements and private operational data are not exposed.

Base URLhttps://doj.kr/api/v1
Quick startCommon rulesEndpointsUsersProblemsContestsPaginationErrors

Quick start

The current v1 read API does not require an API key and can be called from browsers or servers.

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

Common rules

Response format
UTF-8 JSON
CORS
Access-Control-Allow-Origin: *
Time
UTC ISO 8601 strings
Rate limit
Approximately 120 requests per minute per IP

Inspect X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset response headers. Limits may be approximate across multiple server instances.

Private problems and contests, protected contest problem lists, emails, Discord accounts, permissions, and submission source are never returned. Profile images use public delivery URLs; legacy Base64 images may be omitted.

Endpoint overview

MethodPathDescription
GET/api/v1/tagsAlgorithm tag catalog
GET/api/v1/usersSearch users
GET/api/v1/users/{handle}Public user profile
GET/api/v1/users/{handle}/contest-participationsFinished contest participations
GET/api/v1/users/{handle}/virtual-participationsFinished category virtual participations
GET/api/v1/users/{handle}/rating-historyRating history for charts
GET/api/v1/problemsSearch public problems
GET/api/v1/problems/{displayId}Public problem metadata
GET/api/v1/contestsSearch visible contests
GET/api/v1/contests/{slug}Contest metadata

Users

User handles are case-sensitive across all user API endpoints. Search terms and handles in paths must use the same letter casing as the stored handle.

GET/api/v1/usersSearch users
NameTypeDefaultDescription
qstring""Case-sensitive partial handle
limit1..10020Results per page
cursorstring-nextCursor from the previous response
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
}
GET/api/v1/users/{handle}Public user profile

Adds bio, account creation time, and follower/following counts to the search fields. Missing or non-public accounts return 404.

GET/api/v1/users/{handle}/contest-participationsContest participations

Returns finished public and invite-only contests in descending contest-time order. Running and private contests are excluded. Supports limit and cursor.

GET/api/v1/users/{handle}/virtual-participationsCategory virtual participations

Returns finished virtual participations in public categories. Team records are matched by actual membership. Per-problem scores and submissions are not included.

NameTypeDefaultDescription
limit1..200100History points per page
cursorstring-nextCursor from the previous response
{
  "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
}
GET/api/v1/users/{handle}/rating-historyRating chart data

Returns oldest points first. Use occurredAt for the x-axis and newRating for the y-axis. Changes from private contests preserve numeric continuity while returning contest as null.

NameTypeDefaultDescription
limit1..200100History points per page
cursorstring-nextCursor from the previous response
{
  "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
}

Problems

GET/api/v1/problemsSearch public problems
NameTypeDefaultDescription
qstring""Search display ID, slug, or title
difficultyMininteger-Minimum difficulty value
difficultyMaxinteger-Maximum difficulty value
tagsCSV""Tags that must all match, up to 10
sortenumdisplay_id_ascOne of the sort values below
limit1..10020Results per page
cursorstring-nextCursor from the previous response

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
}
GET/api/v1/problems/{displayId}Public problem metadata

Returns the same metadata for one problem. Statements, I/O descriptions, constraints, samples, editorials, and judge data are excluded.

Contests

GET/api/v1/contestsSearch contests
NameTypeDefaultDescription
qstring""Search slug or title
statusenumallall, upcoming, running, or ended
limit1..10020Results per page
cursorstring-nextCursor from the previous response
GET/api/v1/contests/{slug}Contest metadata

Returns timing, window settings, rated state, problem count, description, and rules. Private contests return 404.

Pagination

When nextCursor is not null, pass it unchanged as cursor in the next request. Do not decode or edit it, and do not reuse it after changing filters or sort order.

GET /api/v1/problems?limit=20&cursor=eyJvZmZzZXQiOjIwfQ

Errors and caching

HTTPErrorMeaning
400invalid_requestInvalid query shape or range
400invalid_cursorInvalid cursor
404not_foundMissing or non-public resource
429rate_limit_exceededRate limit exceeded
502/503api_unavailableTemporary backend failure
{ "error": "not_found" }

Respect Cache-Control headers and avoid repeatedly requesting identical data. Breaking changes will use a new versioned path.

For the general DOJ guide, see DOJ Guide.