Skip to main content

Examples

Each example below is a small Go package in testdata/ turned into an OpenAPI 3.1 document by a single apiary command. The same files back apiary's golden tests, so what you see here is exactly what the tool emits.

net/http (Task Manager)

Standard (ctx, req) (resp, error) handlers. The request and response types, the operationId, and the summary all come from the signatures and doc comments; the validate: and doc: struct tags become schema constraints and descriptions.

apiary -security bearer -title "Task Manager API" -version "1.0.0" -out docs/tasks.yaml ./testdata/router

Handlers (testdata/router/router.go):

// Package router is an example task-manager service annotated for apiary.
//
// apiary -security bearer -title "Task Manager API" -version "1.0.0" -out docs/tasks.yaml ./testdata/router
package router

import "context"

type AuthHandler struct{}
type TaskHandler struct{}
type CommentHandler struct{}

// apiary:operation POST /api/v1/auth/login
// summary: Log in
// description: Returns a JWT for a username and password.
// tags: auth
// security: none
// errors: 400,401,500
func (h *AuthHandler) Login(ctx context.Context, req LoginRequest) (LoginResponse, error) {
return LoginResponse{}, nil
}

// apiary:operation POST /api/v1/auth/refresh
// summary: Refresh token
// tags: auth
// security: bearer
// errors: 401,500
func (h *AuthHandler) Refresh(ctx context.Context, req RefreshRequest) (LoginResponse, error) {
return LoginResponse{}, nil
}

// apiary:operation GET /api/v1/tasks
// summary: List tasks
// description: Supports filtering by status and priority, and pagination.
// tags: tasks
// errors: 400,401,500
func (h *TaskHandler) List(ctx context.Context, req ListTasksRequest) (ListTasksResponse, error) {
return ListTasksResponse{}, nil
}

// apiary:operation GET /api/v1/tasks/{id}
// summary: Get task by ID
// tags: tasks
// errors: 401,404,500
func (h *TaskHandler) Get(ctx context.Context, req GetTaskRequest) (TaskDTO, error) {
return TaskDTO{}, nil
}

// apiary:operation POST /api/v1/tasks
// summary: Create task
// tags: tasks
// errors: 400,401,422,500
func (h *TaskHandler) Create(ctx context.Context, req CreateTaskRequest) (TaskDTO, error) {
return TaskDTO{}, nil
}

// apiary:operation PUT /api/v1/tasks/{id}
// summary: Update task
// tags: tasks
// errors: 400,401,403,404,422,500
func (h *TaskHandler) Update(ctx context.Context, req UpdateTaskRequest) (TaskDTO, error) {
return TaskDTO{}, nil
}

// apiary:operation DELETE /api/v1/tasks/{id}
// summary: Delete task
// description: Only the task creator or an administrator.
// tags: tasks
// errors: 401,403,404,500
func (h *TaskHandler) Delete(ctx context.Context, req DeleteTaskRequest) (DeleteTaskResponse, error) {
return DeleteTaskResponse{}, nil
}

// apiary:operation GET /api/v1/tasks/{task_id}/comments
// summary: List task comments
// tags: comments
// errors: 401,404,500
func (h *CommentHandler) List(ctx context.Context, req ListCommentsRequest) (ListCommentsResponse, error) {
return ListCommentsResponse{}, nil
}

// apiary:operation POST /api/v1/tasks/{task_id}/comments
// summary: Add comment
// tags: comments
// errors: 400,401,404,500
func (h *CommentHandler) Add(ctx context.Context, req AddCommentRequest) (CommentDTO, error) {
return CommentDTO{}, nil
}

Types (testdata/router/types.go):

package router

import "time"

