Spaces:
Sleeping
Sleeping
| """ | |
| 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] | |