Yimaru-BackEnd/docs/swagger.yaml
Yared Yemane 90baa582be fix: load sub-module lesson by ID regardless of active flag
Course-management GET/PUT used GetSubModuleLessonByID with is_active=TRUE,
which returned no row for inactive lessons. Align with other ByID lookups
and allow admins to view and edit inactive lessons.

Made-with: Cursor
2026-04-20 00:48:13 -07:00

7997 lines
202 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

definitions:
domain.AgeGroup:
enum:
- UNDER_13
- "13_17"
- "18_24"
- "25_34"
- "35_44"
- "45_54"
- 55_PLUS
type: string
x-enum-varnames:
- AgeUnder13
- Age13To17
- Age18To24
- Age25To34
- Age35To44
- Age45To54
- Age55Plus
domain.CreateRoleReq:
properties:
description:
type: string
name:
maxLength: 100
minLength: 2
type: string
required:
- name
type: object
domain.CreateTeamMemberReq:
properties:
bio:
type: string
department:
type: string
email:
type: string
emergency_contact:
type: string
employment_type:
type: string
first_name:
type: string
hire_date:
description: YYYY-MM-DD
type: string
job_title:
type: string
last_name:
type: string
password:
minLength: 8
type: string
permissions:
items:
type: string
type: array
phone_number:
type: string
profile_picture_url:
type: string
team_role:
type: string
work_phone:
type: string
required:
- email
- first_name
- last_name
- password
- team_role
type: object
domain.EmploymentType:
enum:
- full_time
- part_time
- contract
- intern
type: string
x-enum-varnames:
- EmploymentTypeFullTime
- EmploymentTypePartTime
- EmploymentTypeContract
- EmploymentTypeIntern
domain.ErrorResponse:
properties:
error:
type: string
message:
type: string
type: object
domain.LogEntry:
properties:
caller:
type: string
env:
type: string
fields:
additionalProperties: true
type: object
level:
type: string
message:
type: string
service:
type: string
stacktrace:
type: string
timestamp:
type: string
type: object
domain.LogResponse:
properties:
data:
items:
$ref: '#/definitions/domain.LogEntry'
type: array
message:
type: string
pagination:
$ref: '#/definitions/domain.Pagination'
type: object
domain.LoginRequest:
properties:
email:
type: string
otp_code:
type: string
password:
type: string
phone_number:
type: string
type: object
domain.OtpMedium:
enum:
- email
- sms
type: string
x-enum-varnames:
- OtpMediumEmail
- OtpMediumSms
domain.Pagination:
properties:
current_page:
type: integer
limit:
type: integer
total:
type: integer
total_pages:
type: integer
type: object
domain.Permission:
properties:
created_at:
type: string
description:
type: string
group_name:
type: string
id:
type: integer
key:
type: string
name:
type: string
type: object
domain.QuestionAudioAnswer:
properties:
correctAnswerText:
type: string
createdAt:
type: string
id:
format: int64
type: integer
questionID:
format: int64
type: integer
type: object
domain.QuestionOption:
properties:
createdAt:
type: string
id:
format: int64
type: integer
isCorrect:
type: boolean
optionOrder:
format: int32
type: integer
optionText:
type: string
questionID:
format: int64
type: integer
type: object
domain.QuestionShortAnswer:
properties:
acceptableAnswer:
type: string
createdAt:
type: string
id:
format: int64
type: integer
matchType:
type: string
questionID:
format: int64
type: integer
type: object
domain.QuestionWithDetails:
properties:
audioAnswer:
$ref: '#/definitions/domain.QuestionAudioAnswer'
createdAt:
type: string
difficultyLevel:
type: string
explanation:
type: string
id:
format: int64
type: integer
imageURL:
type: string
options:
items:
$ref: '#/definitions/domain.QuestionOption'
type: array
points:
format: int32
type: integer
questionText:
type: string
questionType:
type: string
sampleAnswerVoicePrompt:
type: string
shortAnswers:
items:
$ref: '#/definitions/domain.QuestionShortAnswer'
type: array
status:
type: string
tips:
type: string
updatedAt:
type: string
voicePrompt:
type: string
type: object
domain.RegisterUserReq:
properties:
email:
type: string
otp_medium:
$ref: '#/definitions/domain.OtpMedium'
password:
type: string
phone_number:
type: string
role:
type: string
type: object
domain.ResendOtpReq:
properties:
email:
type: string
phone_number:
type: string
type: object
domain.Response:
properties:
data: {}
message:
type: string
metadata: {}
status_code:
type: integer
success:
type: boolean
type: object
domain.Role:
enum:
- SUPER_ADMIN
- ADMIN
- STUDENT
- INSTRUCTOR
- SUPPORT
type: string
x-enum-varnames:
- RoleSuperAdmin
- RoleAdmin
- RoleStudent
- RoleInstructor
- RoleSupport
domain.RoleRecord:
properties:
created_at:
type: string
description:
type: string
id:
type: integer
is_system:
type: boolean
name:
type: string
updated_at:
type: string
type: object
domain.RoleWithPermissions:
properties:
created_at:
type: string
description:
type: string
id:
type: integer
is_system:
type: boolean
name:
type: string
permissions:
items:
$ref: '#/definitions/domain.Permission'
type: array
updated_at:
type: string
type: object
domain.SetRolePermissionsReq:
properties:
permission_ids:
items:
type: integer
type: array
required:
- permission_ids
type: object
domain.TeamMemberLoginReq:
properties:
email:
type: string
password:
type: string
required:
- email
- password
type: object
domain.TeamMemberResponse:
properties:
bio:
type: string
created_at:
type: string
department:
type: string
email:
type: string
email_verified:
type: boolean
employment_type:
$ref: '#/definitions/domain.EmploymentType'
first_name:
type: string
hire_date:
type: string
id:
type: integer
job_title:
type: string
last_login:
type: string
last_name:
type: string
permissions:
items:
type: string
type: array
phone_number:
type: string
profile_picture_url:
type: string
status:
$ref: '#/definitions/domain.TeamMemberStatus'
team_role:
$ref: '#/definitions/domain.TeamRole'
updated_at:
type: string
work_phone:
type: string
type: object
domain.TeamMemberStats:
properties:
active_count:
type: integer
inactive_count:
type: integer
suspended_count:
type: integer
terminated_count:
type: integer
total_count:
type: integer
type: object
domain.TeamMemberStatus:
enum:
- active
- inactive
- suspended
- terminated
type: string
x-enum-varnames:
- TeamMemberStatusActive
- TeamMemberStatusInactive
- TeamMemberStatusSuspended
- TeamMemberStatusTerminated
domain.TeamRole:
enum:
- SUPER_ADMIN
- ADMIN
- CONTENT_MANAGER
- SUPPORT_AGENT
- INSTRUCTOR
- FINANCE
- HR
- ANALYST
type: string
x-enum-varnames:
- TeamRoleSuperAdmin
- TeamRoleAdmin
- TeamRoleContentManager
- TeamRoleSupportAgent
- TeamRoleInstructor
- TeamRoleFinance
- TeamRoleHR
- TeamRoleAnalyst
domain.UpdateKnowledgeLevelReq:
properties:
knowledge_level:
description: BEGINNER, INTERMEDIATE, ADVANCED
type: string
user_id:
type: integer
type: object
domain.UpdateRoleReq:
properties:
description:
type: string
name:
maxLength: 100
minLength: 2
type: string
required:
- name
type: object
domain.UpdateTeamMemberReq:
properties:
bio:
type: string
department:
type: string
emergency_contact:
type: string
employment_type:
type: string
first_name:
type: string
hire_date:
type: string
job_title:
type: string
last_name:
type: string
permissions:
items:
type: string
type: array
phone_number:
type: string
profile_picture_url:
type: string
team_role:
type: string
work_phone:
type: string
type: object
domain.UpdateTeamMemberStatusReq:
properties:
status:
type: string
required:
- status
type: object
domain.UpdateUserReq:
properties:
age_group:
$ref: '#/definitions/domain.AgeGroup'
birth_day:
description: YYYY-MM-DD
type: string
country:
type: string
education_level:
type: string
favourite_topic:
type: string
first_name:
type: string
gender:
type: string
initial_assessment_completed:
type: boolean
knowledge_level:
type: string
language_challange:
type: string
language_goal:
type: string
last_name:
type: string
learning_goal:
type: string
nick_name:
type: string
occupation:
type: string
preferred_language:
type: string
profile_picture_url:
type: string
region:
type: string
type: object
domain.UserProfileResponse:
properties:
age_group:
type: string
birth_day:
description: formatted as YYYY-MM-DD
type: string
country:
type: string
created_at:
type: string
education_level:
type: string
email:
description: UserName string `json:"user_name,omitempty"`
type: string
email_verified:
type: boolean
favoutite_topic:
type: string
first_name:
type: string
gender:
type: string
id:
type: integer
initial_assessment_completed:
description: Profile fields
type: boolean
language_challange:
type: string
language_goal:
type: string
last_login:
type: string
last_name:
type: string
learning_goal:
type: string
nick_name:
type: string
occupation:
type: string
phone_number:
type: string
phone_verified:
type: boolean
preferred_language:
type: string
profile_completed:
type: boolean
profile_completion_percentage:
type: integer
profile_picture_url:
type: string
region:
type: string
role:
$ref: '#/definitions/domain.Role'
status:
$ref: '#/definitions/domain.UserStatus'
updated_at:
type: string
type: object
domain.UserStatus:
enum:
- PENDING
- ACTIVE
- SUSPENDED
- DEACTIVATED
type: string
x-enum-varnames:
- UserStatusPending
- UserStatusActive
- UserStatusSuspended
- UserStatusDeactivated
domain.UserSummary:
properties:
active_users:
type: integer
joined_this_month:
type: integer
total_users:
type: integer
type: object
domain.VerifyOtpReq:
properties:
email:
type: string
otp:
type: string
phone_number:
type: string
required:
- otp
type: object
domain.WebhookRequest:
properties:
nonce:
type: string
notificationUrl:
type: string
paymentMethod:
type: string
phone:
type: string
sessionId:
type: string
totalAmount:
type: integer
transaction:
properties:
transactionId:
type: string
transactionStatus:
type: string
type: object
transactionStatus:
type: string
uuid:
type: string
type: object
handlers.AdminProfileRes:
properties:
created_at:
type: string
email:
type: string
email_verified:
type: boolean
first_name:
type: string
id:
type: integer
last_login:
type: string
last_name:
type: string
phone_number:
type: string
phone_verified:
type: boolean
role:
$ref: '#/definitions/domain.Role'
suspended:
type: boolean
suspended_at:
type: string
updated_at:
type: string
type: object
handlers.AdminRes:
properties:
created_at:
type: string
email:
type: string
email_verified:
type: boolean
first_name:
type: string
id:
type: integer
last_login:
type: string
last_name:
type: string
phone_number:
type: string
phone_verified:
type: boolean
role:
$ref: '#/definitions/domain.Role'
suspended:
type: boolean
suspended_at:
type: string
updated_at:
type: string
type: object
handlers.CheckPhoneEmailExistReq:
properties:
email:
example: john.doe@example.com
type: string
phone_number:
example: "1234567890"
type: string
type: object
handlers.CheckPhoneEmailExistRes:
properties:
email_exist:
type: boolean
phone_number_exist:
type: boolean
type: object
handlers.CreateAdminReq:
properties:
email:
example: john.doe@example.com
type: string
first_name:
example: John
type: string
last_name:
example: Doe
type: string
password:
example: password123
type: string
phone_number:
example: "1234567890"
type: string
type: object
handlers.CreatePullUploadRequest:
properties:
description:
type: string
file_size:
type: integer
name:
type: string
source_url:
type: string
required:
- file_size
- name
- source_url
type: object
handlers.CreateTusUploadRequest:
properties:
description:
type: string
file_size:
type: integer
name:
type: string
required:
- file_size
- name
type: object
handlers.LoginAdminRes:
properties:
access_token:
type: string
refresh_token:
type: string
role:
type: string
type: object
handlers.RegisterCodeReq:
properties:
email:
example: john.doe@example.com
type: string
phone_number:
example: "1234567890"
type: string
type: object
handlers.ResetCodeReq:
properties:
email:
example: john.doe@example.com
type: string
phone_number:
example: "1234567890"
type: string
type: object
handlers.ResetPasswordReq:
properties:
email:
example: john.doe@example.com
type: string
otp:
example: "123456"
type: string
password:
example: newpassword123
minLength: 8
type: string
phone_number:
example: "1234567890"
type: string
required:
- otp
- password
type: object
handlers.SearchUserByNameOrPhoneReq:
properties:
query:
type: string
role:
$ref: '#/definitions/domain.Role'
type: object
handlers.SendSingleAfroSMSReq:
properties:
message:
example: Hello world
type: string
recipient:
example: "+251912345678"
type: string
required:
- message
- recipient
type: object
handlers.VimeoEmbedResponse:
properties:
embed_html:
type: string
embed_url:
type: string
video_id:
type: string
type: object
handlers.VimeoUploadResponse:
properties:
link:
type: string
status:
type: string
upload_link:
type: string
uri:
type: string
vimeo_id:
type: string
type: object
handlers.VimeoVideoResponse:
properties:
description:
type: string
duration:
type: integer
embed_html:
type: string
embed_url:
type: string
height:
type: integer
link:
type: string
name:
type: string
status:
type: string
thumbnail_url:
type: string
transcode_status:
type: string
uri:
type: string
vimeo_id:
type: string
width:
type: integer
type: object
handlers.addQuestionToSetReq:
properties:
display_order:
type: integer
question_id:
type: integer
required:
- question_id
type: object
handlers.addUserPersonaReq:
properties:
display_order:
type: integer
user_id:
type: integer
required:
- user_id
type: object
handlers.autoRenewReq:
properties:
auto_renew:
type: boolean
type: object
handlers.capstoneQuestionItem:
properties:
display_order:
type: integer
question_id:
type: integer
type: object
handlers.changePasswordReq:
properties:
current_password:
example: oldpassword123
type: string
new_password:
example: newpassword123
minLength: 8
type: string
required:
- current_password
- new_password
type: object
handlers.clearCourseManagementReq:
properties:
confirm:
type: string
type: object
handlers.createCourseCategoryReq:
properties:
is_active:
type: boolean
name:
type: string
type: object
handlers.createCourseReq:
properties:
category_id:
type: integer
description:
type: string
intro_video_url:
type: string
is_active:
type: boolean
sub_category_id:
type: integer
thumbnail:
type: string
title:
type: string
type: object
handlers.createCourseSubCategoryReq:
properties:
category_id:
type: integer
description:
type: string
display_order:
type: integer
is_active:
type: boolean
name:
type: string
type: object
handlers.createIssueReq:
properties:
description:
type: string
issue_type:
type: string
metadata:
additionalProperties: true
type: object
subject:
type: string
required:
- description
- issue_type
- subject
type: object
handlers.createLevelReq:
properties:
cefr_level:
type: string
course_id:
type: integer
description:
type: string
display_order:
type: integer
is_active:
type: boolean
thumbnail:
type: string
title:
type: string
type: object
handlers.createModuleCapstoneReq:
properties:
description:
type: string
display_order:
type: integer
is_active:
type: boolean
module_id:
type: integer
passing_score:
type: integer
questions:
items:
$ref: '#/definitions/handlers.capstoneQuestionItem'
type: array
shuffle_questions:
type: boolean
status:
type: string
thumbnail:
type: string
time_limit_minutes:
type: integer
tips:
type: string
title:
type: string
type: object
handlers.createModuleReq:
properties:
description:
type: string
display_order:
type: integer
icon_url:
type: string
is_active:
type: boolean
level_id:
type: integer
title:
type: string
type: object
handlers.createPlanReq:
properties:
currency:
type: string
description:
type: string
duration_unit:
enum:
- DAY
- WEEK
- MONTH
- YEAR
type: string
duration_value:
minimum: 1
type: integer
is_active:
type: boolean
name:
type: string
price:
minimum: 0
type: number
required:
- currency
- duration_unit
- duration_value
- name
- price
type: object
handlers.createQuestionReq:
properties:
audio_correct_answer_text:
type: string
difficulty_level:
type: string
explanation:
type: string
image_url:
type: string
options:
items:
$ref: '#/definitions/handlers.optionInput'
type: array
points:
type: integer
question_text:
type: string
question_type:
enum:
- MCQ
- TRUE_FALSE
- SHORT_ANSWER
- AUDIO
type: string
sample_answer_voice_prompt:
type: string
short_answers:
items:
$ref: '#/definitions/handlers.shortAnswerInput'
type: array
status:
type: string
tips:
type: string
voice_prompt:
type: string
required:
- question_text
- question_type
type: object
handlers.createQuestionSetReq:
properties:
banner_image:
type: string
description:
type: string
intro_video_url:
type: string
owner_id:
type: integer
owner_type:
type: string
passing_score:
type: integer
persona:
type: string
set_type:
enum:
- PRACTICE
- INITIAL_ASSESSMENT
- QUIZ
- EXAM
- SURVEY
- CAPSTONE
type: string
shuffle_questions:
type: boolean
status:
type: string
sub_course_video_id:
type: integer
time_limit_minutes:
type: integer
title:
type: string
required:
- set_type
- title
type: object
handlers.createSubModuleCapstoneReq:
properties:
description:
type: string
display_order:
type: integer
is_active:
type: boolean
passing_score:
type: integer
questions:
items:
$ref: '#/definitions/handlers.capstoneQuestionItem'
type: array
shuffle_questions:
type: boolean
status:
type: string
sub_module_id:
type: integer
thumbnail:
type: string
time_limit_minutes:
type: integer
tips:
type: string
title:
type: string
type: object
handlers.createSubModuleLessonReq:
properties:
description:
type: string
display_order:
type: integer
is_active:
type: boolean
sub_module_id:
type: integer
teaching_audio_url:
type: string
teaching_image_url:
type: string
teaching_text:
type: string
teaching_video_url:
type: string
thumbnail:
type: string
title:
type: string
type: object
handlers.createSubModulePracticeReq:
properties:
description:
type: string
display_order:
type: integer
intro_video_url:
type: string
is_active:
type: boolean
question_set_id:
type: integer
sub_module_id:
type: integer
thumbnail:
type: string
title:
type: string
type: object
handlers.createSubModuleReq:
properties:
description:
type: string
display_order:
type: integer
is_active:
type: boolean
module_id:
type: integer
thumbnail:
type: string
tips:
type: string
title:
type: string
type: object
handlers.createSubModuleVideoReq:
properties:
description:
type: string
display_order:
type: integer
duration:
type: integer
instructor_id:
type: string
resolution:
type: string
status:
type: string
sub_module_id:
type: integer
thumbnail:
type: string
title:
type: string
video_url:
type: string
visibility:
type: string
type: object
handlers.initiateDirectPaymentReq:
properties:
email:
type: string
payment_method:
type: string
phone:
type: string
plan_id:
type: integer
required:
- email
- payment_method
- phone
- plan_id
type: object
handlers.initiatePaymentReq:
properties:
email:
type: string
phone:
type: string
plan_id:
type: integer
required:
- email
- phone
- plan_id
type: object
handlers.issueListRes:
properties:
issues:
items:
$ref: '#/definitions/handlers.issueRes'
type: array
total_count:
type: integer
type: object
handlers.issueRes:
properties:
created_at:
type: string
description:
type: string
id:
type: integer
issue_type:
type: string
metadata:
additionalProperties: true
type: object
status:
type: string
subject:
type: string
updated_at:
type: string
user_id:
type: integer
user_role:
type: string
type: object
handlers.loginUserRes:
properties:
access_token:
type: string
refresh_token:
type: string
role:
type: string
user_id:
type: integer
type: object
handlers.logoutReq:
properties:
device_token:
example: <fcm-device-token>
type: string
refresh_token:
example: <refresh-token>
type: string
required:
- refresh_token
type: object
handlers.optionInput:
properties:
is_correct:
type: boolean
option_order:
type: integer
option_text:
type: string
required:
- option_text
type: object
handlers.refreshToken:
properties:
access_token:
example: <jwt-token>
type: string
refresh_token:
example: <refresh-token>
type: string
required:
- access_token
- refresh_token
type: object
handlers.resetAndReseedReq:
properties:
confirm:
type: string
type: object
handlers.shortAnswerInput:
properties:
acceptable_answer:
type: string
match_type:
type: string
required:
- acceptable_answer
type: object
handlers.submitRatingReq:
properties:
review:
type: string
stars:
maximum: 5
minimum: 1
type: integer
target_id:
type: integer
target_type:
type: string
required:
- stars
- target_type
type: object
handlers.subscribeReq:
properties:
payment_method:
type: string
payment_reference:
type: string
plan_id:
type: integer
required:
- plan_id
type: object
handlers.subscribeWithPaymentReq:
properties:
email:
type: string
phone:
type: string
plan_id:
type: integer
required:
- email
- phone
- plan_id
type: object
handlers.teamMemberLoginRes:
properties:
access_token:
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
type: string
member_id:
example: 1
type: integer
refresh_token:
example: <opaque-refresh-token>
type: string
team_role:
example: admin
type: string
type: object
handlers.teamMemberRefreshReq:
properties:
refresh_token:
type: string
required:
- refresh_token
type: object
handlers.updateAdminReq:
properties:
first_name:
example: John
type: string
last_name:
example: Doe
type: string
suspended:
example: false
type: boolean
type: object
handlers.updateCourseReq:
properties:
description:
type: string
intro_video_url:
type: string
is_active:
type: boolean
thumbnail:
type: string
title:
type: string
type: object
handlers.updateCourseThumbnailReq:
properties:
thumbnail_url:
type: string
type: object
handlers.updateIssueStatusReq:
properties:
status:
enum:
- pending
- in_progress
- resolved
- rejected
type: string
required:
- status
type: object
handlers.updateLevelReq:
properties:
description:
type: string
display_order:
type: integer
is_active:
type: boolean
thumbnail:
type: string
title:
type: string
type: object
handlers.updateModuleCapstoneReq:
properties:
description:
type: string
display_order:
type: integer
is_active:
type: boolean
passing_score:
type: integer
questions:
items:
$ref: '#/definitions/handlers.capstoneQuestionItem'
type: array
shuffle_questions:
type: boolean
status:
type: string
thumbnail:
type: string
time_limit_minutes:
type: integer
tips:
type: string
title:
type: string
type: object
handlers.updateModuleReq:
properties:
description:
type: string
display_order:
type: integer
icon_url:
type: string
is_active:
type: boolean
title:
type: string
type: object
handlers.updatePlanReq:
properties:
currency:
type: string
description:
type: string
duration_unit:
type: string
duration_value:
type: integer
is_active:
type: boolean
name:
type: string
price:
type: number
type: object
handlers.updateQuestionOrderReq:
properties:
display_order:
type: integer
required:
- display_order
type: object
handlers.updateQuestionReq:
properties:
audio_correct_answer_text:
type: string
difficulty_level:
type: string
explanation:
type: string
image_url:
type: string
options:
items:
$ref: '#/definitions/handlers.optionInput'
type: array
points:
type: integer
question_text:
type: string
question_type:
type: string
sample_answer_voice_prompt:
type: string
short_answers:
items:
$ref: '#/definitions/handlers.shortAnswerInput'
type: array
status:
type: string
tips:
type: string
voice_prompt:
type: string
type: object
handlers.updateQuestionSetReq:
properties:
banner_image:
type: string
description:
type: string
intro_video_url:
type: string
passing_score:
type: integer
persona:
type: string
shuffle_questions:
type: boolean
status:
type: string
sub_course_video_id:
type: integer
time_limit_minutes:
type: integer
title:
type: string
type: object
handlers.updateSubModuleCapstoneReq:
properties:
description:
type: string
display_order:
type: integer
is_active:
type: boolean
passing_score:
type: integer
questions:
items:
$ref: '#/definitions/handlers.capstoneQuestionItem'
type: array
shuffle_questions:
type: boolean
status:
type: string
thumbnail:
type: string
time_limit_minutes:
type: integer
tips:
type: string
title:
type: string
type: object
handlers.updateSubModuleLessonReq:
properties:
description:
type: string
display_order:
type: integer
is_active:
type: boolean
sub_module_id:
type: integer
teaching_audio_url:
type: string
teaching_image_url:
type: string
teaching_text:
type: string
teaching_video_url:
type: string
thumbnail:
type: string
title:
type: string
type: object
handlers.verifyOTPReq:
properties:
otp:
type: string
session_id:
type: string
required:
- otp
- session_id
type: object
response.APIResponse:
properties:
data: {}
message:
type: string
metadata: {}
page:
type: integer
status:
$ref: '#/definitions/response.Status'
timestamp:
type: string
total:
type: integer
type: object
response.Status:
enum:
- error
- success
type: string
x-enum-varnames:
- Error
- Success
vimeo.OEmbedResponse:
properties:
author_name:
type: string
author_url:
type: string
description:
type: string
duration:
type: integer
height:
type: integer
html:
type: string
is_plus:
type: string
provider_name:
type: string
provider_url:
type: string
thumbnail_height:
type: integer
thumbnail_url:
type: string
thumbnail_width:
type: integer
title:
type: string
type:
type: string
version:
type: string
video_id:
type: integer
width:
type: integer
type: object
info:
contact:
email: support@swagger.io
name: API Support
url: http://www.swagger.io/support
description: This is server for Yimaru.
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
termsOfService: http://swagger.io/terms/
title: Yimaru API
version: 1.0.1
paths:
/api/v1/{tenant_slug}/admin-login:
post:
consumes:
- application/json
description: Login user
parameters:
- description: Login admin
in: body
name: login
required: true
schema:
$ref: '#/definitions/domain.LoginRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.LoginAdminRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Login user
tags:
- auth
/api/v1/{tenant_slug}/otp/resend:
post:
consumes:
- application/json
description: Resend OTP if the previous one is expired
parameters:
- description: Resend OTP
in: body
name: resendOtp
required: true
schema:
$ref: '#/definitions/domain.ResendOtpReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Resend OTP
tags:
- otp
/api/v1/{tenant_slug}/user-login:
post:
consumes:
- application/json
description: Login user
parameters:
- description: Login user
in: body
name: login
required: true
schema:
$ref: '#/definitions/domain.LoginRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.loginUserRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Login user
tags:
- auth
/api/v1/{tenant_slug}/user/admin-profile:
get:
consumes:
- application/json
description: Get user profile
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.AdminProfileRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
security:
- Bearer: []
summary: Get user profile
tags:
- user
/api/v1/{tenant_slug}/user/checkPhoneEmailExist:
post:
consumes:
- application/json
description: Check if phone number or email exist
parameters:
- description: Check phone number or email exist
in: body
name: checkPhoneEmailExist
required: true
schema:
$ref: '#/definitions/handlers.CheckPhoneEmailExistReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.CheckPhoneEmailExistRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Check if phone number or email exist
tags:
- user
/api/v1/{tenant_slug}/user/knowledge-level:
put:
consumes:
- application/json
description: Updates the knowledge level of the specified user after initial
assessment
parameters:
- description: User ID
in: path
name: user_id
required: true
type: integer
- description: Knowledge level
in: body
name: knowledge_level
required: true
schema:
$ref: '#/definitions/domain.UpdateKnowledgeLevelReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update user's knowledge level
tags:
- user
/api/v1/{tenant_slug}/user/register:
post:
consumes:
- application/json
description: Register user
parameters:
- description: Register user
in: body
name: registerUser
required: true
schema:
$ref: '#/definitions/domain.RegisterUserReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Register user
tags:
- user
/api/v1/{tenant_slug}/user/resetPassword:
post:
consumes:
- application/json
description: Reset tenant password
parameters:
- description: Reset password
in: body
name: resetPassword
required: true
schema:
$ref: '#/definitions/handlers.ResetPasswordReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Reset tenant password
tags:
- user
/api/v1/{tenant_slug}/user/sendRegisterCode:
post:
consumes:
- application/json
description: Send register code
parameters:
- description: Send register code
in: body
name: registerCode
required: true
schema:
$ref: '#/definitions/handlers.RegisterCodeReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Send register code
tags:
- user
/api/v1/{tenant_slug}/user/sendResetCode:
post:
consumes:
- application/json
description: Send reset code
parameters:
- description: Send reset code
in: body
name: resetCode
required: true
schema:
$ref: '#/definitions/handlers.ResetCodeReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Send reset code
tags:
- user
/api/v1/{tenant_slug}/user/user-profile:
get:
consumes:
- application/json
description: Get user profile
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.UserProfileResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
security:
- Bearer: []
summary: Get user profile
tags:
- user
/api/v1/activity-logs:
get:
description: Returns a filtered, paginated list of activity logs
parameters:
- description: Filter by actor ID
in: query
name: actor_id
type: integer
- description: Filter by action
in: query
name: action
type: string
- description: Filter by resource type
in: query
name: resource_type
type: string
- description: Filter by resource ID
in: query
name: resource_id
type: integer
- description: Filter logs after this RFC3339 timestamp
in: query
name: after
type: string
- description: Filter logs before this RFC3339 timestamp
in: query
name: before
type: string
- default: 20
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get activity logs
tags:
- activity-logs
/api/v1/activity-logs/{id}:
get:
description: Returns a single activity log entry by its ID
parameters:
- description: Activity Log ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get activity log by ID
tags:
- activity-logs
/api/v1/admin:
get:
consumes:
- application/json
description: Get all Admins
parameters:
- description: Page number
in: query
name: page
type: integer
- description: Page size
in: query
name: page_size
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.AdminRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Get all Admins
tags:
- admin
post:
consumes:
- application/json
description: Create Admin
parameters:
- description: Create admin
in: body
name: manger
required: true
schema:
$ref: '#/definitions/handlers.CreateAdminReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Create Admin
tags:
- admin
/api/v1/admin/{id}:
get:
consumes:
- application/json
description: Get a single admin by id
parameters:
- description: User ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.AdminRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Get admin by id
tags:
- admin
put:
consumes:
- application/json
description: Update Admin
parameters:
- description: Update Admin
in: body
name: admin
required: true
schema:
$ref: '#/definitions/handlers.updateAdminReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Update Admin
tags:
- admin
/api/v1/admin/users/deletion-requests:
get:
consumes:
- application/json
description: Returns account deletion requests for admin panel tracking with
filtering and pagination
parameters:
- description: Search in first_name, last_name, email, phone_number
in: query
name: query
type: string
- description: Role filter
in: query
name: role
type: string
- description: User status filter (ACTIVE, PENDING, SUSPENDED, DEACTIVATED)
in: query
name: status
type: string
- description: Deletion state filter (PENDING, DUE, CANCELLED)
in: query
name: state
type: string
- description: Requested before (RFC3339)
in: query
name: requested_before
type: string
- description: Requested after (RFC3339)
in: query
name: requested_after
type: string
- description: Scheduled before (RFC3339)
in: query
name: scheduled_before
type: string
- description: Scheduled after (RFC3339)
in: query
name: scheduled_after
type: string
- description: Page number (default 1)
in: query
name: page
type: integer
- description: Page size (default 10, max 100)
in: query
name: page_size
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: List account deletion requests
tags:
- user
/api/v1/assessment/questions:
get:
description: Returns all active assessment questions from the initial assessment
set
produces:
- application/json
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/domain.QuestionWithDetails'
type: array
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List assessment questions
tags:
- assessment-question
post:
consumes:
- application/json
description: Creates a new assessment question using the unified questions system
parameters:
- description: Create question payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createQuestionReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create assessment question
tags:
- assessment-question
/api/v1/assessment/questions/{id}:
get:
description: Returns a single assessment question with its options or answer
parameters:
- description: Question ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.QuestionWithDetails'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get assessment question by ID
tags:
- assessment-question
/api/v1/auth/google/android:
post:
parameters:
- description: Google ID Token from Android
in: body
name: idToken
required: true
schema:
type: string
responses: {}
summary: Login via Google Android ID Token
tags:
- auth
/api/v1/auth/google/callback:
get:
responses: {}
summary: Google login callback
tags:
- auth
/api/v1/auth/google/login:
get:
responses: {}
summary: Google login redirect
tags:
- auth
/api/v1/auth/logout:
post:
consumes:
- application/json
description: Logout user
parameters:
- description: Logout user
in: body
name: logout
required: true
schema:
$ref: '#/definitions/handlers.logoutReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Logout user
tags:
- auth
/api/v1/auth/refresh:
post:
consumes:
- application/json
description: Refresh token
parameters:
- description: tokens
in: body
name: refresh
required: true
schema:
$ref: '#/definitions/handlers.refreshToken'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.loginUserRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Refresh token
tags:
- auth
/api/v1/course-management/capstones/{capstoneId}:
delete:
description: Deletes the capstone and its backing question set (and question
items)
parameters:
- description: Capstone ID
in: path
name: capstoneId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Delete capstone
tags:
- course-management
get:
description: Returns one capstone with question-set fields and the ordered question
list
parameters:
- description: Capstone ID
in: path
name: capstoneId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get capstone detail
tags:
- course-management
put:
consumes:
- application/json
description: Updates capstone content, question-set assessment settings, and
optionally replaces the question list
parameters:
- description: Capstone ID
in: path
name: capstoneId
required: true
type: integer
- description: Update capstone payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateSubModuleCapstoneReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update capstone
tags:
- course-management
/api/v1/course-management/categories:
get:
description: Legacy-compatible endpoint for listing course categories
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List course categories
tags:
- course-management
post:
consumes:
- application/json
description: Legacy-compatible endpoint for creating a course category
parameters:
- description: Create category payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createCourseCategoryReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create course category
tags:
- course-management
/api/v1/course-management/categories/{categoryId}/courses:
get:
description: Legacy-compatible endpoint that returns courses for one category
parameters:
- description: Category ID
in: path
name: categoryId
required: true
type: integer
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List courses by category
tags:
- course-management
/api/v1/course-management/courses:
get:
description: Returns all courses with pagination
parameters:
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List all courses
tags:
- course-management
post:
consumes:
- application/json
description: Legacy-compatible endpoint for creating a course
parameters:
- description: Create course payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createCourseReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create course
tags:
- course-management
/api/v1/course-management/courses/{courseId}:
delete:
description: Legacy-compatible endpoint for deleting a course
parameters:
- description: Course ID
in: path
name: courseId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Delete course
tags:
- course-management
get:
description: Returns one course by ID
parameters:
- description: Course ID
in: path
name: courseId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get course detail
tags:
- course-management
put:
consumes:
- application/json
description: Legacy-compatible endpoint for updating a course
parameters:
- description: Course ID
in: path
name: courseId
required: true
type: integer
- description: Update course payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateCourseReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update course
tags:
- course-management
/api/v1/course-management/courses/{courseId}/hierarchy:
get:
description: Returns hierarchy nodes for one course including levels/modules/sub-modules
parameters:
- description: Course ID
in: path
name: courseId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get hierarchy for a course
tags:
- course-management
/api/v1/course-management/courses/{courseId}/learning-path:
get:
description: Legacy-compatible endpoint for course learning path
parameters:
- description: Course ID
in: path
name: courseId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get course learning path
tags:
- course-management
/api/v1/course-management/courses/{courseId}/levels:
get:
description: Returns all active levels for one course
parameters:
- description: Course ID
in: path
name: courseId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List levels by course
tags:
- course-management
/api/v1/course-management/courses/{courseId}/thumbnail:
post:
consumes:
- application/json
description: Legacy-compatible endpoint for updating course thumbnail
parameters:
- description: Course ID
in: path
name: courseId
required: true
type: integer
- description: Update course thumbnail payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateCourseThumbnailReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update course thumbnail
tags:
- course-management
/api/v1/course-management/hierarchy:
get:
description: 'Returns full hierarchy: category -> sub-category -> course'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get unified course hierarchy
tags:
- course-management
/api/v1/course-management/human-language/courses:
get:
description: Returns all courses under Human Language category
parameters:
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List Human Language courses
tags:
- course-management
/api/v1/course-management/human-language/sub-categories:
get:
description: Returns active sub-categories under Human Language category
parameters:
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List Human Language sub-categories
tags:
- course-management
/api/v1/course-management/levels:
get:
description: Returns all levels with pagination
parameters:
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List all levels
tags:
- course-management
post:
consumes:
- application/json
description: Creates a level under a course. cefr_level is a short level code
or label (164 characters), unique per course; optional title defaults to
that value; optional description and thumbnail
parameters:
- description: Create level payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createLevelReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create level
tags:
- course-management
/api/v1/course-management/levels/{levelId}:
get:
description: Returns one level by ID
parameters:
- description: Level ID
in: path
name: levelId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get level detail
tags:
- course-management
put:
consumes:
- application/json
description: Updates level title, description, thumbnail, display order, and
active flag
parameters:
- description: Level ID
in: path
name: levelId
required: true
type: integer
- description: Update level payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateLevelReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update level
tags:
- course-management
/api/v1/course-management/levels/{levelId}/modules:
get:
description: Returns all active modules for one level
parameters:
- description: Level ID
in: path
name: levelId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List modules by level
tags:
- course-management
/api/v1/course-management/module-capstones:
post:
consumes:
- application/json
description: Creates a module-level capstone with a new CAPSTONE question set
and ordered questions
parameters:
- description: Create module capstone payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createModuleCapstoneReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create module capstone
tags:
- course-management
/api/v1/course-management/module-capstones/{moduleCapstoneId}:
delete:
description: Deletes the module capstone and its backing question set
parameters:
- description: Module capstone ID
in: path
name: moduleCapstoneId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Delete module capstone
tags:
- course-management
get:
description: Returns one module capstone with question-set fields and the ordered
question list
parameters:
- description: Module capstone ID
in: path
name: moduleCapstoneId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get module capstone detail
tags:
- course-management
put:
consumes:
- application/json
description: Updates module capstone content, question-set assessment settings,
and optionally replaces the question list
parameters:
- description: Module capstone ID
in: path
name: moduleCapstoneId
required: true
type: integer
- description: Update module capstone payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateModuleCapstoneReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update module capstone
tags:
- course-management
/api/v1/course-management/modules:
get:
description: Returns all modules with pagination
parameters:
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List all modules
tags:
- course-management
post:
consumes:
- application/json
description: Creates a module under a level; optional icon_url stores a module
icon image URL
parameters:
- description: Create module payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createModuleReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create module
tags:
- course-management
/api/v1/course-management/modules/{moduleId}:
get:
description: Returns one module by ID
parameters:
- description: Module ID
in: path
name: moduleId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get module detail
tags:
- course-management
put:
consumes:
- application/json
description: Updates module title, description, icon URL, display order, and
active flag
parameters:
- description: Module ID
in: path
name: moduleId
required: true
type: integer
- description: Update module payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateModuleReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update module
tags:
- course-management
/api/v1/course-management/modules/{moduleId}/capstones:
get:
description: Returns active module capstones with question-set settings and
question counts
parameters:
- description: Module ID
in: path
name: moduleId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List capstones under module
tags:
- course-management
/api/v1/course-management/modules/{moduleId}/sub-modules:
get:
description: Returns all active sub-modules for one module
parameters:
- description: Module ID
in: path
name: moduleId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List sub-modules by module
tags:
- course-management
/api/v1/course-management/practices/{practiceId}:
get:
consumes:
- application/json
description: Returns one active practice by practice ID
parameters:
- description: Practice ID
in: path
name: practiceId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get practice detail
tags:
- course-management
/api/v1/course-management/sub-categories:
get:
description: Returns all active course sub-categories
parameters:
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List course sub-categories
tags:
- course-management
post:
consumes:
- application/json
description: Creates a sub-category under a course category
parameters:
- description: Create sub-category payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createCourseSubCategoryReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create course sub-category
tags:
- course-management
/api/v1/course-management/sub-categories/{subCategoryId}/courses:
get:
description: Returns courses for one sub-category
parameters:
- description: Sub-category ID
in: path
name: subCategoryId
required: true
type: integer
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List courses by sub-category
tags:
- course-management
/api/v1/course-management/sub-module-capstones:
post:
consumes:
- application/json
description: Creates a capstone assessment with a new CAPSTONE question set,
metadata, and ordered questions
parameters:
- description: Create capstone payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createSubModuleCapstoneReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create capstone under sub-module
tags:
- course-management
/api/v1/course-management/sub-module-lessons:
post:
consumes:
- application/json
description: Creates a sub-module lesson with teaching content (text, image,
audio, video URLs) and optional thumbnail
parameters:
- description: Create lesson payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createSubModuleLessonReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create lesson under sub-module
tags:
- course-management
/api/v1/course-management/sub-module-lessons/{lessonId}:
get:
consumes:
- application/json
description: Returns one lesson detail by lesson ID (active or inactive)
parameters:
- description: Lesson ID
in: path
name: lessonId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get lesson detail
tags:
- course-management
put:
consumes:
- application/json
description: Updates lesson teaching content, thumbnail, ordering, and active
flag
parameters:
- description: Lesson ID
in: path
name: lessonId
required: true
type: integer
- description: Update lesson payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateSubModuleLessonReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update lesson detail
tags:
- course-management
/api/v1/course-management/sub-module-practices:
post:
consumes:
- application/json
description: Creates a sub-module practice with metadata and linked question
set
parameters:
- description: Create practice payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createSubModulePracticeReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create practice under sub-module
tags:
- course-management
/api/v1/course-management/sub-module-videos:
post:
consumes:
- application/json
description: Creates a video under a sub-module
parameters:
- description: Create sub-module video payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createSubModuleVideoReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create sub-module video
tags:
- course-management
/api/v1/course-management/sub-modules:
get:
description: Returns all sub-modules with pagination
parameters:
- description: Offset
in: query
name: offset
type: integer
- description: Limit
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List all sub-modules
tags:
- course-management
post:
consumes:
- application/json
description: Creates a sub-module under a module; optional thumbnail (image
URL) and tips text
parameters:
- description: Create sub-module payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createSubModuleReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create sub-module
tags:
- course-management
/api/v1/course-management/sub-modules/{subModuleId}:
get:
description: Returns one sub-module by ID
parameters:
- description: Sub-module ID
in: path
name: subModuleId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get sub-module detail
tags:
- course-management
/api/v1/course-management/sub-modules/{subModuleId}/capstones:
get:
description: Returns active capstones for a sub-module with question-set settings
and question counts
parameters:
- description: Sub-module ID
in: path
name: subModuleId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List capstones under sub-module
tags:
- course-management
/api/v1/course-management/sub-modules/{subModuleId}/lessons:
get:
consumes:
- application/json
description: Returns all active lessons for a sub-module (teaching content metadata)
parameters:
- description: Sub-module ID
in: path
name: subModuleId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get lessons under sub-module
tags:
- course-management
/api/v1/course-management/sub-modules/{subModuleId}/practices:
get:
consumes:
- application/json
description: Returns all active practices attached to a sub-module
parameters:
- description: Sub-module ID
in: path
name: subModuleId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get practices under sub-module
tags:
- course-management
/api/v1/files/audio:
post:
consumes:
- multipart/form-data
parameters:
- description: Audio file (mp3, wav, ogg, m4a, aac, webm)
in: formData
name: file
required: true
type: file
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Upload an audio file
tags:
- files
/api/v1/files/upload:
post:
consumes:
- multipart/form-data
parameters:
- description: 'Media type: image|audio|video'
in: formData
name: media_type
required: true
type: string
- description: Media file
in: formData
name: file
required: true
type: file
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Upload media file
tags:
- files
/api/v1/files/url:
get:
parameters:
- description: MinIO object key (e.g. profile_pictures/uuid.jpg)
in: query
name: key
required: true
type: string
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Get presigned URL for a file
tags:
- files
/api/v1/internal/db/clear-course-management:
post:
consumes:
- application/json
description: Truncates course_categories, courses, and sub_courses (same scope
as reset-reseed) without re-inserting seed SQL.
parameters:
- description: Optional token when DB_RESET_RESEED_TOKEN is set
in: header
name: X-Seed-Reset-Token
type: string
- description: Confirmation payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.clearCourseManagementReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Clear course management hierarchy data only
tags:
- internal
/api/v1/internal/db/reset-reseed:
post:
consumes:
- application/json
description: Truncates course_categories, courses, and sub_courses. If seed
SQL contains INSERTs for those tables (e.g. 007_course_management_seed.sql),
they are replayed; otherwise tables are left empty after truncate.
parameters:
- description: Reset token configured in DB_RESET_RESEED_TOKEN
in: header
name: X-Seed-Reset-Token
required: true
type: string
- description: Confirmation payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.resetAndReseedReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Reset and reseed database
tags:
- internal
/api/v1/internal/users/purge-due-deletions:
post:
description: Worker-safe purge for due self-deletion requests
parameters:
- description: Max users to purge in one run (default 100, max 1000)
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
security:
- Bearer: []
summary: Purge due account deletions
tags:
- user
/api/v1/issues:
get:
description: Returns all reported issues with pagination (admin only)
parameters:
- default: 20
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/handlers.issueListRes'
type: object
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get all issues
tags:
- issues
post:
consumes:
- application/json
description: Allows any authenticated user to report an issue they encountered
parameters:
- description: Issue report payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createIssueReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/handlers.issueRes'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Report an issue
tags:
- issues
/api/v1/issues/{id}:
delete:
description: Deletes an issue report (admin only)
parameters:
- description: Issue ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Delete an issue
tags:
- issues
get:
description: Returns a single issue report by its ID (admin only)
parameters:
- description: Issue ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/handlers.issueRes'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get issue by ID
tags:
- issues
/api/v1/issues/{id}/status:
patch:
consumes:
- application/json
description: Updates the status of an issue (admin only)
parameters:
- description: Issue ID
in: path
name: id
required: true
type: integer
- description: Status update payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateIssueStatusReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Update issue status
tags:
- issues
/api/v1/issues/me:
get:
description: Returns paginated issues reported by the authenticated user
parameters:
- default: 20
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/handlers.issueListRes'
type: object
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get my reported issues
tags:
- issues
/api/v1/issues/user/{user_id}:
get:
description: Returns paginated issues reported by a specific user (admin only)
parameters:
- description: User ID
in: path
name: user_id
required: true
type: integer
- default: 20
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/handlers.issueListRes'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get issues for a specific user
tags:
- issues
/api/v1/logs:
get:
description: Fetches application logs from MongoDB with pagination, level filtering,
and search
parameters:
- description: Filter logs by level (debug, info, warn, error, dpanic, panic,
fatal)
in: query
name: level
type: string
- description: Search term to match against message or fields
in: query
name: search
type: string
- default: 1
description: 'Page number for pagination (default: 1)'
in: query
name: page
type: integer
- default: 50
description: 'Number of items per page (default: 50, max: 100)'
in: query
name: limit
type: integer
produces:
- application/json
responses:
"200":
description: Paginated list of application logs
schema:
$ref: '#/definitions/domain.LogResponse'
"400":
description: Invalid request parameters
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal server error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Retrieve application logs with filtering and pagination
tags:
- Logs
/api/v1/notifications/bulk-email:
post:
consumes:
- multipart/form-data
description: Sends an email to specified user IDs, all users of a role, or direct
email addresses with optional image attachment. Optionally schedule for later
with scheduled_at (RFC3339).
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Send bulk email
tags:
- notifications
/api/v1/notifications/bulk-push:
post:
consumes:
- application/json
description: Sends a push notification to specified user IDs or all users matching
a role. Optionally schedule for later with scheduled_at (RFC3339).
parameters:
- description: Bulk push content
in: body
name: body
required: true
schema:
properties:
image:
type: string
message:
type: string
role:
type: string
scheduled_at:
type: string
title:
type: string
user_ids:
items:
format: int64
type: integer
type: array
type: object
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Send bulk push notification
tags:
- notifications
/api/v1/notifications/bulk-sms:
post:
consumes:
- application/json
description: Sends an SMS to specified user IDs, all users of a role, or direct
phone numbers. Optionally schedule for later with scheduled_at (RFC3339).
parameters:
- description: Bulk SMS content
in: body
name: body
required: true
schema:
properties:
message:
type: string
phone_numbers:
items:
type: string
type: array
role:
type: string
scheduled_at:
type: string
user_ids:
items:
format: int64
type: integer
type: array
type: object
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Send bulk SMS
tags:
- notifications
/api/v1/notifications/scheduled:
get:
description: Returns paginated scheduled notifications with optional status,
channel, and date filters
parameters:
- description: Filter by status
in: query
name: status
type: string
- description: Filter by channel
in: query
name: channel
type: string
- description: Filter after date (RFC3339)
in: query
name: after
type: string
- description: Filter before date (RFC3339)
in: query
name: before
type: string
- default: 20
description: Page size
in: query
name: limit
type: integer
- default: 1
description: Page number
in: query
name: page
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List scheduled notifications
tags:
- notifications
/api/v1/notifications/scheduled/{id}:
get:
description: Returns a single scheduled notification by its ID
parameters:
- description: Scheduled Notification ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get scheduled notification
tags:
- notifications
/api/v1/notifications/scheduled/{id}/cancel:
post:
description: Cancels a scheduled notification if it is still pending or processing
parameters:
- description: Scheduled Notification ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Cancel scheduled notification
tags:
- notifications
/api/v1/notifications/send-email:
post:
consumes:
- multipart/form-data
description: Sends an email to a single email address with optional image attachment
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Send single email
tags:
- notifications
/api/v1/notifications/test-push:
post:
consumes:
- application/json
description: Sends a test push notification to all registered devices of the
current user
parameters:
- description: Test notification content
in: body
name: body
required: true
schema:
properties:
message:
type: string
title:
type: string
type: object
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Send test push notification
tags:
- notifications
/api/v1/payments:
get:
description: Returns the authenticated user's payment history
parameters:
- default: 20
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Get payment history
tags:
- payments
/api/v1/payments/{id}:
get:
description: Returns details of a specific payment
parameters:
- description: Payment ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get payment details
tags:
- payments
/api/v1/payments/{id}/cancel:
post:
description: Cancels a payment that is still pending
parameters:
- description: Payment ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Cancel a pending payment
tags:
- payments
/api/v1/payments/direct:
post:
consumes:
- application/json
description: Creates a payment session and initiates direct payment (OTP-based)
parameters:
- description: Direct payment request
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.initiateDirectPaymentReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Initiate direct payment
tags:
- payments
/api/v1/payments/direct/methods:
get:
description: Returns list of payment methods that support direct payment (OTP-based)
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Get direct payment methods
tags:
- payments
/api/v1/payments/direct/verify-otp:
post:
consumes:
- application/json
description: Verifies the OTP sent for direct payment methods (Amole, HelloCash,
etc.)
parameters:
- description: OTP verification request
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.verifyOTPReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Verify OTP for direct payment
tags:
- payments
/api/v1/payments/methods:
get:
description: Returns list of supported ArifPay payment methods
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Get available payment methods
tags:
- payments
/api/v1/payments/subscribe:
post:
consumes:
- application/json
description: Creates a payment session for a subscription plan
parameters:
- description: Payment request
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.initiatePaymentReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Initiate subscription payment
tags:
- payments
/api/v1/payments/verify/{session_id}:
get:
description: Checks the payment status with the payment provider
parameters:
- description: Session ID
in: path
name: session_id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Verify payment status
tags:
- payments
/api/v1/payments/webhook:
post:
consumes:
- application/json
description: Processes payment notifications from ArifPay
parameters:
- description: Webhook payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.WebhookRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Handle ArifPay webhook
tags:
- payments
/api/v1/practices/{practiceId}/questions:
get:
description: Returns paginated questions for a practice(question-set), including
AUDIO fields
parameters:
- description: Practice(question-set) ID
in: path
name: practiceId
required: true
type: integer
- description: Question type filter (e.g. AUDIO)
in: query
name: question_type
type: string
- default: 10
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get questions by practice
tags:
- question-set-items
/api/v1/progress/practices/{id}/complete:
post:
description: Marks a practice question set as completed for the authenticated
learner
parameters:
- description: Practice Question Set ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Mark practice as completed
tags:
- progression
/api/v1/question-sets:
get:
description: Returns a paginated list of question sets filtered by type
parameters:
- description: Set type (PRACTICE, INITIAL_ASSESSMENT, QUIZ, EXAM, SURVEY, CAPSTONE)
in: query
name: set_type
required: true
type: string
- default: 10
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get question sets by type
tags:
- question-sets
post:
consumes:
- application/json
description: Creates a new question set (practice, assessment, quiz, exam, or
survey)
parameters:
- description: Create question set payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createQuestionSetReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create a new question set
tags:
- question-sets
/api/v1/question-sets/{id}:
delete:
description: Archives a question set (soft delete)
parameters:
- description: Question Set ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Delete a question set
tags:
- question-sets
get:
description: Returns a question set with question count
parameters:
- description: Question Set ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get question set by ID
tags:
- question-sets
put:
consumes:
- application/json
description: Updates a question set's properties
parameters:
- description: Question Set ID
in: path
name: id
required: true
type: integer
- description: Update question set payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateQuestionSetReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update a question set
tags:
- question-sets
/api/v1/question-sets/{setId}/personas:
get:
description: Returns all users assigned as personas to a question set (practice)
parameters:
- description: Question Set ID
in: path
name: setId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get user personas for a question set
tags:
- question-sets
post:
consumes:
- application/json
description: Links a user as a persona to a question set (practice)
parameters:
- description: Question Set ID
in: path
name: setId
required: true
type: integer
- description: Add user persona payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.addUserPersonaReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Add a user as persona to a question set
tags:
- question-sets
/api/v1/question-sets/{setId}/personas/{userId}:
delete:
description: Unlinks a user as persona from a question set (practice)
parameters:
- description: Question Set ID
in: path
name: setId
required: true
type: integer
- description: User ID
in: path
name: userId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Remove a user persona from a question set
tags:
- question-sets
/api/v1/question-sets/{setId}/questions:
get:
description: Returns all questions in a question set with details
parameters:
- description: Question Set ID
in: path
name: setId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get questions in set
tags:
- question-set-items
post:
consumes:
- application/json
description: Links a question to a question set
parameters:
- description: Question Set ID
in: path
name: setId
required: true
type: integer
- description: Add question to set payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.addQuestionToSetReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Add question to set
tags:
- question-set-items
/api/v1/question-sets/{setId}/questions/{questionId}:
delete:
description: Unlinks a question from a question set
parameters:
- description: Question Set ID
in: path
name: setId
required: true
type: integer
- description: Question ID
in: path
name: questionId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Remove question from set
tags:
- question-set-items
/api/v1/question-sets/{setId}/questions/{questionId}/order:
put:
consumes:
- application/json
description: Updates the display order of a question in a set
parameters:
- description: Question Set ID
in: path
name: setId
required: true
type: integer
- description: Question ID
in: path
name: questionId
required: true
type: integer
- description: Update order payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateQuestionOrderReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update question order in set
tags:
- question-set-items
/api/v1/question-sets/by-owner:
get:
description: Returns question sets for a specific owner (e.g., sub-course)
parameters:
- description: Owner type (SUB_COURSE, COURSE, CATEGORY, STANDALONE)
in: query
name: owner_type
required: true
type: string
- description: Owner ID
in: query
name: owner_id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get question sets by owner
tags:
- question-sets
/api/v1/question-sets/sub-courses/{subCourseId}/entry-assessment:
get:
description: Returns the published INITIAL_ASSESSMENT question set for the given
sub-course
parameters:
- description: Sub-course ID
in: path
name: subCourseId
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get entry assessment set for a sub-course
tags:
- question-sets
/api/v1/questions:
get:
description: Returns a paginated list of questions with optional filters
parameters:
- description: Question type filter (MCQ, TRUE_FALSE, SHORT_ANSWER)
in: query
name: question_type
type: string
- description: Difficulty level filter (EASY, MEDIUM, HARD)
in: query
name: difficulty
type: string
- description: Status filter (DRAFT, PUBLISHED, INACTIVE)
in: query
name: status
type: string
- default: 10
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List questions
tags:
- questions
post:
consumes:
- application/json
description: Creates a new question with options (for MCQ/TRUE_FALSE) or short
answers (for SHORT_ANSWER)
parameters:
- description: Create question payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createQuestionReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create a new question
tags:
- questions
/api/v1/questions/{id}:
delete:
description: Archives a question (soft delete)
parameters:
- description: Question ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Delete a question
tags:
- questions
get:
description: Returns a question with its options/short answers
parameters:
- description: Question ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get question by ID
tags:
- questions
put:
consumes:
- application/json
description: Updates a question and optionally replaces its options/short answers
parameters:
- description: Question ID
in: path
name: id
required: true
type: integer
- description: Update question payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updateQuestionReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update a question
tags:
- questions
/api/v1/questions/audio-answer:
post:
consumes:
- multipart/form-data
parameters:
- description: Question ID
in: formData
name: question_id
required: true
type: integer
- description: Question Set ID
in: formData
name: question_set_id
required: true
type: integer
- description: Audio recording
in: formData
name: file
required: true
type: file
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Submit audio answer for a question
tags:
- questions
/api/v1/questions/search:
get:
description: Search questions by text
parameters:
- description: Search query
in: query
name: q
required: true
type: string
- default: 10
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Search questions
tags:
- questions
/api/v1/ratings:
get:
description: Returns paginated ratings for a specific target
parameters:
- description: Target type (app, course, sub_course)
in: query
name: target_type
required: true
type: string
- description: Target ID (0 for app)
in: query
name: target_id
required: true
type: integer
- description: Limit (default 20)
in: query
name: limit
type: integer
- description: Offset (default 0)
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get ratings for a target
tags:
- ratings
post:
consumes:
- application/json
description: Submit a rating for an app, course, or sub-course
parameters:
- description: Submit rating payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.submitRatingReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Submit a rating
tags:
- ratings
/api/v1/ratings/{id}:
delete:
description: Deletes a rating by ID for the current user
parameters:
- description: Rating ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Delete a rating
tags:
- ratings
/api/v1/ratings/me:
get:
description: Returns the current user's rating for a specific target
parameters:
- description: Target type (app, course, sub_course)
in: query
name: target_type
required: true
type: string
- description: Target ID (0 for app)
in: query
name: target_id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get my rating for a target
tags:
- ratings
/api/v1/ratings/me/all:
get:
description: Returns all ratings submitted by the current user
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get all my ratings
tags:
- ratings
/api/v1/ratings/summary:
get:
description: Returns the total count and average stars for a specific target
parameters:
- description: Target type (app, course, sub_course)
in: query
name: target_type
required: true
type: string
- description: Target ID (0 for app)
in: query
name: target_id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get rating summary for a target
tags:
- ratings
/api/v1/rbac/permissions:
get:
consumes:
- application/json
description: Get all permissions in the system grouped by group name
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
items:
$ref: '#/definitions/domain.Permission'
type: array
type: object
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: List all permissions
tags:
- rbac
/api/v1/rbac/permissions/groups:
get:
consumes:
- application/json
description: Get all distinct permission group names
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
items:
type: string
type: array
type: object
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: List permission groups
tags:
- rbac
/api/v1/rbac/permissions/sync:
post:
consumes:
- application/json
description: Re-seed permissions from code and reload the RBAC cache
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Sync permissions
tags:
- rbac
/api/v1/rbac/roles:
get:
consumes:
- application/json
description: Get all roles with optional filters
parameters:
- description: Search by role name
in: query
name: query
type: string
- description: Filter by system role (true/false)
in: query
name: is_system
type: boolean
- description: 'Page number (default: 1)'
in: query
name: page
type: integer
- description: 'Page size (default: 20)'
in: query
name: page_size
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: List all roles
tags:
- rbac
post:
consumes:
- application/json
description: Create a new role with a name and description
parameters:
- description: Role creation payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.CreateRoleReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/domain.RoleRecord'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Create a new role
tags:
- rbac
/api/v1/rbac/roles/{id}:
delete:
consumes:
- application/json
description: Delete a non-system role by ID
parameters:
- description: Role ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Delete a role
tags:
- rbac
get:
consumes:
- application/json
description: Get a role and its permissions by ID
parameters:
- description: Role ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/domain.RoleWithPermissions'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get a role by ID
tags:
- rbac
put:
consumes:
- application/json
description: Update an existing role's name and description
parameters:
- description: Role ID
in: path
name: id
required: true
type: integer
- description: Role update payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.UpdateRoleReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Update a role
tags:
- rbac
/api/v1/rbac/roles/{id}/permissions:
get:
consumes:
- application/json
description: Get all permissions assigned to a role
parameters:
- description: Role ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
items:
$ref: '#/definitions/domain.Permission'
type: array
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get permissions for a role
tags:
- rbac
put:
consumes:
- application/json
description: Replace all permissions for a role with the given permission IDs
parameters:
- description: Role ID
in: path
name: id
required: true
type: integer
- description: Permission IDs payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.SetRolePermissionsReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Set permissions for a role
tags:
- rbac
/api/v1/sendSMS:
post:
consumes:
- application/json
description: Sends an SMS message to a single phone number using AfroMessage
parameters:
- description: Send SMS request
in: body
name: sendSMS
required: true
schema:
$ref: '#/definitions/handlers.SendSingleAfroSMSReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Send single SMS via AfroMessage
tags:
- user
/api/v1/subscription-plans:
get:
description: Returns all subscription plans
parameters:
- description: Return only active plans
in: query
name: active_only
type: boolean
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: List subscription plans
tags:
- subscriptions
post:
consumes:
- application/json
description: Creates a new subscription plan (admin only)
parameters:
- description: Create plan payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.createPlanReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create a subscription plan
tags:
- subscriptions
/api/v1/subscription-plans/{id}:
delete:
description: Deletes a subscription plan (admin only)
parameters:
- description: Plan ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Delete a subscription plan
tags:
- subscriptions
get:
description: Returns a single subscription plan by ID
parameters:
- description: Plan ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get a subscription plan
tags:
- subscriptions
put:
consumes:
- application/json
description: Updates a subscription plan (admin only)
parameters:
- description: Plan ID
in: path
name: id
required: true
type: integer
- description: Update plan payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.updatePlanReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update a subscription plan
tags:
- subscriptions
/api/v1/subscriptions:
post:
consumes:
- application/json
deprecated: true
description: Creates a new subscription for the authenticated user. For regular
users, use /payments/subscribe instead.
parameters:
- description: Subscribe payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.subscribeReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Subscribe to a plan (Admin only - bypasses payment)
tags:
- subscriptions
/api/v1/subscriptions/{id}/auto-renew:
put:
consumes:
- application/json
description: Enables or disables auto-renewal for a subscription
parameters:
- description: Subscription ID
in: path
name: id
required: true
type: integer
- description: Auto-renew payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.autoRenewReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Set auto-renew
tags:
- subscriptions
/api/v1/subscriptions/{id}/cancel:
post:
description: Cancels the user's subscription
parameters:
- description: Subscription ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Cancel subscription
tags:
- subscriptions
/api/v1/subscriptions/checkout:
post:
consumes:
- application/json
description: Initiates payment for a subscription plan. Returns payment URL
for checkout.
parameters:
- description: Subscribe with payment payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.subscribeWithPaymentReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"409":
description: User already has active subscription
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Subscribe to a plan with payment
tags:
- subscriptions
/api/v1/subscriptions/history:
get:
description: Returns the authenticated user's subscription history
parameters:
- default: 20
description: Limit
in: query
name: limit
type: integer
- default: 0
description: Offset
in: query
name: offset
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Get subscription history
tags:
- subscriptions
/api/v1/subscriptions/me:
get:
description: Returns the authenticated user's active subscription
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get current subscription
tags:
- subscriptions
/api/v1/subscriptions/status:
get:
description: Returns whether the authenticated user has an active subscription
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
summary: Check subscription status
tags:
- subscriptions
/api/v1/super-login:
post:
consumes:
- application/json
description: Login super-admin
parameters:
- description: Login super-admin
in: body
name: login
required: true
schema:
$ref: '#/definitions/domain.LoginRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.LoginAdminRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Login super-admin
tags:
- auth
/api/v1/t-approver/{id}:
get:
consumes:
- application/json
description: Get a single admin by id
parameters:
- description: User ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.AdminRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Get admin by id
tags:
- admin
put:
consumes:
- application/json
description: Update Admin
parameters:
- description: Update Admin
in: body
name: admin
required: true
schema:
$ref: '#/definitions/handlers.updateAdminReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Update Admin
tags:
- admin
/api/v1/team/login:
post:
consumes:
- application/json
description: Authenticate a team member (internal staff) with email and password
parameters:
- description: Team member login credentials
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.TeamMemberLoginReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/handlers.teamMemberLoginRes'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Login team member
tags:
- team
/api/v1/team/me:
get:
consumes:
- application/json
description: Get the authenticated team member's own profile
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/domain.TeamMemberResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get my team profile
tags:
- team
/api/v1/team/members:
get:
consumes:
- application/json
description: Get a paginated list of team members with optional filtering
parameters:
- description: Filter by team role (super_admin, admin, content_manager, support_agent,
instructor, finance, hr, analyst)
in: query
name: team_role
type: string
- description: Filter by department
in: query
name: department
type: string
- description: Filter by status (active, inactive, suspended, terminated)
in: query
name: status
type: string
- description: Search by name, email, or phone number
in: query
name: search
type: string
- description: 'Page number (default: 1)'
in: query
name: page
type: integer
- description: 'Items per page (default: 10, max: 100)'
in: query
name: page_size
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
items:
$ref: '#/definitions/domain.TeamMemberResponse'
type: array
metadata:
$ref: '#/definitions/domain.Pagination'
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: List all team members
tags:
- team
post:
consumes:
- application/json
description: Create a new internal team member (admin only)
parameters:
- description: Team member creation payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.CreateTeamMemberReq'
produces:
- application/json
responses:
"201":
description: Created
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/domain.TeamMemberResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Create a new team member
tags:
- team
/api/v1/team/members/{id}:
delete:
consumes:
- application/json
description: Delete a team member (super admin only)
parameters:
- description: Team Member ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Delete team member
tags:
- team
get:
consumes:
- application/json
description: Retrieve a team member's details by their ID
parameters:
- description: Team Member ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/domain.TeamMemberResponse'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get team member by ID
tags:
- team
put:
consumes:
- application/json
description: Update an existing team member's details (admin only)
parameters:
- description: Team Member ID
in: path
name: id
required: true
type: integer
- description: Team member update payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.UpdateTeamMemberReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Update team member
tags:
- team
/api/v1/team/members/{id}/change-password:
post:
consumes:
- application/json
description: Change a team member's password (requires current password)
parameters:
- description: Team Member ID
in: path
name: id
required: true
type: integer
- description: Password change payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.changePasswordReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Change team member password
tags:
- team
/api/v1/team/members/{id}/status:
patch:
consumes:
- application/json
description: Update a team member's status (active, inactive, suspended, terminated)
parameters:
- description: Team Member ID
in: path
name: id
required: true
type: integer
- description: Status update payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.UpdateTeamMemberStatusReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Update team member status
tags:
- team
/api/v1/team/refresh:
post:
consumes:
- application/json
description: Exchanges a valid team refresh token for a new access JWT and a
rotated refresh token (use only tokens from POST /team/login or this endpoint).
parameters:
- description: Current refresh token
in: body
name: body
required: true
schema:
$ref: '#/definitions/handlers.teamMemberRefreshReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/handlers.teamMemberLoginRes'
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Refresh team member tokens
tags:
- team
/api/v1/team/stats:
get:
consumes:
- application/json
description: Get statistics about team members by status
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/domain.TeamMemberStats'
type: object
"401":
description: Unauthorized
schema:
$ref: '#/definitions/domain.ErrorResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get team member statistics
tags:
- team
/api/v1/tenant:
get:
consumes:
- application/json
description: Check if phone number or email exist
parameters:
- description: Check phone number or email exist
in: body
name: checkPhoneEmailExist
required: true
schema:
$ref: '#/definitions/handlers.CheckPhoneEmailExistReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.CheckPhoneEmailExistRes'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Check if phone number or email exist
tags:
- user
/api/v1/user:
put:
consumes:
- application/json
description: Updates user profile information (partial updates supported)
parameters:
- description: User ID
in: path
name: user_id
required: true
type: integer
- description: Update user payload
in: body
name: body
required: true
schema:
$ref: '#/definitions/domain.UpdateUserReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Update user profile
tags:
- user
/api/v1/user/{id}/profile-picture:
post:
consumes:
- multipart/form-data
description: Uploads a profile picture for the specified user
parameters:
- description: User ID
in: path
name: id
required: true
type: integer
- description: Image file (jpg|png|webp)
in: formData
name: file
required: true
type: file
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
security:
- Bearer: []
summary: Upload profile picture
tags:
- user
/api/v1/user/{user_id}/is-pending:
get:
consumes:
- application/json
description: Returns whether the specified user has a status of "pending"
parameters:
- description: User ID
in: path
name: user_id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Check if user status is pending
tags:
- user
/api/v1/user/{user_id}/is-profile-completed:
get:
consumes:
- application/json
description: Returns the profile completion status and percentage for the specified
user
parameters:
- description: User ID
in: path
name: user_id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Check if user profile is completed
tags:
- user
/api/v1/user/delete/{id}:
delete:
consumes:
- application/json
description: Delete a user by their ID
parameters:
- description: User ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Delete user by ID
tags:
- user
/api/v1/user/me:
delete:
description: Starts account deletion with grace period before permanent purge
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
security:
- Bearer: []
summary: Request deletion of my account
tags:
- user
/api/v1/user/me/deletion/cancel:
post:
description: Cancels a pending self-deletion request during grace period
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"403":
description: Forbidden
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
security:
- Bearer: []
summary: Cancel my account deletion request
tags:
- user
/api/v1/user/resetPassword:
post:
consumes:
- application/json
description: Reset password
parameters:
- description: Reset password
in: body
name: resetPassword
required: true
schema:
$ref: '#/definitions/handlers.ResetPasswordReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Reset password
tags:
- user
/api/v1/user/search:
post:
consumes:
- application/json
description: Search for user using name or phone
parameters:
- description: Search for using his name or phone
in: body
name: searchUserByNameOrPhone
required: true
schema:
$ref: '#/definitions/handlers.SearchUserByNameOrPhoneReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.UserProfileResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Search for user using name or phone
tags:
- user
/api/v1/user/sendResetCode:
post:
consumes:
- application/json
description: Send reset code
parameters:
- description: Send reset code
in: body
name: resetCode
required: true
schema:
$ref: '#/definitions/handlers.ResetCodeReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Send reset code
tags:
- user
/api/v1/user/single/{id}:
get:
consumes:
- application/json
description: Get a single user by id
parameters:
- description: User ID
in: path
name: id
required: true
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.UserProfileResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"401":
description: Unauthorized
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Get user by id
tags:
- user
/api/v1/user/status:
patch:
consumes:
- application/json
description: Activates, deactivates, or suspends a user account
parameters:
- description: Status update payload
in: body
name: body
required: true
schema:
type: object
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Update user status
tags:
- user
/api/v1/user/verify-otp:
post:
consumes:
- application/json
description: Verify OTP for registration or other actions
parameters:
- description: Verify OTP
in: body
name: verifyOtp
required: true
schema:
$ref: '#/definitions/domain.VerifyOtpReq'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Verify OTP
tags:
- user
/api/v1/users:
get:
consumes:
- application/json
description: Get users with optional filters
parameters:
- description: Role filter
in: query
name: role
type: string
- description: Search query
in: query
name: query
type: string
- description: Page number
in: query
name: page
type: integer
- description: Page size
in: query
name: page_size
type: integer
- description: Created before (RFC3339)
in: query
name: created_before
type: string
- description: Created after (RFC3339)
in: query
name: created_after
type: string
- description: Status filter (ACTIVE, PENDING, SUSPENDED, DEACTIVATED)
in: query
name: status
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/response.APIResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/response.APIResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/response.APIResponse'
summary: Get all users
tags:
- user
/api/v1/users/summary:
get:
consumes:
- application/json
description: Returns total users, active users, and users who joined this month
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/domain.Response'
- properties:
data:
$ref: '#/definitions/domain.UserSummary'
type: object
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
security:
- Bearer: []
summary: Get user summary statistics
tags:
- user
/api/v1/vimeo/oembed:
get:
consumes:
- application/json
description: Fetches oEmbed metadata for a Vimeo video URL
parameters:
- description: Vimeo video URL
in: query
name: url
required: true
type: string
- description: Desired width
in: query
name: width
type: integer
- description: Desired height
in: query
name: height
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/vimeo.OEmbedResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get oEmbed data for a Vimeo URL
tags:
- Vimeo
/api/v1/vimeo/sample:
get:
consumes:
- application/json
description: Fetches a sample video from Vimeo and returns video details along
with an embeddable iframe for client-side integration
parameters:
- default: "76979871"
description: Vimeo Video ID to use as sample
in: query
name: video_id
type: string
- default: 640
description: Player width
in: query
name: width
type: integer
- default: 360
description: Player height
in: query
name: height
type: integer
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/domain.Response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get a sample Vimeo video with iframe embed
tags:
- Vimeo
/api/v1/vimeo/uploads/pull:
post:
consumes:
- application/json
description: Initiates a pull upload where Vimeo fetches the video from a URL
parameters:
- description: Pull Upload Request
in: body
name: request
required: true
schema:
$ref: '#/definitions/handlers.CreatePullUploadRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/handlers.VimeoUploadResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create a pull upload to Vimeo
tags:
- Vimeo
/api/v1/vimeo/uploads/tus:
post:
consumes:
- application/json
description: Initiates a TUS resumable upload and returns the upload link
parameters:
- description: TUS Upload Request
in: body
name: request
required: true
schema:
$ref: '#/definitions/handlers.CreateTusUploadRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/handlers.VimeoUploadResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Create a TUS resumable upload to Vimeo
tags:
- Vimeo
/api/v1/vimeo/videos/{video_id}:
delete:
consumes:
- application/json
description: Deletes a video from the Vimeo account
parameters:
- description: Vimeo Video ID
in: path
name: video_id
required: true
type: string
produces:
- application/json
responses:
"204":
description: No Content
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Delete a video from Vimeo
tags:
- Vimeo
get:
consumes:
- application/json
description: Retrieves video details from Vimeo by video ID
parameters:
- description: Vimeo Video ID
in: path
name: video_id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.VimeoVideoResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get video information from Vimeo
tags:
- Vimeo
/api/v1/vimeo/videos/{video_id}/embed:
get:
consumes:
- application/json
description: Generates an embeddable player iframe for the video
parameters:
- description: Vimeo Video ID
in: path
name: video_id
required: true
type: string
- default: 640
description: Player width
in: query
name: width
type: integer
- default: 360
description: Player height
in: query
name: height
type: integer
- description: Autoplay video
in: query
name: autoplay
type: boolean
- description: Loop video
in: query
name: loop
type: boolean
- description: Mute video
in: query
name: muted
type: boolean
- description: Background mode (no controls)
in: query
name: background
type: boolean
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.VimeoEmbedResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get embed code for a Vimeo video
tags:
- Vimeo
/api/v1/vimeo/videos/{video_id}/status:
get:
consumes:
- application/json
description: Returns the current transcoding status of a video
parameters:
- description: Vimeo Video ID
in: path
name: video_id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
additionalProperties:
type: string
type: object
"400":
description: Bad Request
schema:
$ref: '#/definitions/domain.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/domain.ErrorResponse'
summary: Get transcode status of a Vimeo video
tags:
- Vimeo
securityDefinitions:
Bearer:
in: header
name: Authorization
type: apiKey
swagger: "2.0"