type TaskDTO struct {
ID int64 `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Status string `json:"status" doc:"todo | in_progress | done"`
Priority int `json:"priority" doc:"1 = low, 3 = high"`
AssignedTo *UserBrief `json:"assigned_to"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

type UserBrief struct {
ID int64 `json:"id"`
Username string `json:"username"`
}

type CommentDTO struct {
ID int64 `json:"id"`
TaskID int64 `json:"task_id"`
Author UserBrief `json:"author"`
Body string `json:"body"`
CreatedAt time.Time `json:"created_at"`
}

type LoginRequest struct {
Username string `json:"username" validate:"required" example:"larry"`
Password string `json:"password" validate:"required" example:"s3cret"`
}

type RefreshRequest struct {
Token string `header:"Authorization" validate:"required" doc:"Bearer <token>"`
}

type LoginResponse struct {
Token string `json:"token"`
ExpiresIn int `json:"expires_in" example:"3600"`
}

type ListTasksRequest struct {
Status string `query:"status" doc:"todo | in_progress | done" example:"todo"`
Priority int `query:"priority" doc:"1-3"`
Page int `query:"page" default:"1" example:"1"`
PageSize int `query:"page_size" default:"20" example:"20"`
}

type ListTasksResponse struct {
Tasks []TaskDTO `json:"tasks"`
Total int `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}

type GetTaskRequest struct {
ID int64 `path:"id" validate:"required" example:"42"`
}

type CreateTaskRequest struct {
Title string `json:"title" validate:"required" example:"Production is down"`
Description string `json:"description" example:"OOM killer terminated the service around 03:00"`
Priority int `json:"priority" doc:"1-3" example:"3"`
AssigneeID int64 `json:"assignee_id"`
}

type UpdateTaskRequest struct {
ID int64 `path:"id" validate:"required"`
Title string `json:"title"`
Description string `json:"description"`
Status string `json:"status" example:"in_progress"`
Priority int `json:"priority"`
AssigneeID int64 `json:"assignee_id"`
}

type DeleteTaskRequest struct {
ID int64 `path:"id" validate:"required" example:"42"`
}

type DeleteTaskResponse struct {
ID int64 `json:"id"`
Success bool `json:"success"`
}

type ListCommentsRequest struct {
TaskID int64 `path:"task_id" validate:"required" example:"42"`
}

type ListCommentsResponse struct {
Comments []CommentDTO `json:"comments"`
Total int `json:"total"`
}

type AddCommentRequest struct {
TaskID int64 `path:"task_id" validate:"required" example:"42"`
Body string `json:"body" validate:"required" example:"Checked the logs, this is a regression from #1337"`
}
Generated OpenAPI document (docs/tasks.yaml)
openapi: 3.1.0
info:
title: Task Manager API
version: 1.0.0
paths:
/api/v1/auth/login:
post:
operationId: authLogin
summary: Log in
description: Returns a JWT for a username and password.
tags:
- auth
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/auth/refresh:
post:
operationId: authRefresh
summary: Refresh token
tags:
- auth
security:
- bearer: []
parameters:
- name: Authorization
in: header
description: Bearer <token>
required: true
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/tasks:
get:
operationId: taskList
summary: List tasks
description: Supports filtering by status and priority, and pagination.
tags:
- tasks
parameters:
- name: status
in: query
description: todo | in_progress | done
required: false
schema:
type: string
example: todo
- name: priority
in: query
description: 1-3
required: false
schema:
type: integer
format: int32
- name: page
in: query
required: false
schema:
type: integer
format: int32
default: 1
example: 1
- name: page_size
in: query
required: false
schema:
type: integer
format: int32
default: 20
example: 20
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ListTasksResponse'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
operationId: taskCreate
summary: Create task
tags:
- tasks
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTaskRequest'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/TaskDTO'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"422":
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/tasks/{id}:
get:
operationId: taskGet
summary: Get task by ID
tags:
- tasks
parameters:
- name: id
in: path
required: true
schema:
type: integer
format: int64
example: 42
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/TaskDTO'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
put:
operationId: taskUpdate
summary: Update task
tags:
- tasks
parameters:
- name: id
in: path
required: true
schema:
type: integer
format: int64
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateTaskRequest'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/TaskDTO'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"403":
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"422":
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
operationId: taskDelete
summary: Delete task
description: Only the task creator or an administrator.
tags:
- tasks
parameters:
- name: id
in: path
required: true
schema:
type: integer
format: int64
example: 42
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteTaskResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"403":
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/tasks/{task_id}/comments:
get:
operationId: commentList
summary: List task comments
tags:
- comments
parameters:
- name: task_id
in: path
required: true
schema:
type: integer
format: int64
example: 42
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ListCommentsResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
operationId: commentAdd
summary: Add comment
tags:
- comments
parameters:
- name: task_id
in: path
required: true
schema:
type: integer
format: int64
example: 42
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddCommentRequest'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/CommentDTO'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- bearer: []
components:
schemas:
AddCommentRequest:
type: object
properties:
body:
type: string
example: 'Checked the logs, this is a regression from #1337'
required:
- body
CommentDTO:
type: object
properties:
author:
$ref: '#/components/schemas/UserBrief'
body:
type: string
created_at:
type: string
format: date-time
id:
type: integer
format: int64
task_id:
type: integer
format: int64
CreateTaskRequest:
type: object
properties:
assignee_id:
type: integer
format: int64
description:
type: string
example: OOM killer terminated the service around 03:00
priority:
type: integer
format: int32
description: 1-3
example: 3
title:
type: string
example: Production is down
required:
- title
DeleteTaskResponse:
type: object
properties:
id:
type: integer
format: int64
success:
type: boolean
ErrorResponse:
type: object
properties:
error:
type: string
description: Human-readable error message
required:
- error
ListCommentsResponse:
type: object
properties:
comments:
type: array
items:
$ref: '#/components/schemas/CommentDTO'
total:
type: integer
format: int32
ListTasksResponse:
type: object
properties:
page:
type: integer
format: int32
page_size:
type: integer
format: int32
tasks:
type: array
items:
$ref: '#/components/schemas/TaskDTO'
total:
type: integer
format: int32
LoginRequest:
type: object
properties:
password:
type: string
example: s3cret
username:
type: string
example: larry
required:
- username
- password
LoginResponse:
type: object
properties:
expires_in:
type: integer
format: int32
example: 3600
token:
type: string
TaskDTO:
type: object
properties:
assigned_to:
anyOf:
- $ref: '#/components/schemas/UserBrief'
- type: "null"
created_at:
type: string
format: date-time
description:
type: string
id:
type: integer
format: int64
priority:
type: integer
format: int32
description: 1 = low, 3 = high
status:
type: string
description: todo | in_progress | done
title:
type: string
updated_at:
type: string
format: date-time
UpdateTaskRequest:
type: object
properties:
assignee_id:
type: integer
format: int64
description:
type: string
priority:
type: integer
format: int32
status:
type: string
example: in_progress
title:
type: string
UserBrief:
type: object
properties:
id:
type: integer
format: int64
username:
type: string
securitySchemes:
bearer:
type: http
scheme: bearer
bearerFormat: JWT
description: 'JWT Bearer token, pass as: Authorization: Bearer <token>'

gin

The same API, served with gin. Because func(c *gin.Context) carries no type information, the request and response types are declared with the request: and response: annotation keys. The generated document is the same shape as the net/http one (only the operationIds differ).

cd testdata/gin && apiary -security bearer -title "Task Manager API (gin)" -version "1.0.0" -out ../../docs/tasks_gin.yaml .

Handlers (testdata/gin/handlers.go):

// Package gin is the same task-manager example, but with gin handlers.
//
// It is a separate nested module (its own go.mod) so the real gin dependency
// stays out of the main apiary module. Generate the spec with:
//
// cd testdata/gin && apiary -security bearer -title "Task Manager API (gin)" -version "1.0.0" -out ../../docs/tasks_gin.yaml .
package gin

import "github.com/gin-gonic/gin"

// apiary:operation POST /api/v1/auth/login
// summary: Log in
// description: Returns a JWT for a username and password.
// tags: auth
// security: none
// request: LoginRequest
// response: LoginResponse
// errors: 400,401,500
func Login(c *gin.Context) {}

// apiary:operation POST /api/v1/auth/refresh
// summary: Refresh token
// tags: auth
// security: bearer
// request: RefreshRequest
// response: LoginResponse
// errors: 401,500
func Refresh(c *gin.Context) {}

// apiary:operation GET /api/v1/tasks
// summary: List tasks
// description: Supports filtering by status and priority, and pagination.
// tags: tasks
// request: ListTasksRequest
// response: ListTasksResponse
// errors: 400,401,500
func ListTasks(c *gin.Context) {}

// apiary:operation GET /api/v1/tasks/{id}
// summary: Get task by ID
// tags: tasks
// request: GetTaskRequest
// response: TaskDTO
// errors: 401,404,500
func GetTask(c *gin.Context) {}

// apiary:operation POST /api/v1/tasks
// summary: Create task
// tags: tasks
// request: CreateTaskRequest
// response: TaskDTO
// errors: 400,401,422,500
func CreateTask(c *gin.Context) {}

// apiary:operation PUT /api/v1/tasks/{id}
// summary: Update task
// tags: tasks
// request: UpdateTaskRequest
// response: TaskDTO
// errors: 400,401,403,404,422,500
func UpdateTask(c *gin.Context) {}

// apiary:operation DELETE /api/v1/tasks/{id}
// summary: Delete task
// description: Only the task creator or an administrator.
// tags: tasks
// request: DeleteTaskRequest
// response: DeleteTaskResponse
// errors: 401,403,404,500
func DeleteTask(c *gin.Context) {}

// apiary:operation GET /api/v1/tasks/{task_id}/comments
// summary: List task comments
// tags: comments
// request: ListCommentsRequest
// response: ListCommentsResponse
// errors: 401,404,500
func ListComments(c *gin.Context) {}

// apiary:operation POST /api/v1/tasks/{task_id}/comments
// summary: Add comment
// tags: comments
// request: AddCommentRequest
// response: CommentDTO
// errors: 400,401,404,500
func AddComment(c *gin.Context) {}

Types (testdata/gin/types.go):

package gin

import "time"

type TaskDTO struct {
ID int64 `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Status string `json:"status" doc:"todo | in_progress | done"`
Priority int `json:"priority" doc:"1 = low, 3 = high"`
AssignedTo *UserBrief `json:"assigned_to"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

type UserBrief struct {
ID int64 `json:"id"`
Username string `json:"username"`
}

type CommentDTO struct {
ID int64 `json:"id"`
TaskID int64 `json:"task_id"`
Author UserBrief `json:"author"`
Body string `json:"body"`
CreatedAt time.Time `json:"created_at"`
}

type LoginRequest struct {
Username string `json:"username" validate:"required" example:"larry"`
Password string `json:"password" validate:"required" example:"s3cret"`
}

type RefreshRequest struct {
Token string `header:"Authorization" validate:"required" doc:"Bearer <token>"`
}

type LoginResponse struct {
Token string `json:"token"`
ExpiresIn int `json:"expires_in" example:"3600"`
}

type ListTasksRequest struct {
Status string `query:"status" doc:"todo | in_progress | done" example:"todo"`
Priority int `query:"priority" doc:"1-3"`
Page int `query:"page" default:"1" example:"1"`
PageSize int `query:"page_size" default:"20" example:"20"`
}

type ListTasksResponse struct {
Tasks []TaskDTO `json:"tasks"`
Total int `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}

type GetTaskRequest struct {
ID int64 `path:"id" validate:"required" example:"42"`
}

type CreateTaskRequest struct {
Title string `json:"title" validate:"required" example:"Production is down"`
Description string `json:"description" example:"Kafka is acting up"`
Priority int `json:"priority" doc:"1-3" example:"3"`
AssigneeID int64 `json:"assignee_id"`
}

type UpdateTaskRequest struct {
ID int64 `path:"id" validate:"required"`
Title string `json:"title"`
Description string `json:"description"`
Status string `json:"status" example:"in_progress"`
Priority int `json:"priority"`
AssigneeID int64 `json:"assignee_id"`
}

type DeleteTaskRequest struct {
ID int64 `path:"id" validate:"required" example:"42"`
}

type DeleteTaskResponse struct {
ID int64 `json:"id"`
Success bool `json:"success"`
}

type ListCommentsRequest struct {
TaskID int64 `path:"task_id" validate:"required" example:"42"`
}

type ListCommentsResponse struct {
Comments []CommentDTO `json:"comments"`
Total int `json:"total"`
}

type AddCommentRequest struct {
TaskID int64 `path:"task_id" validate:"required" example:"42"`
Body string `json:"body" validate:"required" example:"Checked the logs, this is a regression from #1337"`
}
Generated OpenAPI document (docs/tasks_gin.yaml)
openapi: 3.1.0
info:
title: Task Manager API (gin)
version: 1.0.0
paths:
/api/v1/auth/login:
post:
operationId: login
summary: Log in
description: Returns a JWT for a username and password.
tags:
- auth
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/auth/refresh:
post:
operationId: refresh
summary: Refresh token
tags:
- auth
security:
- bearer: []
parameters:
- name: Authorization
in: header
description: Bearer <token>
required: true
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/tasks:
get:
operationId: listTasks
summary: List tasks
description: Supports filtering by status and priority, and pagination.
tags:
- tasks
parameters:
- name: status
in: query
description: todo | in_progress | done
required: false
schema:
type: string
example: todo
- name: priority
in: query
description: 1-3
required: false
schema:
type: integer
format: int32
- name: page
in: query
required: false
schema:
type: integer
format: int32
default: 1
example: 1
- name: page_size
in: query
required: false
schema:
type: integer
format: int32
default: 20
example: 20
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ListTasksResponse'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
operationId: createTask
summary: Create task
tags:
- tasks
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTaskRequest'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/TaskDTO'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"422":
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/tasks/{id}:
get:
operationId: getTask
summary: Get task by ID
tags:
- tasks
parameters:
- name: id
in: path
required: true
schema:
type: integer
format: int64
example: 42
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/TaskDTO'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
put:
operationId: updateTask
summary: Update task
tags:
- tasks
parameters:
- name: id
in: path
required: true
schema:
type: integer
format: int64
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateTaskRequest'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/TaskDTO'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"403":
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"422":
description: Unprocessable Entity
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
operationId: deleteTask
summary: Delete task
description: Only the task creator or an administrator.
tags:
- tasks
parameters:
- name: id
in: path
required: true
schema:
type: integer
format: int64
example: 42
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteTaskResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"403":
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/v1/tasks/{task_id}/comments:
get:
operationId: listComments
summary: List task comments
tags:
- comments
parameters:
- name: task_id
in: path
required: true
schema:
type: integer
format: int64
example: 42
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ListCommentsResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
operationId: addComment
summary: Add comment
tags:
- comments
parameters:
- name: task_id
in: path
required: true
schema:
type: integer
format: int64
example: 42
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AddCommentRequest'
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/CommentDTO'
"400":
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"401":
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"404":
description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
"500":
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- bearer: []
components:
schemas:
AddCommentRequest:
type: object
properties:
body:
type: string
example: 'Checked the logs, this is a regression from #1337'
required:
- body
CommentDTO:
type: object
properties:
author:
$ref: '#/components/schemas/UserBrief'
body:
type: string
created_at:
type: string
format: date-time
id:
type: integer
format: int64
task_id:
type: integer
format: int64
CreateTaskRequest:
type: object
properties:
assignee_id:
type: integer
format: int64
description:
type: string
example: Kafka is acting up
priority:
type: integer
format: int32
description: 1-3
example: 3
title:
type: string
example: Production is down
required:
- title
DeleteTaskResponse:
type: object
properties:
id:
type: integer
format: int64
success:
type: boolean
ErrorResponse:
type: object
properties:
error:
type: string
description: Human-readable error message
required:
- error
ListCommentsResponse:
type: object
properties:
comments:
type: array
items:
$ref: '#/components/schemas/CommentDTO'
total:
type: integer
format: int32
ListTasksResponse:
type: object
properties:
page:
type: integer
format: int32
page_size:
type: integer
format: int32
tasks:
type: array
items:
$ref: '#/components/schemas/TaskDTO'
total:
type: integer
format: int32
LoginRequest:
type: object
properties:
password:
type: string
example: s3cret
username:
type: string
example: larry
required:
- username
- password
LoginResponse:
type: object
properties:
expires_in:
type: integer
format: int32
example: 3600
token:
type: string
TaskDTO:
type: object
properties:
assigned_to:
anyOf:
- $ref: '#/components/schemas/UserBrief'
- type: "null"
created_at:
type: string
format: date-time
description:
type: string
id:
type: integer
format: int64
priority:
type: integer
format: int32
description: 1 = low, 3 = high
status:
type: string
description: todo | in_progress | done
title:
type: string
updated_at:
type: string
format: date-time
UpdateTaskRequest:
type: object
properties:
assignee_id:
type: integer
format: int64
description:
type: string
priority:
type: integer
format: int32
status:
type: string
example: in_progress
title:
type: string
UserBrief:
type: object
properties:
id:
type: integer
format: int64
username:
type: string
securitySchemes:
bearer:
type: http
scheme: bearer
bearerFormat: JWT
description: 'JWT Bearer token, pass as: Authorization: Bearer <token>'