api-design-env / server /problems.py
HIMANSHUKUMARJHA's picture
Upload folder using huggingface_hub
c27ca09 verified
"""
Problem bank for the API Design RL environment.
Each problem defines:
- id, difficulty, title, description, constraints
- ground_truth: the reference endpoint list the grader compares against
"""
from typing import Any, Dict, List, TypedDict
class GroundTruthEndpoint(TypedDict, total=False):
method: str
path: str
description: str
request_body: Dict[str, Any]
response_body: Dict[str, Any]
status_code: int
query_params: List[str]
class Problem(TypedDict):
id: str
difficulty: str
title: str
description: str
constraints: List[str]
ground_truth: List[GroundTruthEndpoint]
PROBLEMS: List[Problem] = [
# ── EASY ─────────────────────────────────────────────────────────
{
"id": "todo_crud",
"difficulty": "easy",
"title": "Todo List CRUD API",
"description": (
"Design a REST API for a simple todo-list application. "
"Users should be able to create, read, update, and delete todo items. "
"Each todo has a title, description, and completed status."
),
"constraints": [
"Support listing all todos with optional filtering by completed status",
"Support getting a single todo by ID",
"Support creating a new todo",
"Support updating an existing todo",
"Support deleting a todo",
],
"ground_truth": [
{
"method": "GET",
"path": "/todos",
"description": "List all todos",
"request_body": {},
"response_body": {"todos": "list", "count": "int"},
"status_code": 200,
"query_params": ["completed", "limit", "offset"],
},
{
"method": "GET",
"path": "/todos/{id}",
"description": "Get a single todo by ID",
"request_body": {},
"response_body": {
"id": "int",
"title": "string",
"description": "string",
"completed": "bool",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/todos",
"description": "Create a new todo",
"request_body": {
"title": "string",
"description": "string",
},
"response_body": {
"id": "int",
"title": "string",
"description": "string",
"completed": "bool",
},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/todos/{id}",
"description": "Update a todo",
"request_body": {
"title": "string",
"description": "string",
"completed": "bool",
},
"response_body": {
"id": "int",
"title": "string",
"description": "string",
"completed": "bool",
},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/todos/{id}",
"description": "Delete a todo",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
],
},
{
"id": "bookmark_manager",
"difficulty": "easy",
"title": "Bookmark Manager API",
"description": (
"Design a REST API for a personal bookmark manager. "
"Users can save, organise, and search their bookmarks. "
"Each bookmark has a URL, title, optional description, and tags."
),
"constraints": [
"Support listing bookmarks with search by title or tag",
"Support creating a bookmark",
"Support updating a bookmark",
"Support deleting a bookmark",
"Support listing all tags in use",
],
"ground_truth": [
{
"method": "GET",
"path": "/bookmarks",
"description": "List bookmarks",
"request_body": {},
"response_body": {"bookmarks": "list", "count": "int"},
"status_code": 200,
"query_params": ["search", "tag", "limit", "offset"],
},
{
"method": "GET",
"path": "/bookmarks/{id}",
"description": "Get a single bookmark",
"request_body": {},
"response_body": {
"id": "int",
"url": "string",
"title": "string",
"description": "string",
"tags": "list",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/bookmarks",
"description": "Create a bookmark",
"request_body": {
"url": "string",
"title": "string",
"tags": "list",
},
"response_body": {
"id": "int",
"url": "string",
"title": "string",
"tags": "list",
},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/bookmarks/{id}",
"description": "Update a bookmark",
"request_body": {
"url": "string",
"title": "string",
"tags": "list",
},
"response_body": {
"id": "int",
"url": "string",
"title": "string",
"tags": "list",
},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/bookmarks/{id}",
"description": "Delete a bookmark",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "GET",
"path": "/tags",
"description": "List all tags",
"request_body": {},
"response_body": {"tags": "list"},
"status_code": 200,
"query_params": [],
},
],
},
{
"id": "notes_app",
"difficulty": "easy",
"title": "Notes App API",
"description": (
"Design a REST API for a simple note-taking application. "
"Users can create, read, update, and delete notes. "
"Notes have a title, body, and created/updated timestamps."
),
"constraints": [
"Support listing notes sorted by last updated",
"Support getting a single note",
"Support creating a note",
"Support updating a note",
"Support deleting a note",
],
"ground_truth": [
{
"method": "GET",
"path": "/notes",
"description": "List all notes",
"request_body": {},
"response_body": {"notes": "list", "count": "int"},
"status_code": 200,
"query_params": ["sort", "limit", "offset"],
},
{
"method": "GET",
"path": "/notes/{id}",
"description": "Get a note",
"request_body": {},
"response_body": {
"id": "int",
"title": "string",
"body": "string",
"created_at": "string",
"updated_at": "string",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/notes",
"description": "Create a note",
"request_body": {"title": "string", "body": "string"},
"response_body": {
"id": "int",
"title": "string",
"body": "string",
},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/notes/{id}",
"description": "Update a note",
"request_body": {"title": "string", "body": "string"},
"response_body": {
"id": "int",
"title": "string",
"body": "string",
},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/notes/{id}",
"description": "Delete a note",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
],
},
{
"id": "contacts_api",
"difficulty": "easy",
"title": "Contacts API",
"description": (
"Design a REST API for managing personal contacts. "
"Each contact has a name, email, phone, and optional company."
),
"constraints": [
"List contacts with search by name or email",
"Get single contact",
"Create contact",
"Update contact",
"Delete contact",
],
"ground_truth": [
{
"method": "GET",
"path": "/contacts",
"description": "List contacts",
"request_body": {},
"response_body": {"contacts": "list", "count": "int"},
"status_code": 200,
"query_params": ["search", "limit", "offset"],
},
{
"method": "GET",
"path": "/contacts/{id}",
"description": "Get contact",
"request_body": {},
"response_body": {
"id": "int",
"name": "string",
"email": "string",
"phone": "string",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/contacts",
"description": "Create contact",
"request_body": {
"name": "string",
"email": "string",
"phone": "string",
},
"response_body": {
"id": "int",
"name": "string",
"email": "string",
},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/contacts/{id}",
"description": "Update contact",
"request_body": {
"name": "string",
"email": "string",
"phone": "string",
},
"response_body": {
"id": "int",
"name": "string",
"email": "string",
},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/contacts/{id}",
"description": "Delete contact",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
],
},
# ── MEDIUM ───────────────────────────────────────────────────────
{
"id": "ecommerce_products",
"difficulty": "medium",
"title": "E-Commerce Product Catalog API",
"description": (
"Design a REST API for an e-commerce product catalog. "
"Products belong to categories, have images, variants "
"(size/color), pricing, and inventory counts. "
"Support filtering, sorting, and pagination."
),
"constraints": [
"List products with filtering by category, price range, and availability",
"Support sorting by price, name, or created date",
"CRUD for products",
"Manage product categories",
"Manage product variants (size, color, stock)",
],
"ground_truth": [
{
"method": "GET",
"path": "/products",
"description": "List products with filters",
"request_body": {},
"response_body": {"products": "list", "total": "int"},
"status_code": 200,
"query_params": [
"category",
"min_price",
"max_price",
"in_stock",
"sort",
"limit",
"offset",
],
},
{
"method": "GET",
"path": "/products/{id}",
"description": "Get product details",
"request_body": {},
"response_body": {
"id": "int",
"name": "string",
"price": "float",
"category": "string",
"variants": "list",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/products",
"description": "Create product",
"request_body": {
"name": "string",
"price": "float",
"category_id": "int",
"description": "string",
},
"response_body": {"id": "int", "name": "string", "price": "float"},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/products/{id}",
"description": "Update product",
"request_body": {
"name": "string",
"price": "float",
"description": "string",
},
"response_body": {"id": "int", "name": "string", "price": "float"},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/products/{id}",
"description": "Delete product",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "GET",
"path": "/categories",
"description": "List categories",
"request_body": {},
"response_body": {"categories": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/categories",
"description": "Create category",
"request_body": {"name": "string"},
"response_body": {"id": "int", "name": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/products/{id}/variants",
"description": "List product variants",
"request_body": {},
"response_body": {"variants": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/products/{id}/variants",
"description": "Create product variant",
"request_body": {
"size": "string",
"color": "string",
"stock": "int",
"price_modifier": "float",
},
"response_body": {
"id": "int",
"size": "string",
"color": "string",
"stock": "int",
},
"status_code": 201,
"query_params": [],
},
],
},
{
"id": "blog_platform",
"difficulty": "medium",
"title": "Blog Platform API",
"description": (
"Design a REST API for a blog platform. "
"Authors write posts, readers leave comments. "
"Posts can be drafted or published, and have tags."
),
"constraints": [
"CRUD for blog posts",
"Support draft and published states for posts",
"CRUD for comments on a post",
"List posts with filtering by author, tag, and status",
"Manage tags",
],
"ground_truth": [
{
"method": "GET",
"path": "/posts",
"description": "List posts",
"request_body": {},
"response_body": {"posts": "list", "total": "int"},
"status_code": 200,
"query_params": ["author", "tag", "status", "limit", "offset"],
},
{
"method": "GET",
"path": "/posts/{id}",
"description": "Get a post",
"request_body": {},
"response_body": {
"id": "int",
"title": "string",
"body": "string",
"status": "string",
"author": "string",
"tags": "list",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/posts",
"description": "Create a post",
"request_body": {
"title": "string",
"body": "string",
"tags": "list",
"status": "string",
},
"response_body": {"id": "int", "title": "string", "status": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/posts/{id}",
"description": "Update a post",
"request_body": {
"title": "string",
"body": "string",
"tags": "list",
"status": "string",
},
"response_body": {"id": "int", "title": "string", "status": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/posts/{id}",
"description": "Delete a post",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "PATCH",
"path": "/posts/{id}",
"description": "Publish or unpublish a post",
"request_body": {"status": "string"},
"response_body": {"id": "int", "status": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "GET",
"path": "/posts/{post_id}/comments",
"description": "List comments on a post",
"request_body": {},
"response_body": {"comments": "list", "count": "int"},
"status_code": 200,
"query_params": ["limit", "offset"],
},
{
"method": "POST",
"path": "/posts/{post_id}/comments",
"description": "Add a comment",
"request_body": {"body": "string", "author": "string"},
"response_body": {"id": "int", "body": "string", "author": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "DELETE",
"path": "/posts/{post_id}/comments/{id}",
"description": "Delete a comment",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "GET",
"path": "/tags",
"description": "List tags",
"request_body": {},
"response_body": {"tags": "list"},
"status_code": 200,
"query_params": [],
},
],
},
{
"id": "event_management",
"difficulty": "medium",
"title": "Event Management API",
"description": (
"Design a REST API for an event management platform. "
"Organisers create events, attendees register. "
"Events have dates, locations, capacity limits, and ticket types."
),
"constraints": [
"CRUD for events",
"Register and unregister attendees for an event",
"List events with filtering by date range and location",
"Manage ticket types per event",
"Get attendee list for an event",
],
"ground_truth": [
{
"method": "GET",
"path": "/events",
"description": "List events",
"request_body": {},
"response_body": {"events": "list", "total": "int"},
"status_code": 200,
"query_params": [
"start_date",
"end_date",
"location",
"limit",
"offset",
],
},
{
"method": "GET",
"path": "/events/{id}",
"description": "Get event details",
"request_body": {},
"response_body": {
"id": "int",
"title": "string",
"date": "string",
"location": "string",
"capacity": "int",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/events",
"description": "Create event",
"request_body": {
"title": "string",
"date": "string",
"location": "string",
"capacity": "int",
},
"response_body": {"id": "int", "title": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/events/{id}",
"description": "Update event",
"request_body": {
"title": "string",
"date": "string",
"location": "string",
},
"response_body": {"id": "int", "title": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/events/{id}",
"description": "Delete event",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "POST",
"path": "/events/{event_id}/registrations",
"description": "Register attendee",
"request_body": {
"attendee_name": "string",
"email": "string",
"ticket_type": "string",
},
"response_body": {"id": "int", "attendee_name": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "DELETE",
"path": "/events/{event_id}/registrations/{id}",
"description": "Unregister attendee",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "GET",
"path": "/events/{event_id}/registrations",
"description": "List attendees",
"request_body": {},
"response_body": {"registrations": "list", "count": "int"},
"status_code": 200,
"query_params": ["limit", "offset"],
},
{
"method": "GET",
"path": "/events/{event_id}/tickets",
"description": "List ticket types",
"request_body": {},
"response_body": {"tickets": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/events/{event_id}/tickets",
"description": "Create ticket type",
"request_body": {
"name": "string",
"price": "float",
"quantity": "int",
},
"response_body": {"id": "int", "name": "string", "price": "float"},
"status_code": 201,
"query_params": [],
},
],
},
{
"id": "task_board",
"difficulty": "medium",
"title": "Kanban Task Board API",
"description": (
"Design a REST API for a kanban-style task board. "
"Boards contain columns, columns contain cards. "
"Cards can be assigned to users and have labels."
),
"constraints": [
"CRUD for boards",
"CRUD for columns within a board",
"CRUD for cards within a column",
"Assign and unassign users to cards",
"Move cards between columns",
],
"ground_truth": [
{
"method": "GET",
"path": "/boards",
"description": "List boards",
"request_body": {},
"response_body": {"boards": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/boards",
"description": "Create board",
"request_body": {"name": "string"},
"response_body": {"id": "int", "name": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/boards/{board_id}/columns",
"description": "List columns",
"request_body": {},
"response_body": {"columns": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/boards/{board_id}/columns",
"description": "Create column",
"request_body": {"name": "string", "position": "int"},
"response_body": {"id": "int", "name": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/columns/{column_id}/cards",
"description": "List cards in column",
"request_body": {},
"response_body": {"cards": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/columns/{column_id}/cards",
"description": "Create card",
"request_body": {
"title": "string",
"description": "string",
"labels": "list",
},
"response_body": {"id": "int", "title": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/cards/{id}",
"description": "Update card",
"request_body": {"title": "string", "description": "string"},
"response_body": {"id": "int", "title": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "PATCH",
"path": "/cards/{id}/move",
"description": "Move card to another column",
"request_body": {"column_id": "int", "position": "int"},
"response_body": {"id": "int", "column_id": "int"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/cards/{card_id}/assignees",
"description": "Assign user to card",
"request_body": {"user_id": "int"},
"response_body": {"card_id": "int", "user_id": "int"},
"status_code": 201,
"query_params": [],
},
{
"method": "DELETE",
"path": "/cards/{card_id}/assignees/{user_id}",
"description": "Unassign user",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
],
},
# ── HARD ─────────────────────────────────────────────────────────
{
"id": "multi_tenant_saas",
"difficulty": "hard",
"title": "Multi-Tenant SaaS API with RBAC",
"description": (
"Design a REST API for a multi-tenant SaaS platform. "
"Each tenant (organisation) has users with different roles "
"(admin, editor, viewer). Admins manage users and settings. "
"The API must scope all resources to their tenant."
),
"constraints": [
"CRUD for tenants (organisations)",
"Manage users within a tenant",
"Role-based access: admin, editor, viewer",
"Invite users to a tenant",
"Tenant-level settings management",
"All resource paths scoped under /tenants/{tenant_id}",
],
"ground_truth": [
{
"method": "POST",
"path": "/tenants",
"description": "Create tenant",
"request_body": {"name": "string", "plan": "string"},
"response_body": {"id": "int", "name": "string", "plan": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/tenants/{tenant_id}",
"description": "Get tenant details",
"request_body": {},
"response_body": {
"id": "int",
"name": "string",
"plan": "string",
"user_count": "int",
},
"status_code": 200,
"query_params": [],
},
{
"method": "PUT",
"path": "/tenants/{tenant_id}",
"description": "Update tenant",
"request_body": {"name": "string", "plan": "string"},
"response_body": {"id": "int", "name": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "GET",
"path": "/tenants/{tenant_id}/users",
"description": "List tenant users",
"request_body": {},
"response_body": {"users": "list", "count": "int"},
"status_code": 200,
"query_params": ["role", "limit", "offset"],
},
{
"method": "POST",
"path": "/tenants/{tenant_id}/users",
"description": "Add user to tenant",
"request_body": {
"email": "string",
"name": "string",
"role": "string",
},
"response_body": {
"id": "int",
"email": "string",
"role": "string",
},
"status_code": 201,
"query_params": [],
},
{
"method": "PATCH",
"path": "/tenants/{tenant_id}/users/{user_id}",
"description": "Update user role",
"request_body": {"role": "string"},
"response_body": {"id": "int", "role": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/tenants/{tenant_id}/users/{user_id}",
"description": "Remove user from tenant",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "POST",
"path": "/tenants/{tenant_id}/invitations",
"description": "Invite user",
"request_body": {"email": "string", "role": "string"},
"response_body": {
"id": "int",
"email": "string",
"status": "string",
},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/tenants/{tenant_id}/settings",
"description": "Get tenant settings",
"request_body": {},
"response_body": {"settings": "dict"},
"status_code": 200,
"query_params": [],
},
{
"method": "PUT",
"path": "/tenants/{tenant_id}/settings",
"description": "Update tenant settings",
"request_body": {"settings": "dict"},
"response_body": {"settings": "dict"},
"status_code": 200,
"query_params": [],
},
],
},
{
"id": "file_storage_api",
"difficulty": "hard",
"title": "Cloud File Storage API",
"description": (
"Design a REST API for a cloud file storage service (like a "
"simplified Dropbox). Support folders, files, sharing, and "
"version history."
),
"constraints": [
"CRUD for folders (nested hierarchy)",
"Upload, download, rename, and delete files",
"Share files/folders with other users (read/write permissions)",
"List file version history",
"Move files between folders",
"Search files by name",
],
"ground_truth": [
{
"method": "GET",
"path": "/folders/{id}",
"description": "Get folder contents",
"request_body": {},
"response_body": {
"id": "int",
"name": "string",
"files": "list",
"subfolders": "list",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/folders",
"description": "Create folder",
"request_body": {"name": "string", "parent_id": "int"},
"response_body": {"id": "int", "name": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "DELETE",
"path": "/folders/{id}",
"description": "Delete folder",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "POST",
"path": "/files",
"description": "Upload file",
"request_body": {
"name": "string",
"folder_id": "int",
"content": "binary",
},
"response_body": {
"id": "int",
"name": "string",
"size": "int",
"version": "int",
},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/files/{id}",
"description": "Download file",
"request_body": {},
"response_body": {"content": "binary", "name": "string"},
"status_code": 200,
"query_params": ["version"],
},
{
"method": "PUT",
"path": "/files/{id}",
"description": "Update file metadata",
"request_body": {"name": "string"},
"response_body": {"id": "int", "name": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/files/{id}",
"description": "Delete file",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "PATCH",
"path": "/files/{id}/move",
"description": "Move file to folder",
"request_body": {"folder_id": "int"},
"response_body": {"id": "int", "folder_id": "int"},
"status_code": 200,
"query_params": [],
},
{
"method": "GET",
"path": "/files/{id}/versions",
"description": "List file versions",
"request_body": {},
"response_body": {"versions": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/files/{id}/share",
"description": "Share file with user",
"request_body": {
"user_id": "int",
"permission": "string",
},
"response_body": {
"id": "int",
"user_id": "int",
"permission": "string",
},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/files/search",
"description": "Search files",
"request_body": {},
"response_body": {"files": "list", "count": "int"},
"status_code": 200,
"query_params": ["query", "folder_id", "limit", "offset"],
},
],
},
{
"id": "messaging_platform",
"difficulty": "hard",
"title": "Real-Time Messaging API",
"description": (
"Design a REST API for a messaging platform. "
"Users create channels, send messages, react to messages, "
"and manage channel membership. Support threads and pinning."
),
"constraints": [
"CRUD for channels",
"Send, edit, and delete messages in a channel",
"Thread replies on messages",
"React to messages with emoji",
"Manage channel members (add/remove/list)",
"Pin and unpin messages",
],
"ground_truth": [
{
"method": "GET",
"path": "/channels",
"description": "List channels",
"request_body": {},
"response_body": {"channels": "list"},
"status_code": 200,
"query_params": ["limit", "offset"],
},
{
"method": "POST",
"path": "/channels",
"description": "Create channel",
"request_body": {"name": "string", "description": "string"},
"response_body": {"id": "int", "name": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/channels/{channel_id}/messages",
"description": "List messages",
"request_body": {},
"response_body": {"messages": "list"},
"status_code": 200,
"query_params": ["before", "after", "limit"],
},
{
"method": "POST",
"path": "/channels/{channel_id}/messages",
"description": "Send message",
"request_body": {"content": "string"},
"response_body": {"id": "int", "content": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "PUT",
"path": "/channels/{channel_id}/messages/{id}",
"description": "Edit message",
"request_body": {"content": "string"},
"response_body": {"id": "int", "content": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/channels/{channel_id}/messages/{id}",
"description": "Delete message",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "POST",
"path": "/messages/{message_id}/reactions",
"description": "React to message",
"request_body": {"emoji": "string"},
"response_body": {"message_id": "int", "emoji": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "DELETE",
"path": "/messages/{message_id}/reactions/{emoji}",
"description": "Remove reaction",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "GET",
"path": "/messages/{message_id}/thread",
"description": "Get thread replies",
"request_body": {},
"response_body": {"replies": "list"},
"status_code": 200,
"query_params": ["limit", "offset"],
},
{
"method": "POST",
"path": "/messages/{message_id}/thread",
"description": "Reply in thread",
"request_body": {"content": "string"},
"response_body": {"id": "int", "content": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "POST",
"path": "/channels/{channel_id}/members",
"description": "Add member",
"request_body": {"user_id": "int"},
"response_body": {"channel_id": "int", "user_id": "int"},
"status_code": 201,
"query_params": [],
},
{
"method": "DELETE",
"path": "/channels/{channel_id}/members/{user_id}",
"description": "Remove member",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "POST",
"path": "/channels/{channel_id}/pins",
"description": "Pin message",
"request_body": {"message_id": "int"},
"response_body": {"channel_id": "int", "message_id": "int"},
"status_code": 201,
"query_params": [],
},
{
"method": "DELETE",
"path": "/channels/{channel_id}/pins/{message_id}",
"description": "Unpin message",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
],
},
# ── HARD: frontier-challenging ─────────────────────────────────────
{
"id": "ci_cd_pipeline_api",
"difficulty": "hard",
"title": "CI/CD Pipeline Orchestration API",
"description": (
"Design a REST API for a CI/CD pipeline orchestration platform "
"(like a simplified GitHub Actions / GitLab CI). Organisations "
"define pipelines with stages, stages contain jobs, jobs produce "
"artifacts and logs. Pipelines are triggered by webhooks or "
"manually, and support parameterised runs, retries of individual "
"failed jobs, and cancellation of in-progress runs."
),
"constraints": [
"CRUD for pipeline definitions (YAML-like config)",
"Trigger a pipeline run (manual or webhook)",
"List and filter runs by status (pending/running/success/failed)",
"Get detailed run status with per-stage and per-job breakdown",
"Retry a specific failed job within a run",
"Cancel an in-progress run",
"Stream or fetch job logs",
"Download job artifacts",
"Manage webhook triggers for a pipeline",
"Manage pipeline-level environment variables (secrets)",
],
"ground_truth": [
{
"method": "GET",
"path": "/pipelines",
"description": "List pipeline definitions",
"request_body": {},
"response_body": {"pipelines": "list", "total": "int"},
"status_code": 200,
"query_params": ["limit", "offset"],
},
{
"method": "POST",
"path": "/pipelines",
"description": "Create pipeline definition",
"request_body": {
"name": "string",
"config": "object",
"description": "string",
},
"response_body": {"id": "int", "name": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/pipelines/{id}",
"description": "Get pipeline definition",
"request_body": {},
"response_body": {
"id": "int",
"name": "string",
"config": "object",
"stages": "list",
},
"status_code": 200,
"query_params": [],
},
{
"method": "PUT",
"path": "/pipelines/{id}",
"description": "Update pipeline definition",
"request_body": {"name": "string", "config": "object"},
"response_body": {"id": "int", "name": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "DELETE",
"path": "/pipelines/{id}",
"description": "Delete pipeline",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "POST",
"path": "/pipelines/{pipeline_id}/runs",
"description": "Trigger a pipeline run",
"request_body": {
"parameters": "object",
"branch": "string",
},
"response_body": {
"id": "int",
"status": "string",
"pipeline_id": "int",
},
"status_code": 201,
"query_params": [],
},
{
"method": "GET",
"path": "/pipelines/{pipeline_id}/runs",
"description": "List runs for a pipeline",
"request_body": {},
"response_body": {"runs": "list", "total": "int"},
"status_code": 200,
"query_params": ["status", "limit", "offset"],
},
{
"method": "GET",
"path": "/runs/{run_id}",
"description": "Get run details with stage/job breakdown",
"request_body": {},
"response_body": {
"id": "int",
"status": "string",
"stages": "list",
"started_at": "string",
"finished_at": "string",
},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/runs/{run_id}/cancel",
"description": "Cancel an in-progress run",
"request_body": {},
"response_body": {"id": "int", "status": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/runs/{run_id}/jobs/{job_id}/retry",
"description": "Retry a failed job",
"request_body": {},
"response_body": {"id": "int", "status": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "GET",
"path": "/runs/{run_id}/jobs/{job_id}/logs",
"description": "Get job logs",
"request_body": {},
"response_body": {"lines": "list", "job_id": "int"},
"status_code": 200,
"query_params": ["tail", "since"],
},
{
"method": "GET",
"path": "/runs/{run_id}/jobs/{job_id}/artifacts",
"description": "List job artifacts",
"request_body": {},
"response_body": {"artifacts": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "GET",
"path": "/runs/{run_id}/jobs/{job_id}/artifacts/{artifact_id}",
"description": "Download artifact",
"request_body": {},
"response_body": {"content": "binary", "name": "string"},
"status_code": 200,
"query_params": [],
},
{
"method": "GET",
"path": "/pipelines/{pipeline_id}/webhooks",
"description": "List webhooks for pipeline",
"request_body": {},
"response_body": {"webhooks": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "POST",
"path": "/pipelines/{pipeline_id}/webhooks",
"description": "Create webhook trigger",
"request_body": {
"url": "string",
"events": "list",
"secret": "string",
},
"response_body": {"id": "int", "url": "string"},
"status_code": 201,
"query_params": [],
},
{
"method": "DELETE",
"path": "/pipelines/{pipeline_id}/webhooks/{id}",
"description": "Delete webhook",
"request_body": {},
"response_body": {},
"status_code": 204,
"query_params": [],
},
{
"method": "GET",
"path": "/pipelines/{pipeline_id}/variables",
"description": "List environment variables",
"request_body": {},
"response_body": {"variables": "list"},
"status_code": 200,
"query_params": [],
},
{
"method": "PUT",
"path": "/pipelines/{pipeline_id}/variables",
"description": "Set environment variables",
"request_body": {"variables": "object"},
"response_body": {"variables": "object"},
"status_code": 200,
"query_params": [],
},
],
},
]
def get_problem(problem_id: str) -> Problem:
for p in PROBLEMS:
if p["id"] == problem_id:
return p
raise ValueError(f"Unknown problem: {problem_id}")
def get_problems_by_difficulty(difficulty: str) -> List[Problem]:
return [p for p in PROBLEMS if p["difficulty"] == difficulty]