2024-12-20 00:42:36 +00:00
|
|
|
openapi: '3.0.3'
|
|
|
|
info:
|
|
|
|
title: Todo REST API
|
|
|
|
version: '1.0.0'
|
|
|
|
description: A RESTful API for managing todo items
|
|
|
|
|
|
|
|
servers:
|
|
|
|
- url: /api/v1
|
|
|
|
description: Base API path
|
|
|
|
|
|
|
|
components:
|
|
|
|
schemas:
|
|
|
|
Todo:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
id:
|
|
|
|
type: string
|
|
|
|
format: uuid
|
|
|
|
readOnly: true
|
|
|
|
title:
|
|
|
|
type: string
|
|
|
|
minLength: 1
|
|
|
|
maxLength: 200
|
|
|
|
description:
|
|
|
|
type: string
|
|
|
|
maxLength: 2000
|
|
|
|
completed:
|
|
|
|
type: boolean
|
|
|
|
default: false
|
|
|
|
dueDate:
|
|
|
|
type: string
|
|
|
|
format: date-time
|
|
|
|
userId:
|
|
|
|
type: string
|
|
|
|
createdAt:
|
|
|
|
type: string
|
|
|
|
format: date-time
|
|
|
|
readOnly: true
|
|
|
|
updatedAt:
|
|
|
|
type: string
|
|
|
|
format: date-time
|
|
|
|
readOnly: true
|
|
|
|
required:
|
|
|
|
- id
|
|
|
|
- title
|
|
|
|
- completed
|
|
|
|
- userId
|
|
|
|
- createdAt
|
|
|
|
- updatedAt
|
|
|
|
|
|
|
|
TodoCreate:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
title:
|
|
|
|
type: string
|
|
|
|
minLength: 1
|
|
|
|
maxLength: 200
|
|
|
|
description:
|
|
|
|
type: string
|
|
|
|
maxLength: 2000
|
|
|
|
dueDate:
|
|
|
|
type: string
|
|
|
|
format: date-time
|
|
|
|
userId:
|
|
|
|
type: string
|
|
|
|
required:
|
|
|
|
- title
|
|
|
|
- userId
|
|
|
|
|
|
|
|
TodoUpdate:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
title:
|
|
|
|
type: string
|
|
|
|
minLength: 1
|
|
|
|
maxLength: 200
|
|
|
|
description:
|
|
|
|
type: string
|
|
|
|
maxLength: 2000
|
|
|
|
completed:
|
|
|
|
type: boolean
|
|
|
|
dueDate:
|
|
|
|
type: string
|
|
|
|
format: date-time
|
|
|
|
minProperties: 1
|
|
|
|
|
|
|
|
TodoList:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
data:
|
2024-12-22 04:15:51 +00:00
|
|
|
type: array
|
|
|
|
items:
|
|
|
|
$ref: '#/components/schemas/Todo'
|
2024-12-20 00:42:36 +00:00
|
|
|
metadata:
|
2024-12-22 04:15:51 +00:00
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
total:
|
|
|
|
type: integer
|
|
|
|
minimum: 0
|
|
|
|
limit:
|
|
|
|
type: integer
|
|
|
|
minimum: 1
|
|
|
|
offset:
|
|
|
|
type: integer
|
|
|
|
minimum: 0
|
|
|
|
required:
|
|
|
|
- total
|
|
|
|
- limit
|
|
|
|
- offset
|
2024-12-20 00:42:36 +00:00
|
|
|
required:
|
|
|
|
- data
|
|
|
|
- metadata
|
|
|
|
|
|
|
|
TodoResponse:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
data:
|
2024-12-22 04:15:51 +00:00
|
|
|
$ref: '#/components/schemas/Todo'
|
2024-12-20 00:42:36 +00:00
|
|
|
required:
|
|
|
|
- data
|
|
|
|
|
|
|
|
Error:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
error:
|
2024-12-22 04:15:51 +00:00
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
code:
|
|
|
|
type: string
|
|
|
|
enum:
|
|
|
|
- VALIDATION_ERROR
|
|
|
|
- UNAUTHORIZED
|
|
|
|
- FORBIDDEN
|
|
|
|
- NOT_FOUND
|
|
|
|
- RATE_LIMIT_EXCEEDED
|
|
|
|
- INTERNAL_ERROR
|
|
|
|
message:
|
|
|
|
type: string
|
|
|
|
details:
|
|
|
|
type: array
|
|
|
|
items:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
field:
|
|
|
|
type: string
|
|
|
|
message:
|
|
|
|
type: string
|
|
|
|
required:
|
|
|
|
- field
|
|
|
|
- message
|
|
|
|
required:
|
|
|
|
- code
|
|
|
|
- message
|
2024-12-20 00:42:36 +00:00
|
|
|
|
|
|
|
parameters:
|
|
|
|
TodoId:
|
|
|
|
name: todoId
|
|
|
|
in: path
|
|
|
|
required: true
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
format: uuid
|
|
|
|
UserId:
|
|
|
|
name: userId
|
|
|
|
in: query
|
|
|
|
required: true
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
Status:
|
|
|
|
name: status
|
|
|
|
in: query
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
enum: [active, completed]
|
|
|
|
Limit:
|
|
|
|
name: limit
|
|
|
|
in: query
|
|
|
|
schema:
|
|
|
|
type: integer
|
|
|
|
minimum: 1
|
|
|
|
maximum: 100
|
|
|
|
default: 50
|
|
|
|
Offset:
|
|
|
|
name: offset
|
|
|
|
in: query
|
|
|
|
schema:
|
|
|
|
type: integer
|
|
|
|
minimum: 0
|
|
|
|
default: 0
|
|
|
|
SortBy:
|
|
|
|
name: sortBy
|
|
|
|
in: query
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
enum: [createdAt, dueDate]
|
|
|
|
default: createdAt
|
|
|
|
SortOrder:
|
|
|
|
name: sortOrder
|
|
|
|
in: query
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
enum: [asc, desc]
|
|
|
|
default: desc
|
|
|
|
|
|
|
|
securitySchemes:
|
|
|
|
bearerAuth:
|
|
|
|
type: http
|
|
|
|
scheme: bearer
|
|
|
|
bearerFormat: JWT
|
|
|
|
|
|
|
|
security:
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
|
|
paths:
|
|
|
|
/todos:
|
|
|
|
get:
|
|
|
|
summary: List todos
|
|
|
|
parameters:
|
|
|
|
- $ref: '#/components/parameters/UserId'
|
|
|
|
- $ref: '#/components/parameters/Status'
|
|
|
|
- $ref: '#/components/parameters/Limit'
|
|
|
|
- $ref: '#/components/parameters/Offset'
|
|
|
|
- $ref: '#/components/parameters/SortBy'
|
|
|
|
- $ref: '#/components/parameters/SortOrder'
|
|
|
|
responses:
|
|
|
|
'200':
|
|
|
|
description: Successfully retrieved todos
|
|
|
|
headers:
|
|
|
|
ETag:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
Last-Modified:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
X-Request-ID:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
X-RateLimit-Limit:
|
|
|
|
schema:
|
|
|
|
type: integer
|
|
|
|
X-RateLimit-Remaining:
|
|
|
|
schema:
|
|
|
|
type: integer
|
|
|
|
X-RateLimit-Reset:
|
|
|
|
schema:
|
|
|
|
type: integer
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/TodoList'
|
|
|
|
'400':
|
|
|
|
description: Invalid parameters
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'401':
|
|
|
|
description: Unauthorized
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'429':
|
|
|
|
description: Too many requests
|
|
|
|
headers:
|
|
|
|
Retry-After:
|
|
|
|
schema:
|
|
|
|
type: integer
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'500':
|
|
|
|
description: Internal server error
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
|
|
post:
|
|
|
|
summary: Create a new todo
|
|
|
|
requestBody:
|
|
|
|
required: true
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/TodoCreate'
|
|
|
|
responses:
|
|
|
|
'201':
|
|
|
|
description: Todo created successfully
|
|
|
|
headers:
|
|
|
|
Location:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
format: uri
|
|
|
|
ETag:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
X-Request-ID:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/TodoResponse'
|
|
|
|
'400':
|
|
|
|
description: Invalid input
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'401':
|
|
|
|
description: Unauthorized
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'500':
|
|
|
|
description: Internal server error
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
|
|
/todos/{todoId}:
|
|
|
|
parameters:
|
|
|
|
- $ref: '#/components/parameters/TodoId'
|
|
|
|
|
|
|
|
get:
|
|
|
|
summary: Get a specific todo
|
|
|
|
responses:
|
|
|
|
'200':
|
|
|
|
description: Successfully retrieved todo
|
|
|
|
headers:
|
|
|
|
ETag:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
Last-Modified:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
X-Request-ID:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/TodoResponse'
|
|
|
|
'401':
|
|
|
|
description: Unauthorized
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'404':
|
|
|
|
description: Todo not found
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'500':
|
|
|
|
description: Internal server error
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
|
|
patch:
|
|
|
|
summary: Update a todo
|
|
|
|
requestBody:
|
|
|
|
required: true
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/TodoUpdate'
|
|
|
|
responses:
|
|
|
|
'200':
|
|
|
|
description: Todo updated successfully
|
|
|
|
headers:
|
|
|
|
ETag:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
X-Request-ID:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/TodoResponse'
|
|
|
|
'400':
|
|
|
|
description: Invalid input
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'401':
|
|
|
|
description: Unauthorized
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'404':
|
|
|
|
description: Todo not found
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'500':
|
|
|
|
description: Internal server error
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
|
|
delete:
|
|
|
|
summary: Delete a todo
|
|
|
|
responses:
|
|
|
|
'204':
|
|
|
|
description: Todo deleted successfully
|
|
|
|
headers:
|
|
|
|
X-Request-ID:
|
|
|
|
schema:
|
|
|
|
type: string
|
|
|
|
'401':
|
|
|
|
description: Unauthorized
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'404':
|
|
|
|
description: Todo not found
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
'500':
|
|
|
|
description: Internal server error
|
|
|
|
content:
|
|
|
|
application/json:
|
|
|
|
schema:
|
|
|
|
$ref: '#/components/schemas/Error'
|