// Package docs Code generated by swaggo/swag. DO NOT EDIT package docs import "github.com/swaggo/swag" const docTemplate = `{ "schemes": {{ marshal .Schemes }}, "swagger": "2.0", "info": { "description": "{{escape .Description}}", "title": "{{.Title}}", "termsOfService": "http://swagger.io/terms/", "contact": { "name": "API Support", "url": "http://www.swagger.io/support", "email": "support@swagger.io" }, "license": { "name": "Apache 2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0.html" }, "version": "{{.Version}}" }, "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { "/api/v1/activity-logs": { "get": { "description": "Returns a filtered, paginated list of activity logs", "produces": [ "application/json" ], "tags": [ "activity-logs" ], "summary": "Get activity logs", "parameters": [ { "type": "integer", "description": "Filter by actor ID", "name": "actor_id", "in": "query" }, { "type": "string", "description": "Filter by action", "name": "action", "in": "query" }, { "type": "string", "description": "Filter by resource type", "name": "resource_type", "in": "query" }, { "type": "integer", "description": "Filter by resource ID", "name": "resource_id", "in": "query" }, { "type": "string", "description": "Filter logs after this RFC3339 timestamp", "name": "after", "in": "query" }, { "type": "string", "description": "Filter logs before this RFC3339 timestamp", "name": "before", "in": "query" }, { "type": "integer", "default": 20, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "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" } } } } }, "/api/v1/activity-logs/{id}": { "get": { "description": "Returns a single activity log entry by its ID", "produces": [ "application/json" ], "tags": [ "activity-logs" ], "summary": "Get activity log by ID", "parameters": [ { "type": "integer", "description": "Activity Log ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/admin": { "get": { "description": "Get all Admins", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "admin" ], "summary": "Get all Admins", "parameters": [ { "type": "integer", "description": "Page number", "name": "page", "in": "query" }, { "type": "integer", "description": "Page size", "name": "page_size", "in": "query" } ], "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" } } } }, "post": { "description": "Create Admin", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "admin" ], "summary": "Create Admin", "parameters": [ { "description": "Create admin", "name": "manger", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.CreateAdminReq" } } ], "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" } } } } }, "/api/v1/admin/app-versions": { "get": { "security": [ { "Bearer": [] } ], "produces": [ "application/json" ], "tags": [ "app-versions" ], "summary": "List mobile app versions (admin)", "parameters": [ { "type": "string", "description": "Filter by ANDROID or IOS", "name": "platform", "in": "query" }, { "type": "string", "description": "Filter by ACTIVE or INACTIVE", "name": "status", "in": "query" }, { "type": "integer", "description": "Limit (default 20)", "name": "limit", "in": "query" }, { "type": "integer", "description": "Offset (default 0)", "name": "offset", "in": "query" } ], "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" } } } }, "post": { "security": [ { "Bearer": [] } ], "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "app-versions" ], "summary": "Create mobile app version (admin)", "parameters": [ { "description": "App version payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createMobileAppVersionReq" } } ], "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" } } } } }, "/api/v1/admin/app-versions/{id}": { "get": { "security": [ { "Bearer": [] } ], "produces": [ "application/json" ], "tags": [ "app-versions" ], "summary": "Get mobile app version by ID (admin)", "parameters": [ { "type": "integer", "description": "App version ID", "name": "id", "in": "path", "required": true } ], "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" } } } }, "put": { "security": [ { "Bearer": [] } ], "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "app-versions" ], "summary": "Update mobile app version (admin)", "parameters": [ { "type": "integer", "description": "App version ID", "name": "id", "in": "path", "required": true }, { "description": "App version payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateMobileAppVersionReq" } } ], "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" } } } }, "delete": { "security": [ { "Bearer": [] } ], "produces": [ "application/json" ], "tags": [ "app-versions" ], "summary": "Delete mobile app version (admin)", "parameters": [ { "type": "integer", "description": "App version ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/admin/email-templates": { "get": { "description": "Returns email templates for admin management", "produces": [ "application/json" ], "tags": [ "email-templates" ], "summary": "List email templates (admin)", "parameters": [ { "type": "string", "description": "ACTIVE or INACTIVE", "name": "status", "in": "query" }, { "type": "string", "description": "Search by slug, name, or subject", "name": "query", "in": "query" }, { "type": "integer", "description": "Limit (default 20)", "name": "limit", "in": "query" }, { "type": "integer", "description": "Offset (default 0)", "name": "offset", "in": "query" } ], "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" } } } }, "post": { "description": "Creates a new custom email template", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "email-templates" ], "summary": "Create email template", "parameters": [ { "description": "Create email template payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createEmailTemplateReq" } } ], "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" } } } } }, "/api/v1/admin/email-templates/slug/{slug}": { "get": { "description": "Returns one email template by slug regardless of status", "produces": [ "application/json" ], "tags": [ "email-templates" ], "summary": "Get email template by slug (admin)", "parameters": [ { "type": "string", "description": "Email template slug", "name": "slug", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/admin/email-templates/slug/{slug}/preview": { "post": { "description": "Renders an email template with sample variables without sending", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "email-templates" ], "summary": "Preview email template by slug", "parameters": [ { "type": "string", "description": "Email template slug", "name": "slug", "in": "path", "required": true }, { "description": "Preview variables", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.previewEmailTemplateReq" } } ], "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" } } } } }, "/api/v1/admin/email-templates/{id}": { "get": { "description": "Returns one email template regardless of status", "produces": [ "application/json" ], "tags": [ "email-templates" ], "summary": "Get email template by ID (admin)", "parameters": [ { "type": "integer", "description": "Email template ID", "name": "id", "in": "path", "required": true } ], "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" } } } }, "put": { "description": "Updates an existing email template", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "email-templates" ], "summary": "Update email template", "parameters": [ { "type": "integer", "description": "Email template ID", "name": "id", "in": "path", "required": true }, { "description": "Update email template payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateEmailTemplateReq" } } ], "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" } } } }, "delete": { "description": "Deletes a custom email template", "produces": [ "application/json" ], "tags": [ "email-templates" ], "summary": "Delete email template", "parameters": [ { "type": "integer", "description": "Email template ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/admin/email-templates/{id}/preview": { "post": { "description": "Renders an email template with sample variables without sending", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "email-templates" ], "summary": "Preview email template by ID", "parameters": [ { "type": "integer", "description": "Email template ID", "name": "id", "in": "path", "required": true }, { "description": "Preview variables", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.previewEmailTemplateReq" } } ], "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" } } } } }, "/api/v1/admin/faqs": { "get": { "description": "Returns FAQs for admin management with status/category filtering", "produces": [ "application/json" ], "tags": [ "faqs" ], "summary": "List FAQs (admin)", "parameters": [ { "type": "string", "description": "ACTIVE or INACTIVE", "name": "status", "in": "query" }, { "type": "string", "description": "Filter by category", "name": "category", "in": "query" }, { "type": "integer", "description": "Limit (default 20)", "name": "limit", "in": "query" }, { "type": "integer", "description": "Offset (default 0)", "name": "offset", "in": "query" } ], "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" } } } }, "post": { "description": "Creates a new FAQ item", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "faqs" ], "summary": "Create FAQ", "parameters": [ { "description": "Create FAQ payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createFAQReq" } } ], "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" } } } } }, "/api/v1/admin/faqs/{id}": { "get": { "description": "Returns one FAQ regardless of status", "produces": [ "application/json" ], "tags": [ "faqs" ], "summary": "Get FAQ by ID (admin)", "parameters": [ { "type": "integer", "description": "FAQ ID", "name": "id", "in": "path", "required": true } ], "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" } } } }, "put": { "description": "Updates an existing FAQ item", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "faqs" ], "summary": "Update FAQ", "parameters": [ { "type": "integer", "description": "FAQ ID", "name": "id", "in": "path", "required": true }, { "description": "Update FAQ payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateFAQReq" } } ], "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" } } } }, "delete": { "description": "Deletes an FAQ item", "produces": [ "application/json" ], "tags": [ "faqs" ], "summary": "Delete FAQ", "parameters": [ { "type": "integer", "description": "FAQ ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/admin/field-options": { "get": { "produces": [ "application/json" ], "tags": [ "field-options" ], "summary": "List field options (admin)", "parameters": [ { "type": "string", "description": "Filter by field key", "name": "field_key", "in": "query" }, { "type": "string", "description": "ACTIVE or INACTIVE", "name": "status", "in": "query" }, { "type": "integer", "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "post": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "field-options" ], "summary": "Create field option (admin)", "parameters": [ { "description": "Create option", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createFieldOptionReq" } } ], "responses": { "201": { "description": "Created", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/admin/field-options/{id}": { "get": { "produces": [ "application/json" ], "tags": [ "field-options" ], "summary": "Get field option by ID (admin)", "parameters": [ { "type": "integer", "description": "Option ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "put": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "field-options" ], "summary": "Update field option (admin)", "parameters": [ { "type": "integer", "description": "Option ID", "name": "id", "in": "path", "required": true }, { "description": "Update option", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateFieldOptionReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "delete": { "produces": [ "application/json" ], "tags": [ "field-options" ], "summary": "Delete field option (admin)", "parameters": [ { "type": "integer", "description": "Option ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/admin/roles/{role}/bulk-deactivate": { "post": { "security": [ { "Bearer": [] } ], "description": "Sets all platform users with the given users.role to DEACTIVATED (except the caller) and all team_members with the given team_role to inactive. Path :role may be a role key (e.g. INSTRUCTOR, ADMIN) or a decimal RBAC roles.id from GET /api/v1/rbac/roles (resolved to RoleRecord.name uppercased). SUPER_ADMIN cannot be bulk-deactivated. ADMIN platform users must use SUPER_ADMIN to bulk change other platform ADMIN users (team_members with team_role ADMIN under path ADMIN remain allowed). Empty body allowed; optionally pass exclude_team_member_id to skip one team_members row (e.g. yourself).", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "admin" ], "summary": "Bulk deactivate accounts by role (SUPER_ADMIN or ADMIN platform users only)", "parameters": [ { "type": "string", "description": "Role key (INSTRUCTOR etc.) or RBAC roles.id (integer string)", "name": "role", "in": "path", "required": true }, { "description": "Optional exclusions", "name": "body", "in": "body", "schema": { "$ref": "#/definitions/domain.BulkAccountsByRoleRequest" } } ], "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" } } } } }, "/api/v1/admin/roles/{role}/bulk-reactivate": { "post": { "security": [ { "Bearer": [] } ], "description": "Sets all platform users with the given role from DEACTIVATED to ACTIVE (except the caller) and all team_members with the given team_role from inactive to active. Path :role may be a role key or decimal RBAC roles.id (see bulk-deactivate). Path role must correspond to valid platform users.role or team_members.team_role (after resolving id → name). SUPER_ADMIN cannot be bulk changed. ADMIN callers cannot bulk change other platform ADMIN users (team_members ADMIN under path ADMIN is allowed). Matches only users currently DEACTIVATED and team rows currently inactive.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "admin" ], "summary": "Bulk reactivate accounts by role (SUPER_ADMIN or ADMIN platform users only)", "parameters": [ { "type": "string", "description": "Role key (INSTRUCTOR etc.) or RBAC roles.id (integer string)", "name": "role", "in": "path", "required": true }, { "description": "Optional exclusions", "name": "body", "in": "body", "schema": { "$ref": "#/definitions/domain.BulkAccountsByRoleRequest" } } ], "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" } } } } }, "/api/v1/admin/users/deletion-requests": { "get": { "description": "Returns account deletion requests for admin panel tracking with filtering and pagination", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "List account deletion requests", "parameters": [ { "type": "string", "description": "Search in first_name, last_name, email, phone_number", "name": "query", "in": "query" }, { "type": "string", "description": "Role filter", "name": "role", "in": "query" }, { "type": "string", "description": "User status filter (ACTIVE, PENDING, SUSPENDED, DEACTIVATED)", "name": "status", "in": "query" }, { "type": "string", "description": "Deletion state filter (PENDING, DUE, CANCELLED)", "name": "state", "in": "query" }, { "type": "string", "description": "Requested before (RFC3339)", "name": "requested_before", "in": "query" }, { "type": "string", "description": "Requested after (RFC3339)", "name": "requested_after", "in": "query" }, { "type": "string", "description": "Scheduled before (RFC3339)", "name": "scheduled_before", "in": "query" }, { "type": "string", "description": "Scheduled after (RFC3339)", "name": "scheduled_after", "in": "query" }, { "type": "integer", "description": "Page number (default 1)", "name": "page", "in": "query" }, { "type": "integer", "description": "Page size (default 10, max 100)", "name": "page_size", "in": "query" } ], "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" } } } } }, "/api/v1/admin/users/{user_id}/lms-learning-activity": { "get": { "security": [ { "Bearer": [] } ], "description": "Returns programs, courses, modules, and lessons with completion details and completed practices. Only persisted completion signals are included (completed lessons, completed published practices, and rollup completion timestamps—not partial or in-progress attempts).", "produces": [ "application/json" ], "tags": [ "lms" ], "summary": "Get a user's nested LMS learning activity (admin)", "parameters": [ { "type": "integer", "description": "Target user ID", "name": "user_id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/admin/users/{user_id}/recent-activity": { "get": { "security": [ { "Bearer": [] } ], "description": "Reverse-chronological feed for profile UI: account joined plus LMS completion milestones (lessons/modules/courses/programs). Optional practice completions via include_practices. Does not include \"started learning path\" unless you add persisted engagement events—the schema stores completions only.", "produces": [ "application/json" ], "tags": [ "lms" ], "summary": "Recent activity timeline for a user (admin)", "parameters": [ { "type": "integer", "description": "Target user ID", "name": "user_id", "in": "path", "required": true }, { "type": "integer", "description": "Max items after merge (default 40, max 120)", "name": "limit", "in": "query" }, { "type": "boolean", "description": "Include completed LMS practices (more verbose)", "name": "include_practices", "in": "query" } ], "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" } } } } }, "/api/v1/admin/{id}": { "get": { "description": "Get a single admin by id", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "admin" ], "summary": "Get admin by id", "parameters": [ { "type": "integer", "description": "User ID", "name": "id", "in": "path", "required": true } ], "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" } } } }, "put": { "description": "Update Admin", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "admin" ], "summary": "Update Admin", "parameters": [ { "description": "Update Admin", "name": "admin", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateAdminReq" } } ], "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" } } } } }, "/api/v1/analytics/dashboard": { "get": { "description": "Platform analytics with optional date filters: all-time (default), year, year+month, or custom from/to range. When year is set, payments.revenue_monthly returns Jan–Dec SUCCESS revenue totals (UTC) per currency for that calendar year — use for yearly revenue charts. Daily series remains in revenue_last_30_days (see date_filter.series_*). Courses section counts LMS + exam_prep inventory.", "produces": [ "application/json" ], "tags": [ "analytics" ], "summary": "Analytics dashboard", "parameters": [ { "type": "integer", "description": "Calendar year (e.g. 2025)", "name": "year", "in": "query" }, { "type": "integer", "description": "Calendar month 1-12 (requires year)", "name": "month", "in": "query" }, { "type": "string", "description": "Custom range start (YYYY-MM-DD or RFC3339)", "name": "from", "in": "query" }, { "type": "string", "description": "Custom range end (YYYY-MM-DD or RFC3339, inclusive)", "name": "to", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.AnalyticsDashboard" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/app/version/check": { "get": { "description": "Public endpoint for mobile clients to determine if an app update is available (force or optional)", "produces": [ "application/json" ], "tags": [ "app-versions" ], "summary": "Check mobile app version", "parameters": [ { "type": "string", "description": "Platform: ANDROID or IOS", "name": "platform", "in": "query", "required": true }, { "type": "integer", "description": "Client build number (Android versionCode / iOS build number)", "name": "version_code", "in": "query", "required": true } ], "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" } } } } }, "/api/v1/assessment/questions": { "get": { "description": "Returns all active assessment questions from the initial assessment set", "produces": [ "application/json" ], "tags": [ "assessment-question" ], "summary": "List assessment questions", "responses": { "200": { "description": "OK", "schema": { "type": "array", "items": { "$ref": "#/definitions/domain.QuestionWithDetails" } } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "post": { "description": "Creates a new assessment question using the unified questions system", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "assessment-question" ], "summary": "Create assessment question", "parameters": [ { "description": "Create question payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createQuestionReq" } } ], "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" } } } } }, "/api/v1/assessment/questions/{id}": { "get": { "description": "Returns a single assessment question with its options or answer", "produces": [ "application/json" ], "tags": [ "assessment-question" ], "summary": "Get assessment question by ID", "parameters": [ { "type": "integer", "description": "Question ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/auth/google/android": { "post": { "tags": [ "auth" ], "summary": "Login via Google Android ID Token", "parameters": [ { "description": "Google ID Token from Android", "name": "idToken", "in": "body", "required": true, "schema": { "type": "string" } } ], "responses": {} } }, "/api/v1/auth/google/callback": { "get": { "tags": [ "auth" ], "summary": "Google login callback", "responses": {} } }, "/api/v1/auth/google/login": { "get": { "tags": [ "auth" ], "summary": "Google login redirect", "responses": {} } }, "/api/v1/auth/logout": { "post": { "description": "Logout user", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Logout user", "parameters": [ { "description": "Logout user", "name": "logout", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.logoutReq" } } ], "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" } } } } }, "/api/v1/auth/refresh": { "post": { "description": "Refresh token", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Refresh token", "parameters": [ { "description": "tokens", "name": "refresh", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.refreshToken" } } ], "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" } } } } }, "/api/v1/courses/{courseId}/modules": { "get": { "produces": [ "application/json" ], "tags": [ "modules" ], "summary": "List modules for a course", "parameters": [ { "type": "integer", "description": "Course ID", "name": "courseId", "in": "path", "required": true }, { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "post": { "description": "Create a module under a course; parent program is taken from the course.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "modules" ], "summary": "Create module", "parameters": [ { "type": "integer", "description": "Course ID", "name": "courseId", "in": "path", "required": true }, { "description": "Module", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateModuleInput" } } ], "responses": { "201": { "description": "Created", "schema": { "$ref": "#/definitions/domain.Response" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/courses/{courseId}/modules/reorder": { "put": { "tags": [ "modules" ], "summary": "Reorder modules within a course", "parameters": [ { "type": "integer", "description": "Course ID", "name": "courseId", "in": "path", "required": true }, { "description": "ordered_ids: every module id in this course, in the new order", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.ReorderIDsRequest" } } ], "responses": {} } }, "/api/v1/courses/{id}": { "get": { "produces": [ "application/json" ], "tags": [ "courses" ], "summary": "Get course by ID", "parameters": [ { "type": "integer", "description": "Course ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "put": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "courses" ], "summary": "Update course", "parameters": [ { "type": "integer", "description": "Course ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateCourseInput" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "delete": { "tags": [ "courses" ], "summary": "Delete course", "parameters": [ { "type": "integer", "description": "Course ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/courses/{id}/practices": { "get": { "tags": [ "practices" ], "parameters": [ { "type": "integer", "description": "Course ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/exam-prep/catalog-courses": { "get": { "produces": [ "application/json" ], "tags": [ "exam-prep" ], "summary": "List exam-prep catalog courses", "parameters": [ { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "post": { "description": "Top-level exam track (DET, IELTS, …) in schema exam_prep — separate from LMS programs/courses", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "exam-prep" ], "summary": "Create exam-prep catalog course", "parameters": [ { "description": "Catalog course", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateExamPrepCatalogCourseInput" } } ], "responses": { "201": { "description": "Created", "schema": { "$ref": "#/definitions/domain.Response" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/exam-prep/catalog-courses/reorder": { "put": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "exam-prep" ], "summary": "Reorder all exam-prep catalog courses", "parameters": [ { "description": "ordered_ids: every catalog course id exactly once", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.ReorderIDsRequest" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/exam-prep/catalog-courses/{catalogCourseId}/units": { "get": { "tags": [ "exam-prep" ], "summary": "List exam-prep units for a catalog course", "parameters": [ { "type": "integer", "description": "Catalog course ID", "name": "catalogCourseId", "in": "path", "required": true }, { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "post": { "description": "Unit under a catalog course (e.g. chapter title). Optional sort_order assigns position within that catalog course (siblings at or after that index are shifted); omit to append after the current highest sort_order in the catalog course.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "exam-prep" ], "summary": "Create exam-prep unit", "parameters": [ { "type": "integer", "description": "Catalog course ID", "name": "catalogCourseId", "in": "path", "required": true }, { "description": "Unit", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateExamPrepUnitInput" } } ], "responses": { "201": { "description": "Created", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/exam-prep/catalog-courses/{catalogCourseId}/units/reorder": { "put": { "tags": [ "exam-prep" ], "summary": "Reorder units within a catalog course", "parameters": [ { "type": "integer", "description": "Catalog course ID", "name": "catalogCourseId", "in": "path", "required": true }, { "description": "ordered_ids: every unit id in this catalog course, new order", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.ReorderIDsRequest" } } ], "responses": {} } }, "/api/v1/exam-prep/catalog-courses/{id}": { "get": { "produces": [ "application/json" ], "tags": [ "exam-prep" ], "summary": "Get exam-prep catalog course by ID", "parameters": [ { "type": "integer", "description": "Catalog course ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "put": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "exam-prep" ], "summary": "Update exam-prep catalog course", "parameters": [ { "type": "integer", "description": "Catalog course ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateExamPrepCatalogCourseInput" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "delete": { "tags": [ "exam-prep" ], "summary": "Delete exam-prep catalog course", "parameters": [ { "type": "integer", "description": "Catalog course ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/exam-prep/lessons/{id}": { "get": { "tags": [ "exam-prep" ], "summary": "Get exam-prep lesson by ID", "responses": {} }, "put": { "tags": [ "exam-prep" ], "summary": "Update exam-prep lesson", "responses": {} }, "delete": { "tags": [ "exam-prep" ], "summary": "Delete exam-prep lesson", "responses": {} } }, "/api/v1/exam-prep/lessons/{lessonId}/practices": { "get": { "tags": [ "exam-prep" ], "summary": "List exam-prep practices for a lesson", "parameters": [ { "type": "integer", "description": "Exam prep lesson ID", "name": "lessonId", "in": "path", "required": true }, { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": {} }, "post": { "tags": [ "exam-prep" ], "summary": "Create exam-prep practice (under a lesson; uses shared question_sets)", "parameters": [ { "type": "integer", "description": "Exam prep lesson ID (unit_module_lessons.id)", "name": "lessonId", "in": "path", "required": true }, { "description": "Practice", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateExamPrepPracticeInput" } } ], "responses": {} } }, "/api/v1/exam-prep/modules/{id}": { "get": { "tags": [ "exam-prep" ], "summary": "Get exam-prep module by ID", "responses": {} }, "put": { "tags": [ "exam-prep" ], "summary": "Update exam-prep module", "responses": {} }, "delete": { "tags": [ "exam-prep" ], "summary": "Delete exam-prep module", "responses": {} } }, "/api/v1/exam-prep/modules/{moduleId}/lessons": { "get": { "tags": [ "exam-prep" ], "summary": "List exam-prep lessons for a unit module", "parameters": [ { "type": "integer", "description": "Exam prep unit module ID", "name": "moduleId", "in": "path", "required": true }, { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": {} }, "post": { "tags": [ "exam-prep" ], "summary": "Create exam-prep lesson (under a unit module)", "parameters": [ { "type": "integer", "description": "Exam prep unit module ID", "name": "moduleId", "in": "path", "required": true }, { "description": "Lesson", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateExamPrepLessonInput" } } ], "responses": {} } }, "/api/v1/exam-prep/modules/{moduleId}/lessons/reorder": { "put": { "tags": [ "exam-prep" ], "summary": "Reorder lessons within an exam-prep unit module", "responses": {} } }, "/api/v1/exam-prep/practices/{id}": { "get": { "tags": [ "exam-prep" ], "summary": "Get exam-prep practice by ID", "parameters": [ { "type": "integer", "description": "Exam prep practice ID", "name": "id", "in": "path", "required": true } ], "responses": {} }, "put": { "tags": [ "exam-prep" ], "summary": "Update exam-prep practice", "parameters": [ { "type": "integer", "description": "Exam prep practice ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateExamPrepPracticeInput" } } ], "responses": {} }, "delete": { "tags": [ "exam-prep" ], "summary": "Delete exam-prep practice", "parameters": [ { "type": "integer", "description": "Exam prep practice ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/exam-prep/units/{id}": { "get": { "tags": [ "exam-prep" ], "summary": "Get exam-prep unit by ID", "parameters": [ { "type": "integer", "description": "Unit ID", "name": "id", "in": "path", "required": true } ], "responses": {} }, "put": { "tags": [ "exam-prep" ], "summary": "Update exam-prep unit", "parameters": [ { "type": "integer", "description": "Unit ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateExamPrepUnitInput" } } ], "responses": {} }, "delete": { "tags": [ "exam-prep" ], "summary": "Delete exam-prep unit", "parameters": [ { "type": "integer", "description": "Unit ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/exam-prep/units/{unitId}/modules": { "get": { "tags": [ "exam-prep" ], "summary": "List exam-prep modules for a unit", "parameters": [ { "type": "integer", "description": "Unit ID", "name": "unitId", "in": "path", "required": true } ], "responses": {} }, "post": { "tags": [ "exam-prep" ], "summary": "Create exam-prep module", "parameters": [ { "type": "integer", "description": "Unit ID", "name": "unitId", "in": "path", "required": true }, { "description": "Module", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateExamPrepModuleInput" } } ], "responses": {} } }, "/api/v1/exam-prep/units/{unitId}/modules/reorder": { "put": { "tags": [ "exam-prep" ], "summary": "Reorder modules within a unit", "parameters": [ { "type": "integer", "description": "Unit ID", "name": "unitId", "in": "path", "required": true }, { "description": "ordered_ids", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.ReorderIDsRequest" } } ], "responses": {} } }, "/api/v1/faqs": { "get": { "description": "Returns active FAQs for public/help center usage", "produces": [ "application/json" ], "tags": [ "faqs" ], "summary": "List published FAQs", "parameters": [ { "type": "string", "description": "Filter by category", "name": "category", "in": "query" }, { "type": "integer", "description": "Limit (default 50)", "name": "limit", "in": "query" }, { "type": "integer", "description": "Offset (default 0)", "name": "offset", "in": "query" } ], "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" } } } } }, "/api/v1/faqs/{id}": { "get": { "description": "Returns one active FAQ item", "produces": [ "application/json" ], "tags": [ "faqs" ], "summary": "Get published FAQ by ID", "parameters": [ { "type": "integer", "description": "FAQ ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/field-options": { "get": { "description": "Returns active options grouped by field_key (e.g. education_level, country)", "produces": [ "application/json" ], "tags": [ "field-options" ], "summary": "List field options for client dropdowns", "parameters": [ { "type": "string", "description": "Filter by field key", "name": "field_key", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/field-options/fields": { "get": { "description": "Returns field_key values that have options (e.g. education_level, country)", "produces": [ "application/json" ], "tags": [ "field-options" ], "summary": "List distinct field keys", "parameters": [ { "type": "boolean", "description": "If true, only keys with active options", "name": "active_only", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/files/audio": { "post": { "consumes": [ "multipart/form-data" ], "tags": [ "files" ], "summary": "Upload an audio file", "parameters": [ { "type": "file", "description": "Audio file (mp3, wav, ogg, m4a, aac, webm)", "name": "file", "in": "formData", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/files/refresh-url": { "post": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "files" ], "summary": "Refresh presigned URL for a file", "parameters": [ { "description": "reference (object key, minio://..., or existing presigned URL)", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.refreshFileURLReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/files/upload": { "post": { "consumes": [ "multipart/form-data" ], "tags": [ "files" ], "summary": "Upload media file", "parameters": [ { "type": "string", "description": "Media type: image|audio|video", "name": "media_type", "in": "formData", "required": true }, { "type": "file", "description": "Media file", "name": "file", "in": "formData", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/files/url": { "get": { "tags": [ "files" ], "summary": "Get presigned URL for a file", "parameters": [ { "type": "string", "description": "MinIO object key (e.g. profile_pictures/uuid.jpg)", "name": "key", "in": "query", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/internal/users/purge-due-deletions": { "post": { "security": [ { "Bearer": [] } ], "description": "Worker-safe purge for due self-deletion requests", "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Purge due account deletions", "parameters": [ { "type": "integer", "description": "Max users to purge in one run (default 100, max 1000)", "name": "limit", "in": "query" } ], "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" } } } } }, "/api/v1/issues": { "get": { "security": [ { "Bearer": [] } ], "description": "Returns all reported issues with pagination (admin only)", "produces": [ "application/json" ], "tags": [ "issues" ], "summary": "Get all issues", "parameters": [ { "type": "integer", "default": 20, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/handlers.issueListRes" } } } ] } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "post": { "security": [ { "Bearer": [] } ], "description": "Allows any authenticated user to report an issue they encountered", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "issues" ], "summary": "Report an issue", "parameters": [ { "description": "Issue report payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createIssueReq" } } ], "responses": { "201": { "description": "Created", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/handlers.issueRes" } } } ] } }, "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" } } } } }, "/api/v1/issues/me": { "get": { "security": [ { "Bearer": [] } ], "description": "Returns paginated issues reported by the authenticated user", "produces": [ "application/json" ], "tags": [ "issues" ], "summary": "Get my reported issues", "parameters": [ { "type": "integer", "default": 20, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/handlers.issueListRes" } } } ] } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/issues/user/{user_id}": { "get": { "security": [ { "Bearer": [] } ], "description": "Returns paginated issues reported by a specific user (admin only)", "produces": [ "application/json" ], "tags": [ "issues" ], "summary": "Get issues for a specific user", "parameters": [ { "type": "integer", "description": "User ID", "name": "user_id", "in": "path", "required": true }, { "type": "integer", "default": 20, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/handlers.issueListRes" } } } ] } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/issues/{id}": { "get": { "security": [ { "Bearer": [] } ], "description": "Returns a single issue report by its ID (admin only)", "produces": [ "application/json" ], "tags": [ "issues" ], "summary": "Get issue by ID", "parameters": [ { "type": "integer", "description": "Issue ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/handlers.issueRes" } } } ] } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "delete": { "security": [ { "Bearer": [] } ], "description": "Deletes an issue report (admin only)", "produces": [ "application/json" ], "tags": [ "issues" ], "summary": "Delete an issue", "parameters": [ { "type": "integer", "description": "Issue ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/issues/{id}/status": { "patch": { "security": [ { "Bearer": [] } ], "description": "Updates the status of an issue (admin only)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "issues" ], "summary": "Update issue status", "parameters": [ { "type": "integer", "description": "Issue ID", "name": "id", "in": "path", "required": true }, { "description": "Status update payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateIssueStatusReq" } } ], "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" } } } } }, "/api/v1/lessons/{id}": { "get": { "tags": [ "lessons" ], "parameters": [ { "type": "integer", "description": "Lesson ID", "name": "id", "in": "path", "required": true } ], "responses": {} }, "put": { "tags": [ "lessons" ], "parameters": [ { "type": "integer", "description": "Lesson ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateLessonInput" } } ], "responses": {} }, "delete": { "tags": [ "lessons" ], "parameters": [ { "type": "integer", "description": "Lesson ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/lessons/{id}/complete": { "post": { "description": "Records lesson completion; may cascade to module, course, and program progress for the authenticated user. Learners must meet sequential prerequisites; staff bypass checks.", "tags": [ "lessons" ], "summary": "Mark a lesson as completed", "parameters": [ { "type": "integer", "description": "Lesson ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "403": { "description": "Forbidden", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/lessons/{id}/practices": { "get": { "tags": [ "practices" ], "parameters": [ { "type": "integer", "description": "Lesson ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/lms/progress": { "get": { "description": "Returns practice-based completed lesson, module, course, and program IDs for the authenticated user (ordered by completion time, then id).", "produces": [ "application/json" ], "tags": [ "lms" ], "summary": "Get my LMS completion history", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/lms/progress-summary": { "get": { "description": "Returns the learner's nested LMS hierarchy with the same access progress data exposed on the individual program, course, module, and lesson APIs.", "produces": [ "application/json" ], "tags": [ "lms" ], "summary": "Get my LMS progress summary", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/logs": { "get": { "description": "Fetches application logs from MongoDB with pagination, level filtering, and search", "produces": [ "application/json" ], "tags": [ "Logs" ], "summary": "Retrieve application logs with filtering and pagination", "parameters": [ { "type": "string", "description": "Filter logs by level (debug, info, warn, error, dpanic, panic, fatal)", "name": "level", "in": "query" }, { "type": "string", "description": "Search term to match against message or fields", "name": "search", "in": "query" }, { "type": "integer", "default": 1, "description": "Page number for pagination (default: 1)", "name": "page", "in": "query" }, { "type": "integer", "default": 50, "description": "Number of items per page (default: 50, max: 100)", "name": "limit", "in": "query" } ], "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" } } } } }, "/api/v1/modules/{id}": { "get": { "tags": [ "modules" ], "parameters": [ { "type": "integer", "description": "Module ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } }, "put": { "tags": [ "modules" ], "parameters": [ { "type": "integer", "description": "Module ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateModuleInput" } } ], "responses": {} }, "delete": { "tags": [ "modules" ], "parameters": [ { "type": "integer", "description": "Module ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/modules/{id}/practices": { "get": { "tags": [ "practices" ], "parameters": [ { "type": "integer", "description": "Module ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/modules/{moduleId}/lessons": { "get": { "tags": [ "lessons" ], "parameters": [ { "type": "integer", "description": "Module ID", "name": "moduleId", "in": "path", "required": true }, { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": {} }, "post": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "lessons" ], "summary": "Create lesson", "parameters": [ { "type": "integer", "description": "Module ID", "name": "moduleId", "in": "path", "required": true }, { "description": "Lesson", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateLessonInput" } } ], "responses": {} } }, "/api/v1/notifications/bulk-email": { "post": { "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).", "consumes": [ "multipart/form-data" ], "produces": [ "application/json" ], "tags": [ "notifications" ], "summary": "Send bulk email", "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" } } } } }, "/api/v1/notifications/bulk-push": { "post": { "description": "Sends a push notification to specified user IDs or all users matching a role. Optionally schedule for later with scheduled_at (RFC3339).", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "notifications" ], "summary": "Send bulk push notification", "parameters": [ { "description": "Bulk push content", "name": "body", "in": "body", "required": true, "schema": { "type": "object", "properties": { "image": { "type": "string" }, "message": { "type": "string" }, "role": { "type": "string" }, "scheduled_at": { "type": "string" }, "title": { "type": "string" }, "user_ids": { "type": "array", "items": { "type": "integer", "format": "int64" } } } } } ], "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" } } } } }, "/api/v1/notifications/bulk-sms": { "post": { "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).", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "notifications" ], "summary": "Send bulk SMS", "parameters": [ { "description": "Bulk SMS content", "name": "body", "in": "body", "required": true, "schema": { "type": "object", "properties": { "message": { "type": "string" }, "phone_numbers": { "type": "array", "items": { "type": "string" } }, "role": { "type": "string" }, "scheduled_at": { "type": "string" }, "user_ids": { "type": "array", "items": { "type": "integer", "format": "int64" } } } } } ], "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" } } } } }, "/api/v1/notifications/scheduled": { "get": { "description": "Returns paginated scheduled notifications with optional status, channel, and date filters", "produces": [ "application/json" ], "tags": [ "notifications" ], "summary": "List scheduled notifications", "parameters": [ { "type": "string", "description": "Filter by status", "name": "status", "in": "query" }, { "type": "string", "description": "Filter by channel", "name": "channel", "in": "query" }, { "type": "string", "description": "Filter after date (RFC3339)", "name": "after", "in": "query" }, { "type": "string", "description": "Filter before date (RFC3339)", "name": "before", "in": "query" }, { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 1, "description": "Page number", "name": "page", "in": "query" } ], "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" } } } } }, "/api/v1/notifications/scheduled/{id}": { "get": { "description": "Returns a single scheduled notification by its ID", "produces": [ "application/json" ], "tags": [ "notifications" ], "summary": "Get scheduled notification", "parameters": [ { "type": "integer", "description": "Scheduled Notification ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/notifications/scheduled/{id}/cancel": { "post": { "description": "Cancels a scheduled notification if it is still pending or processing", "produces": [ "application/json" ], "tags": [ "notifications" ], "summary": "Cancel scheduled notification", "parameters": [ { "type": "integer", "description": "Scheduled Notification ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/notifications/send-email": { "post": { "description": "Sends an email to a single email address with optional image attachment", "consumes": [ "multipart/form-data" ], "produces": [ "application/json" ], "tags": [ "notifications" ], "summary": "Send single email", "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" } } } } }, "/api/v1/notifications/test-push": { "post": { "description": "Sends a test push notification to all registered devices of the current user", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "notifications" ], "summary": "Send test push notification", "parameters": [ { "description": "Test notification content", "name": "body", "in": "body", "required": true, "schema": { "type": "object", "properties": { "message": { "type": "string" }, "title": { "type": "string" } } } } ], "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" } } } } }, "/api/v1/payments": { "get": { "description": "Returns the authenticated user's payment history", "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Get payment history", "parameters": [ { "type": "integer", "default": 20, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/payments/arifpay/success": { "get": { "description": "Displays the Yimaru Academy success page after ArifPay redirects the learner back to the backend.", "produces": [ "text/html" ], "tags": [ "payments" ], "summary": "ArifPay payment success page", "parameters": [ { "type": "string", "description": "ArifPay session identifier", "name": "session_id", "in": "query" }, { "type": "string", "description": "ArifPay session identifier", "name": "sessionId", "in": "query" }, { "type": "string", "description": "Fallback payment nonce", "name": "nonce", "in": "query" } ], "responses": { "200": { "description": "HTML success page", "schema": { "type": "string" } } } } }, "/api/v1/payments/chapa/callback": { "get": { "description": "Verifies payment after Chapa redirects to callback_url", "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Chapa payment callback", "parameters": [ { "type": "string", "description": "Transaction reference", "name": "trx_ref", "in": "query" }, { "type": "string", "description": "Chapa reference ID", "name": "ref_id", "in": "query" }, { "type": "string", "description": "Payment status", "name": "status", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/payments/direct": { "post": { "description": "Creates a payment session and initiates direct payment (OTP-based)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Initiate direct payment", "parameters": [ { "description": "Direct payment request", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.initiateDirectPaymentReq" } } ], "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" } } } } }, "/api/v1/payments/direct/methods": { "get": { "description": "Returns list of payment methods that support direct payment (OTP-based)", "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Get direct payment methods", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/payments/direct/verify-otp": { "post": { "description": "Verifies the OTP sent for direct payment methods (Amole, HelloCash, etc.)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Verify OTP for direct payment", "parameters": [ { "description": "OTP verification request", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.verifyOTPReq" } } ], "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" } } } } }, "/api/v1/payments/methods": { "get": { "description": "Returns payment methods available on Chapa checkout", "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Get Chapa payment methods", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/payments/subscribe": { "post": { "description": "Creates a payment session for a subscription plan", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Initiate subscription payment", "parameters": [ { "description": "Payment request", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.initiatePaymentReq" } } ], "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" } } } } }, "/api/v1/payments/verify/{session_id}": { "get": { "description": "Checks the payment status with the payment provider", "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Verify payment status", "parameters": [ { "type": "string", "description": "Session ID", "name": "session_id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/payments/webhook": { "post": { "description": "Processes payment notifications from Chapa (charge.success, etc.)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Handle Chapa webhook", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/payments/{id}": { "get": { "description": "Returns details of a specific payment", "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Get payment details", "parameters": [ { "type": "integer", "description": "Payment ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/payments/{id}/cancel": { "post": { "description": "Cancels a payment that is still pending", "produces": [ "application/json" ], "tags": [ "payments" ], "summary": "Cancel a pending payment", "parameters": [ { "type": "integer", "description": "Payment ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/personas": { "get": { "tags": [ "personas" ], "summary": "List LMS personas (catalog for practice assignment)", "parameters": [ { "type": "boolean", "default": true, "description": "When true (default), return only active personas", "name": "active_only", "in": "query" }, { "type": "integer", "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "description": "Offset", "name": "offset", "in": "query" } ], "responses": {} }, "post": { "consumes": [ "application/json" ], "tags": [ "personas" ], "summary": "Create LMS persona catalog entry", "parameters": [ { "description": "Persona", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateLmsPersonaInput" } } ], "responses": { "201": { "description": "Created", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/personas/{id}": { "get": { "tags": [ "personas" ], "summary": "Get LMS persona by ID", "parameters": [ { "type": "integer", "description": "Persona ID", "name": "id", "in": "path", "required": true } ], "responses": {} }, "put": { "tags": [ "personas" ], "summary": "Update LMS persona", "parameters": [ { "type": "integer", "description": "Persona ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateLmsPersonaInput" } } ], "responses": {} }, "delete": { "tags": [ "personas" ], "summary": "Delete LMS persona (practices referencing it will have persona_id cleared)", "parameters": [ { "type": "integer", "description": "Persona ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/practices": { "post": { "consumes": [ "application/json" ], "tags": [ "practices" ], "parameters": [ { "description": "Practice (parent_kind: COURSE | MODULE | LESSON)", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreatePracticeInput" } } ], "responses": {} } }, "/api/v1/practices/{id}": { "get": { "tags": [ "practices" ], "parameters": [ { "type": "integer", "description": "Practice ID", "name": "id", "in": "path", "required": true } ], "responses": {} }, "put": { "tags": [ "practices" ], "parameters": [ { "type": "integer", "description": "Practice ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update (parent is immutable)", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdatePracticeInput" } } ], "responses": {} }, "delete": { "tags": [ "practices" ], "parameters": [ { "type": "integer", "description": "Practice ID", "name": "id", "in": "path", "required": true } ], "responses": {} } }, "/api/v1/practices/{practiceId}/questions": { "get": { "description": "Returns paginated questions for a practice(question-set), including AUDIO fields", "produces": [ "application/json" ], "tags": [ "question-set-items" ], "summary": "Get questions by practice", "parameters": [ { "type": "integer", "description": "Practice(question-set) ID", "name": "practiceId", "in": "path", "required": true }, { "type": "string", "description": "Question type filter (e.g. AUDIO)", "name": "question_type", "in": "query" }, { "type": "integer", "default": 10, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "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" } } } } }, "/api/v1/programs": { "get": { "description": "Paginated list of programs", "produces": [ "application/json" ], "tags": [ "programs" ], "summary": "List programs", "parameters": [ { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "post": { "description": "Create a top-level LMS program. Optional sort_order inserts at that global ordering; omit it to append after the current highest sort_order. Unique constraint applies to sort_order.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "programs" ], "summary": "Create program", "parameters": [ { "description": "Program", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateProgramInput" } } ], "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" } } } } }, "/api/v1/programs/reorder": { "put": { "description": "Sets learning order of programs. Body must list every current program id exactly once, in the desired order (index 0 = first in path).", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "programs" ], "summary": "Reorder all programs", "parameters": [ { "description": "New order: ordered_ids is the full set of program ids", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.ReorderIDsRequest" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/programs/{id}": { "get": { "produces": [ "application/json" ], "tags": [ "programs" ], "summary": "Get program by ID", "parameters": [ { "type": "integer", "description": "Program ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "put": { "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "programs" ], "summary": "Update program", "parameters": [ { "type": "integer", "description": "Program ID", "name": "id", "in": "path", "required": true }, { "description": "Fields to update", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateProgramInput" } } ], "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" } } } }, "delete": { "tags": [ "programs" ], "summary": "Delete program", "parameters": [ { "type": "integer", "description": "Program ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/programs/{id}/courses": { "get": { "produces": [ "application/json" ], "tags": [ "courses" ], "summary": "List courses by program", "parameters": [ { "type": "integer", "description": "Program ID", "name": "id", "in": "path", "required": true }, { "type": "integer", "default": 20, "description": "Page size", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "post": { "description": "Create a course under a program. Optional sort_order assigns position within that program (siblings shifted); omit to append after the current highest sort_order in the program.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "courses" ], "summary": "Create course", "parameters": [ { "type": "integer", "description": "Program ID", "name": "id", "in": "path", "required": true }, { "description": "Course", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateCourseInput" } } ], "responses": { "201": { "description": "Created", "schema": { "$ref": "#/definitions/domain.Response" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/programs/{id}/courses/reorder": { "put": { "tags": [ "courses" ], "summary": "Reorder courses within a program", "parameters": [ { "type": "integer", "description": "Program ID", "name": "id", "in": "path", "required": true }, { "description": "ordered_ids: every course id in this program, in the new order", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.ReorderIDsRequest" } } ], "responses": {} } }, "/api/v1/progress/practices/{id}/complete": { "post": { "description": "Marks a practice question set as completed for the authenticated learner", "produces": [ "application/json" ], "tags": [ "progression" ], "summary": "Mark practice as completed", "parameters": [ { "type": "integer", "description": "Practice Question Set ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/question-sets": { "get": { "description": "Returns a paginated list of question sets filtered by type", "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Get question sets by type", "parameters": [ { "type": "string", "description": "Set type (PRACTICE, INITIAL_ASSESSMENT, QUIZ, EXAM, SURVEY, CAPSTONE)", "name": "set_type", "in": "query", "required": true }, { "type": "integer", "default": 10, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "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" } } } }, "post": { "description": "Creates a new question set (practice, assessment, quiz, exam, or survey)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Create a new question set", "parameters": [ { "description": "Create question set payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createQuestionSetReq" } } ], "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" } } } } }, "/api/v1/question-sets/by-owner": { "get": { "description": "Returns question sets for a specific owner (e.g., sub-course)", "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Get question sets by owner", "parameters": [ { "type": "string", "description": "Owner type (SUB_COURSE, COURSE, CATEGORY, STANDALONE)", "name": "owner_type", "in": "query", "required": true }, { "type": "integer", "description": "Owner ID", "name": "owner_id", "in": "query", "required": true } ], "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" } } } } }, "/api/v1/question-sets/{id}": { "get": { "description": "Returns a question set with question count", "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Get question set by ID", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "id", "in": "path", "required": true } ], "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" } } } }, "put": { "description": "Updates a question set's properties", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Update a question set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "id", "in": "path", "required": true }, { "description": "Update question set payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateQuestionSetReq" } } ], "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" } } } }, "delete": { "description": "Archives a question set (soft delete)", "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Delete a question set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/question-sets/{setId}/personas": { "get": { "description": "Returns all users assigned as personas to a question set (practice)", "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Get user personas for a question set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "setId", "in": "path", "required": true } ], "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" } } } }, "post": { "description": "Links a user as a persona to a question set (practice)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Add a user as persona to a question set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "setId", "in": "path", "required": true }, { "description": "Add user persona payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.addUserPersonaReq" } } ], "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" } } } } }, "/api/v1/question-sets/{setId}/personas/{userId}": { "delete": { "description": "Unlinks a user as persona from a question set (practice)", "produces": [ "application/json" ], "tags": [ "question-sets" ], "summary": "Remove a user persona from a question set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "setId", "in": "path", "required": true }, { "type": "integer", "description": "User ID", "name": "userId", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/question-sets/{setId}/questions": { "get": { "description": "Returns all questions in a question set with details", "produces": [ "application/json" ], "tags": [ "question-set-items" ], "summary": "Get questions in set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "setId", "in": "path", "required": true } ], "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" } } } }, "post": { "description": "Links a question to a question set", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "question-set-items" ], "summary": "Add question to set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "setId", "in": "path", "required": true }, { "description": "Add question to set payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.addQuestionToSetReq" } } ], "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" } } } } }, "/api/v1/question-sets/{setId}/questions/{questionId}": { "delete": { "description": "Unlinks a question from a question set", "produces": [ "application/json" ], "tags": [ "question-set-items" ], "summary": "Remove question from set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "setId", "in": "path", "required": true }, { "type": "integer", "description": "Question ID", "name": "questionId", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/question-sets/{setId}/questions/{questionId}/order": { "put": { "description": "Updates the display order of a question in a set", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "question-set-items" ], "summary": "Update question order in set", "parameters": [ { "type": "integer", "description": "Question Set ID", "name": "setId", "in": "path", "required": true }, { "type": "integer", "description": "Question ID", "name": "questionId", "in": "path", "required": true }, { "description": "Update order payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateQuestionOrderReq" } } ], "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" } } } } }, "/api/v1/questions": { "get": { "description": "Returns a paginated list of questions with optional filters", "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "List questions", "parameters": [ { "type": "string", "description": "Question type filter (MCQ, TRUE_FALSE, SHORT_ANSWER)", "name": "question_type", "in": "query" }, { "type": "string", "description": "Difficulty level filter (EASY, MEDIUM, HARD)", "name": "difficulty", "in": "query" }, { "type": "string", "description": "Status filter (DRAFT, PUBLISHED, INACTIVE)", "name": "status", "in": "query" }, { "type": "integer", "default": 10, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "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" } } } }, "post": { "description": "Creates a new question with options (for MCQ/TRUE_FALSE) or short answers (for SHORT_ANSWER). Supports question_type_definition_id for dynamic builder-linked questions.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Create a new question", "parameters": [ { "description": "Create question payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createQuestionReq" } } ], "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" } } } } }, "/api/v1/questions/audio-answer": { "post": { "consumes": [ "multipart/form-data" ], "tags": [ "questions" ], "summary": "Submit audio answer for a question", "parameters": [ { "type": "integer", "description": "Question ID", "name": "question_id", "in": "formData", "required": true }, { "type": "integer", "description": "Question Set ID", "name": "question_set_id", "in": "formData", "required": true }, { "type": "file", "description": "Audio recording", "name": "file", "in": "formData", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/questions/component-catalog": { "get": { "description": "Valid stimulus and response component kind codes for dynamic question-type definitions", "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Question-type builder component catalog", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/questions/search": { "get": { "description": "Search questions by text", "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Search questions", "parameters": [ { "type": "string", "description": "Search query", "name": "q", "in": "query", "required": true }, { "type": "integer", "default": 10, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "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" } } } } }, "/api/v1/questions/type-definitions": { "get": { "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "List reusable question-type definitions", "parameters": [ { "type": "string", "description": "Filter by status (ACTIVE, INACTIVE)", "name": "status", "in": "query" }, { "type": "boolean", "description": "Include system seeded definitions", "name": "include_system", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "post": { "description": "Stores a reusable dynamic question-type definition for future question construction. Only runtime-mappable definitions are persisted.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Create reusable question-type definition", "parameters": [ { "description": "Question type definition payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createQuestionTypeDefinitionReq" } } ], "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" } } } } }, "/api/v1/questions/type-definitions/{id}": { "get": { "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Get reusable question-type definition by id", "parameters": [ { "type": "integer", "description": "Question type definition id", "name": "id", "in": "path", "required": true } ], "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" } } } }, "put": { "description": "Updates a reusable dynamic question-type definition. Updated definitions must remain runtime-mappable.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Update reusable question-type definition", "parameters": [ { "type": "integer", "description": "Question type definition id", "name": "id", "in": "path", "required": true }, { "description": "Update question type definition payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateQuestionTypeDefinitionReq" } } ], "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" } } } }, "delete": { "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Delete reusable question-type definition", "parameters": [ { "type": "integer", "description": "Question type definition id", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/questions/validate-question-type-definition": { "post": { "description": "Validates selected stimulus and response component kinds for temporary question-type definitions (component-level validation only)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Validate dynamic question-type definition", "parameters": [ { "description": "Stimulus and response component kinds", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.validateQuestionTypeDefinitionReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/questions/{id}": { "get": { "description": "Returns a question with its options/short answers", "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Get question by ID", "parameters": [ { "type": "integer", "description": "Question ID", "name": "id", "in": "path", "required": true } ], "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" } } } }, "put": { "description": "Updates a question and optionally replaces its options/short answers. Supports question_type_definition_id for dynamic builder-linked questions.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Update a question", "parameters": [ { "type": "integer", "description": "Question ID", "name": "id", "in": "path", "required": true }, { "description": "Update question payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateQuestionReq" } } ], "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" } } } }, "delete": { "description": "Archives a question (soft delete)", "produces": [ "application/json" ], "tags": [ "questions" ], "summary": "Delete a question", "parameters": [ { "type": "integer", "description": "Question ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/ratings": { "get": { "description": "Returns paginated ratings for a specific target", "produces": [ "application/json" ], "tags": [ "ratings" ], "summary": "Get ratings for a target", "parameters": [ { "type": "string", "description": "Target type (app, course, sub_course)", "name": "target_type", "in": "query", "required": true }, { "type": "integer", "description": "Target ID (0 for app)", "name": "target_id", "in": "query", "required": true }, { "type": "integer", "description": "Limit (default 20)", "name": "limit", "in": "query" }, { "type": "integer", "description": "Offset (default 0)", "name": "offset", "in": "query" } ], "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" } } } }, "post": { "description": "Submit a rating for an app, course, or sub-course", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "ratings" ], "summary": "Submit a rating", "parameters": [ { "description": "Submit rating payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.submitRatingReq" } } ], "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" } } } } }, "/api/v1/ratings/me": { "get": { "description": "Returns the current user's rating for a specific target", "produces": [ "application/json" ], "tags": [ "ratings" ], "summary": "Get my rating for a target", "parameters": [ { "type": "string", "description": "Target type (app, course, sub_course)", "name": "target_type", "in": "query", "required": true }, { "type": "integer", "description": "Target ID (0 for app)", "name": "target_id", "in": "query", "required": true } ], "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" } } } } }, "/api/v1/ratings/me/all": { "get": { "description": "Returns all ratings submitted by the current user", "produces": [ "application/json" ], "tags": [ "ratings" ], "summary": "Get all my ratings", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/ratings/summary": { "get": { "description": "Returns the total count and average stars for a specific target", "produces": [ "application/json" ], "tags": [ "ratings" ], "summary": "Get rating summary for a target", "parameters": [ { "type": "string", "description": "Target type (app, course, sub_course)", "name": "target_type", "in": "query", "required": true }, { "type": "integer", "description": "Target ID (0 for app)", "name": "target_id", "in": "query", "required": true } ], "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" } } } } }, "/api/v1/ratings/{id}": { "delete": { "description": "Deletes a rating by ID for the current user", "produces": [ "application/json" ], "tags": [ "ratings" ], "summary": "Delete a rating", "parameters": [ { "type": "integer", "description": "Rating ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/rbac/permissions": { "get": { "security": [ { "Bearer": [] } ], "description": "Get all permissions in the system grouped by group name", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "List all permissions", "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/definitions/domain.Permission" } } } } ] } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/rbac/permissions/groups": { "get": { "security": [ { "Bearer": [] } ], "description": "Get all distinct permission group names", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "List permission groups", "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "type": "string" } } } } ] } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/rbac/permissions/sync": { "post": { "security": [ { "Bearer": [] } ], "description": "Re-seed permissions from code and reload the RBAC cache", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "Sync permissions", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/rbac/roles": { "get": { "security": [ { "Bearer": [] } ], "description": "Get all roles with optional filters", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "List all roles", "parameters": [ { "type": "string", "description": "Search by role name", "name": "query", "in": "query" }, { "type": "boolean", "description": "Filter by system role (true/false)", "name": "is_system", "in": "query" }, { "type": "integer", "description": "Page number (default: 1)", "name": "page", "in": "query" }, { "type": "integer", "description": "Page size (default: 20)", "name": "page_size", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "post": { "security": [ { "Bearer": [] } ], "description": "Create a new role with a name and description", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "Create a new role", "parameters": [ { "description": "Role creation payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateRoleReq" } } ], "responses": { "201": { "description": "Created", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/domain.RoleRecord" } } } ] } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/rbac/roles/{id}": { "get": { "security": [ { "Bearer": [] } ], "description": "Get a role and its permissions by ID", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "Get a role by ID", "parameters": [ { "type": "integer", "description": "Role ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/domain.RoleWithPermissions" } } } ] } }, "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" } } } }, "put": { "security": [ { "Bearer": [] } ], "description": "Update an existing role's name and description", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "Update a role", "parameters": [ { "type": "integer", "description": "Role ID", "name": "id", "in": "path", "required": true }, { "description": "Role update payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateRoleReq" } } ], "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" } } } }, "delete": { "security": [ { "Bearer": [] } ], "description": "Delete a non-system role by ID", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "Delete a role", "parameters": [ { "type": "integer", "description": "Role ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/rbac/roles/{id}/permissions": { "get": { "security": [ { "Bearer": [] } ], "description": "Get all permissions assigned to a role", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "Get permissions for a role", "parameters": [ { "type": "integer", "description": "Role ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/definitions/domain.Permission" } } } } ] } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "put": { "security": [ { "Bearer": [] } ], "description": "Replace all permissions for a role with the given permission IDs", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "rbac" ], "summary": "Set permissions for a role", "parameters": [ { "type": "integer", "description": "Role ID", "name": "id", "in": "path", "required": true }, { "description": "Permission IDs payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.SetRolePermissionsReq" } } ], "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" } } } } }, "/api/v1/sendSMS": { "post": { "description": "Sends an SMS message to a single phone number using AfroMessage", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Send single SMS via AfroMessage", "parameters": [ { "description": "Send SMS request", "name": "sendSMS", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.SendSingleAfroSMSReq" } } ], "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" } } } } }, "/api/v1/subscription-plans": { "get": { "description": "Returns all subscription plans", "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "List subscription plans", "parameters": [ { "type": "boolean", "description": "Return only active plans", "name": "active_only", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "post": { "description": "Creates a new subscription plan (admin only)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Create a subscription plan", "parameters": [ { "description": "Create plan payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.createPlanReq" } } ], "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" } } } } }, "/api/v1/subscription-plans/{id}": { "get": { "description": "Returns a single subscription plan by ID", "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Get a subscription plan", "parameters": [ { "type": "integer", "description": "Plan ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } }, "put": { "description": "Updates a subscription plan (admin only)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Update a subscription plan", "parameters": [ { "type": "integer", "description": "Plan ID", "name": "id", "in": "path", "required": true }, { "description": "Update plan payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updatePlanReq" } } ], "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" } } } }, "delete": { "description": "Deletes a subscription plan (admin only)", "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Delete a subscription plan", "parameters": [ { "type": "integer", "description": "Plan ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/subscriptions": { "post": { "description": "Creates a new subscription for the authenticated user. For regular users, use /payments/subscribe instead.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Subscribe to a plan (Admin only - bypasses payment)", "deprecated": true, "parameters": [ { "description": "Subscribe payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.subscribeReq" } } ], "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" } } } } }, "/api/v1/subscriptions/checkout": { "post": { "description": "Initiates payment for a subscription plan. Returns payment URL for checkout.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Subscribe to a plan with payment", "parameters": [ { "description": "Subscribe with payment payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.subscribeWithPaymentReq" } } ], "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" } } } } }, "/api/v1/subscriptions/history": { "get": { "description": "Returns the authenticated user's subscription history", "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Get subscription history", "parameters": [ { "type": "integer", "default": 20, "description": "Limit", "name": "limit", "in": "query" }, { "type": "integer", "default": 0, "description": "Offset", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/subscriptions/me": { "get": { "description": "Returns the authenticated user's active subscription", "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Get current subscription", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "404": { "description": "Not Found", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/subscriptions/status": { "get": { "description": "Returns whether the authenticated user has an active subscription", "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Check subscription status", "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/subscriptions/{id}/auto-renew": { "put": { "description": "Enables or disables auto-renewal for a subscription", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Set auto-renew", "parameters": [ { "type": "integer", "description": "Subscription ID", "name": "id", "in": "path", "required": true }, { "description": "Auto-renew payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.autoRenewReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/subscriptions/{id}/cancel": { "post": { "description": "Cancels the user's subscription", "produces": [ "application/json" ], "tags": [ "subscriptions" ], "summary": "Cancel subscription", "parameters": [ { "type": "integer", "description": "Subscription ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/super-login": { "post": { "description": "Login super-admin", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Login super-admin", "parameters": [ { "description": "Login super-admin", "name": "login", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.LoginRequest" } } ], "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" } } } } }, "/api/v1/t-approver/{id}": { "get": { "description": "Get a single admin by id", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "admin" ], "summary": "Get admin by id", "parameters": [ { "type": "integer", "description": "User ID", "name": "id", "in": "path", "required": true } ], "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" } } } }, "put": { "description": "Update Admin", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "admin" ], "summary": "Update Admin", "parameters": [ { "description": "Update Admin", "name": "admin", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.updateAdminReq" } } ], "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" } } } } }, "/api/v1/team/invitations": { "get": { "description": "Lists team member invitations with optional status filter", "produces": [ "application/json" ], "tags": [ "team" ], "summary": "List team invitations", "parameters": [ { "type": "string", "description": "pending, accepted, expired, or revoked", "name": "status", "in": "query" }, { "type": "integer", "description": "Limit (default 20)", "name": "limit", "in": "query" }, { "type": "integer", "description": "Offset (default 0)", "name": "offset", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/team/invitations/accept": { "post": { "description": "Public endpoint to set password and profile details after following the invite link", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Accept team invitation and complete account setup", "parameters": [ { "description": "Accept invitation payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.AcceptTeamInvitationReq" } } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/team/invitations/verify": { "get": { "description": "Public endpoint used by the admin panel accept-invite page", "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Verify team invitation token", "parameters": [ { "type": "string", "description": "Invitation token", "name": "token", "in": "query", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/team/invitations/{id}/revoke": { "post": { "description": "Revokes the invitation and removes the pending team member if not yet accepted", "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Revoke a pending team invitation", "parameters": [ { "type": "integer", "description": "Invitation ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } } } } }, "/api/v1/team/login": { "post": { "description": "Authenticate a team member (internal staff) with email and password", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Login team member", "parameters": [ { "description": "Team member login credentials", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.TeamMemberLoginReq" } } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/handlers.teamMemberLoginRes" } } } ] } }, "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" } } } } }, "/api/v1/team/me": { "get": { "security": [ { "Bearer": [] } ], "description": "Get the authenticated team member's own profile", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Get my team profile", "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/domain.TeamMemberResponse" } } } ] } }, "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" } } } } }, "/api/v1/team/members": { "get": { "security": [ { "Bearer": [] } ], "description": "Get a paginated list of team members with optional filtering", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "List all team members", "parameters": [ { "type": "string", "description": "Filter by team role (super_admin, admin, content_manager, support_agent, instructor, finance, hr, analyst)", "name": "team_role", "in": "query" }, { "type": "string", "description": "Filter by department", "name": "department", "in": "query" }, { "type": "string", "description": "Filter by status (active, inactive, suspended, terminated)", "name": "status", "in": "query" }, { "type": "string", "description": "Search by name, email, or phone number", "name": "search", "in": "query" }, { "type": "integer", "description": "Page number (default: 1)", "name": "page", "in": "query" }, { "type": "integer", "description": "Items per page (default: 10, max: 100)", "name": "page_size", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/definitions/domain.TeamMemberResponse" } }, "metadata": { "$ref": "#/definitions/domain.Pagination" } } } ] } }, "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" } } } }, "post": { "security": [ { "Bearer": [] } ], "description": "Create a new internal team member (admin only)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Create a new team member", "parameters": [ { "description": "Team member creation payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.CreateTeamMemberReq" } } ], "responses": { "201": { "description": "Created", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/domain.TeamMemberResponse" } } } ] } }, "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" } } } } }, "/api/v1/team/members/invite": { "post": { "description": "Creates a pending team member (email + team_role only) and sends an invitation email; profile is completed on accept", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Invite a team member by email", "parameters": [ { "description": "Invite payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.InviteTeamMemberReq" } } ], "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" } } } } }, "/api/v1/team/members/{id}": { "get": { "security": [ { "Bearer": [] } ], "description": "Retrieve a team member's details by their ID", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Get team member by ID", "parameters": [ { "type": "integer", "description": "Team Member ID", "name": "id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/domain.TeamMemberResponse" } } } ] } }, "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" } } } }, "put": { "security": [ { "Bearer": [] } ], "description": "Update an existing team member's details (admin only)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Update team member", "parameters": [ { "type": "integer", "description": "Team Member ID", "name": "id", "in": "path", "required": true }, { "description": "Team member update payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateTeamMemberReq" } } ], "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" } } } }, "delete": { "security": [ { "Bearer": [] } ], "description": "Delete a team member (super admin only)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Delete team member", "parameters": [ { "type": "integer", "description": "Team Member ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/team/members/{id}/change-password": { "post": { "security": [ { "Bearer": [] } ], "description": "Change a team member's password (requires current password)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Change team member password", "parameters": [ { "type": "integer", "description": "Team Member ID", "name": "id", "in": "path", "required": true }, { "description": "Password change payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.changePasswordReq" } } ], "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" } } } } }, "/api/v1/team/members/{id}/resend-invite": { "post": { "description": "Revokes the current pending invite and sends a new invitation email", "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Resend team invitation", "parameters": [ { "type": "integer", "description": "Team member ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/team/members/{id}/status": { "patch": { "security": [ { "Bearer": [] } ], "description": "Update a team member's status (active, inactive, suspended, terminated)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Update team member status", "parameters": [ { "type": "integer", "description": "Team Member ID", "name": "id", "in": "path", "required": true }, { "description": "Status update payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateTeamMemberStatusReq" } } ], "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" } } } } }, "/api/v1/team/refresh": { "post": { "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).", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Refresh team member tokens", "parameters": [ { "description": "Current refresh token", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.teamMemberRefreshReq" } } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/handlers.teamMemberLoginRes" } } } ] } }, "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" } } } } }, "/api/v1/team/stats": { "get": { "security": [ { "Bearer": [] } ], "description": "Get statistics about team members by status", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "team" ], "summary": "Get team member statistics", "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/domain.TeamMemberStats" } } } ] } }, "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" } } } } }, "/api/v1/tenant": { "get": { "description": "Check if phone number or email exist", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Check if phone number or email exist", "parameters": [ { "description": "Check phone number or email exist", "name": "checkPhoneEmailExist", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.CheckPhoneEmailExistReq" } } ], "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" } } } } }, "/api/v1/user": { "put": { "description": "Updates user profile information (partial updates supported)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Update user profile", "parameters": [ { "type": "integer", "description": "User ID", "name": "user_id", "in": "path", "required": true }, { "description": "Update user payload", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateUserReq" } } ], "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" } } } } }, "/api/v1/user/delete/{id}": { "delete": { "description": "Delete a user by their ID", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Delete user by ID", "parameters": [ { "type": "integer", "description": "User ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/user/me": { "delete": { "security": [ { "Bearer": [] } ], "description": "Starts account deletion with grace period before permanent purge", "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Request deletion of my account", "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" } } } } }, "/api/v1/user/me/deletion/cancel": { "post": { "security": [ { "Bearer": [] } ], "description": "Cancels a pending self-deletion request during grace period", "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Cancel my account deletion request", "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" } } } } }, "/api/v1/user/resetPassword": { "post": { "description": "Reset password", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Reset password", "parameters": [ { "description": "Reset password", "name": "resetPassword", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.ResetPasswordReq" } } ], "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" } } } } }, "/api/v1/user/search": { "post": { "description": "Search for user using name or phone", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Search for user using name or phone", "parameters": [ { "description": "Search for using his name or phone", "name": "searchUserByNameOrPhone", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.SearchUserByNameOrPhoneReq" } } ], "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" } } } } }, "/api/v1/user/sendResetCode": { "post": { "description": "Send reset code", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Send reset code", "parameters": [ { "description": "Send reset code", "name": "resetCode", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.ResetCodeReq" } } ], "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" } } } } }, "/api/v1/user/single/{id}": { "get": { "description": "Get a single user by id", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Get user by id", "parameters": [ { "type": "integer", "description": "User ID", "name": "id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/user/status": { "patch": { "description": "Activates, deactivates, or suspends a user account", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Update user status", "parameters": [ { "description": "Status update payload", "name": "body", "in": "body", "required": true, "schema": { "type": "object" } } ], "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" } } } } }, "/api/v1/user/verify-otp": { "post": { "description": "Verify OTP for registration or other actions", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Verify OTP", "parameters": [ { "description": "Verify OTP", "name": "verifyOtp", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.VerifyOtpReq" } } ], "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" } } } } }, "/api/v1/user/{id}/profile-picture": { "post": { "security": [ { "Bearer": [] } ], "description": "Uploads a profile picture for the specified user", "consumes": [ "multipart/form-data" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Upload profile picture", "parameters": [ { "type": "integer", "description": "User ID", "name": "id", "in": "path", "required": true }, { "type": "file", "description": "Image file (jpg|png|webp)", "name": "file", "in": "formData", "required": true } ], "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" } } } } }, "/api/v1/user/{user_id}/is-pending": { "get": { "description": "Returns whether the specified user has a status of \"pending\"", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Check if user status is pending", "parameters": [ { "type": "string", "description": "User ID", "name": "user_id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/user/{user_id}/is-profile-completed": { "get": { "description": "Returns the profile completion status and percentage for the specified user", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Check if user profile is completed", "parameters": [ { "type": "integer", "description": "User ID", "name": "user_id", "in": "path", "required": true } ], "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" } } } } }, "/api/v1/users": { "get": { "description": "Get users with optional filters. Each user includes subscription_status: ACTIVE, PENDING, or Unsubscribed.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Get all users", "parameters": [ { "type": "string", "description": "Role filter", "name": "role", "in": "query" }, { "type": "string", "description": "Search query", "name": "query", "in": "query" }, { "type": "integer", "description": "Page number", "name": "page", "in": "query" }, { "type": "integer", "description": "Page size", "name": "page_size", "in": "query" }, { "type": "string", "description": "Created before (RFC3339)", "name": "created_before", "in": "query" }, { "type": "string", "description": "Created after (RFC3339)", "name": "created_after", "in": "query" }, { "type": "string", "description": "User account status filter (ACTIVE, PENDING, SUSPENDED, DEACTIVATED)", "name": "status", "in": "query" }, { "type": "string", "description": "Country filter (case-insensitive match on stored value)", "name": "country", "in": "query" }, { "type": "string", "description": "Region filter (case-insensitive match on stored value)", "name": "region", "in": "query" }, { "type": "string", "description": "Derived subscription filter: ACTIVE, PENDING, or Unsubscribed (matches response subscription_status semantics)", "name": "subscription_status", "in": "query" } ], "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" } } } } }, "/api/v1/users/summary": { "get": { "security": [ { "Bearer": [] } ], "description": "Returns total users, active users, and users who joined this month", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Get user summary statistics", "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/domain.UserSummary" } } } ] } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/videos/engagement/heartbeat": { "post": { "description": "Records playback position for analytics (completion, replay, and drop-off). Send periodic heartbeats while watching; set ended=true when the viewer leaves. A new session starts after 30 minutes of inactivity or when ended=true on the prior session.", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "videos" ], "summary": "Report video playback progress", "parameters": [ { "description": "Playback heartbeat", "name": "body", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.VideoEngagementHeartbeatInput" } } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "$ref": "#/definitions/domain.VideoWatchSessionResponse" } } } ] } }, "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" } } } } }, "/api/v1/vimeo/oembed": { "get": { "description": "Fetches oEmbed metadata for a Vimeo video URL", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "Get oEmbed data for a Vimeo URL", "parameters": [ { "type": "string", "description": "Vimeo video URL", "name": "url", "in": "query", "required": true }, { "type": "integer", "description": "Desired width", "name": "width", "in": "query" }, { "type": "integer", "description": "Desired height", "name": "height", "in": "query" } ], "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" } } } } }, "/api/v1/vimeo/sample": { "get": { "description": "Fetches a sample video from Vimeo and returns video details along with an embeddable iframe for client-side integration", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "Get a sample Vimeo video with iframe embed", "parameters": [ { "type": "string", "default": "76979871", "description": "Vimeo Video ID to use as sample", "name": "video_id", "in": "query" }, { "type": "integer", "default": 640, "description": "Player width", "name": "width", "in": "query" }, { "type": "integer", "default": 360, "description": "Player height", "name": "height", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/domain.Response" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/vimeo/uploads/pull": { "post": { "description": "Initiates a pull upload where Vimeo fetches the video from a URL", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "Create a pull upload to Vimeo", "parameters": [ { "description": "Pull Upload Request", "name": "request", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.CreatePullUploadRequest" } } ], "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" } } } } }, "/api/v1/vimeo/uploads/tus": { "post": { "description": "Initiates a TUS resumable upload and returns the upload link", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "Create a TUS resumable upload to Vimeo", "parameters": [ { "description": "TUS Upload Request", "name": "request", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.CreateTusUploadRequest" } } ], "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" } } } } }, "/api/v1/vimeo/videos": { "get": { "description": "Returns a paginated list of videos for the Vimeo API token (GET https://api.vimeo.com/me/videos)", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "List videos stored in the Vimeo account", "parameters": [ { "type": "integer", "default": 1, "description": "Page number (starts at 1)", "name": "page", "in": "query" }, { "type": "integer", "default": 25, "description": "Page size (Vimeo max 100)", "name": "per_page", "in": "query" }, { "type": "string", "description": "Search query", "name": "query", "in": "query" }, { "type": "string", "description": "Sort field (e.g. date, alphabetical, plays, likes, comments, duration, relevance)", "name": "sort", "in": "query" }, { "type": "string", "description": "asc or desc", "name": "direction", "in": "query" }, { "type": "string", "description": "Vimeo filter (e.g. embeddable, playable)", "name": "filter", "in": "query" }, { "type": "string", "description": "Vimeo filter_type when using filter", "name": "filter_type", "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { "allOf": [ { "$ref": "#/definitions/domain.Response" }, { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/definitions/handlers.VimeoVideoResponse" } }, "metadata": { "$ref": "#/definitions/handlers.VimeoVideosListMetadata" } } } ] } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "503": { "description": "Service Unavailable", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/vimeo/videos/{video_id}": { "get": { "description": "Retrieves video details from Vimeo by video ID", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "Get video information from Vimeo", "parameters": [ { "type": "string", "description": "Vimeo Video ID", "name": "video_id", "in": "path", "required": true } ], "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" } } } }, "delete": { "description": "Deletes a video from the Vimeo account", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "Delete a video from Vimeo", "parameters": [ { "type": "string", "description": "Vimeo Video ID", "name": "video_id", "in": "path", "required": true } ], "responses": { "204": { "description": "No Content" }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/vimeo/videos/{video_id}/embed": { "get": { "description": "Generates an embeddable player iframe for the video", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "Get embed code for a Vimeo video", "parameters": [ { "type": "string", "description": "Vimeo Video ID", "name": "video_id", "in": "path", "required": true }, { "type": "integer", "default": 640, "description": "Player width", "name": "width", "in": "query" }, { "type": "integer", "default": 360, "description": "Player height", "name": "height", "in": "query" }, { "type": "boolean", "description": "Autoplay video", "name": "autoplay", "in": "query" }, { "type": "boolean", "description": "Loop video", "name": "loop", "in": "query" }, { "type": "boolean", "description": "Mute video", "name": "muted", "in": "query" }, { "type": "boolean", "description": "Background mode (no controls)", "name": "background", "in": "query" } ], "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" } } } } }, "/api/v1/vimeo/videos/{video_id}/status": { "get": { "description": "Returns the current transcoding status of a video", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "Vimeo" ], "summary": "Get transcode status of a Vimeo video", "parameters": [ { "type": "string", "description": "Vimeo Video ID", "name": "video_id", "in": "path", "required": true } ], "responses": { "200": { "description": "OK", "schema": { "type": "object", "additionalProperties": { "type": "string" } } }, "400": { "description": "Bad Request", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } }, "500": { "description": "Internal Server Error", "schema": { "$ref": "#/definitions/domain.ErrorResponse" } } } } }, "/api/v1/{tenant_slug}/admin-login": { "post": { "description": "Login user", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Login user", "parameters": [ { "description": "Login admin", "name": "login", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.LoginRequest" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/otp/resend": { "post": { "description": "Resend OTP if the previous one is expired", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "otp" ], "summary": "Resend OTP", "parameters": [ { "description": "Resend OTP", "name": "resendOtp", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.ResendOtpReq" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/user-login": { "post": { "description": "Login user", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "auth" ], "summary": "Login user", "parameters": [ { "description": "Login user", "name": "login", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.LoginRequest" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/user/admin-profile": { "get": { "security": [ { "Bearer": [] } ], "description": "Get user profile", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Get user profile", "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" } } } } }, "/api/v1/{tenant_slug}/user/checkPhoneEmailExist": { "post": { "description": "Check if phone number or email exist", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Check if phone number or email exist", "parameters": [ { "description": "Check phone number or email exist", "name": "checkPhoneEmailExist", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.CheckPhoneEmailExistReq" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/user/knowledge-level": { "put": { "description": "Updates the knowledge level of the specified user after initial assessment", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Update user's knowledge level", "parameters": [ { "type": "integer", "description": "User ID", "name": "user_id", "in": "path", "required": true }, { "description": "Knowledge level", "name": "knowledge_level", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.UpdateKnowledgeLevelReq" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/user/register": { "post": { "description": "Register user", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Register user", "parameters": [ { "description": "Register user", "name": "registerUser", "in": "body", "required": true, "schema": { "$ref": "#/definitions/domain.RegisterUserReq" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/user/resetPassword": { "post": { "description": "Reset tenant password", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Reset tenant password", "parameters": [ { "description": "Reset password", "name": "resetPassword", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.ResetPasswordReq" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/user/sendRegisterCode": { "post": { "description": "Send register code", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Send register code", "parameters": [ { "description": "Send register code", "name": "registerCode", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.RegisterCodeReq" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/user/sendResetCode": { "post": { "description": "Send reset code", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Send reset code", "parameters": [ { "description": "Send reset code", "name": "resetCode", "in": "body", "required": true, "schema": { "$ref": "#/definitions/handlers.ResetCodeReq" } } ], "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" } } } } }, "/api/v1/{tenant_slug}/user/user-profile": { "get": { "security": [ { "Bearer": [] } ], "description": "Get user profile", "consumes": [ "application/json" ], "produces": [ "application/json" ], "tags": [ "user" ], "summary": "Get user profile", "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" } } } } } }, "definitions": { "domain.AcceptTeamInvitationReq": { "type": "object", "required": [ "first_name", "last_name", "password", "token" ], "properties": { "bio": { "type": "string" }, "department": { "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": { "type": "string", "minLength": 8 }, "phone_number": { "type": "string" }, "profile_picture_url": { "type": "string" }, "token": { "type": "string" }, "work_phone": { "type": "string" } } }, "domain.AgeGroup": { "type": "string", "enum": [ "UNDER_13", "13_17", "18_24", "25_34", "35_44", "45_54", "55_PLUS" ], "x-enum-varnames": [ "AgeUnder13", "Age13To17", "Age18To24", "Age25To34", "Age35To44", "Age45To54", "Age55Plus" ] }, "domain.AnalyticsContentSection": { "type": "object", "properties": { "question_sets_by_type": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "questions_by_type": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "total_question_sets": { "type": "integer" }, "total_questions": { "type": "integer" } } }, "domain.AnalyticsCoursesSection": { "type": "object", "properties": { "exam_prep": { "$ref": "#/definitions/domain.AnalyticsExamPrepContentCounts" }, "lms": { "$ref": "#/definitions/domain.AnalyticsLMSContentCounts" }, "total_categories": { "description": "Top-level keys preserved for existing clients: map to LMS programs, courses, modules, and all video lessons (LMS + exam prep).", "type": "integer" }, "total_courses": { "type": "integer" }, "total_sub_courses": { "type": "integer" }, "total_videos": { "type": "integer" } } }, "domain.AnalyticsDashboard": { "type": "object", "properties": { "content": { "$ref": "#/definitions/domain.AnalyticsContentSection" }, "courses": { "$ref": "#/definitions/domain.AnalyticsCoursesSection" }, "date_filter": { "$ref": "#/definitions/domain.AnalyticsDateFilter" }, "generated_at": { "type": "string" }, "issues": { "$ref": "#/definitions/domain.AnalyticsIssuesSection" }, "notifications": { "$ref": "#/definitions/domain.AnalyticsNotificationsSection" }, "payments": { "$ref": "#/definitions/domain.AnalyticsPaymentsSection" }, "subscriptions": { "$ref": "#/definitions/domain.AnalyticsSubscriptionsSection" }, "team": { "$ref": "#/definitions/domain.AnalyticsTeamSection" }, "users": { "$ref": "#/definitions/domain.AnalyticsUsersSection" }, "videos": { "$ref": "#/definitions/domain.AnalyticsVideosSection" } } }, "domain.AnalyticsDateFilter": { "type": "object", "properties": { "from": { "type": "string" }, "mode": { "type": "string" }, "month": { "type": "integer" }, "range_end": { "type": "string" }, "range_start": { "type": "string" }, "ref_date": { "type": "string" }, "series_end": { "type": "string" }, "series_start": { "type": "string" }, "to": { "type": "string" }, "year": { "type": "integer" } } }, "domain.AnalyticsExamPrepContentCounts": { "type": "object", "properties": { "catalog_courses": { "type": "integer" }, "lesson_practices": { "type": "integer" }, "lessons": { "type": "integer" }, "lessons_with_video": { "type": "integer" }, "unit_modules": { "type": "integer" }, "units": { "type": "integer" } } }, "domain.AnalyticsIssuesSection": { "type": "object", "properties": { "by_status": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_type": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "resolution_rate": { "type": "number" }, "resolved_issues": { "type": "integer" }, "total_issues": { "type": "integer" } } }, "domain.AnalyticsLMSContentCounts": { "type": "object", "properties": { "courses": { "type": "integer" }, "lessons": { "type": "integer" }, "lessons_with_video": { "type": "integer" }, "modules": { "type": "integer" }, "practices": { "type": "integer" }, "practices_at_course": { "type": "integer" }, "practices_at_lesson": { "type": "integer" }, "practices_at_module": { "type": "integer" }, "programs": { "type": "integer" } } }, "domain.AnalyticsLabelAmount": { "type": "object", "properties": { "amount": { "type": "number" }, "count": { "type": "integer" }, "label": { "type": "string" } } }, "domain.AnalyticsLabelCount": { "type": "object", "properties": { "count": { "type": "integer" }, "label": { "type": "string" } } }, "domain.AnalyticsMonthlyRevenuePoint": { "type": "object", "properties": { "currency": { "type": "string" }, "label": { "description": "Short English month label, e.g. Jan", "type": "string" }, "month": { "description": "1–12", "type": "integer" }, "month_start": { "description": "UTC date of month start (for sorting / tooltips)", "type": "string" }, "revenue": { "description": "SUCCESS payments aggregate for that bucket", "type": "number" } } }, "domain.AnalyticsNotificationsSection": { "type": "object", "properties": { "by_channel": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_type": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "read_count": { "type": "integer" }, "total_sent": { "type": "integer" }, "unread_count": { "type": "integer" } } }, "domain.AnalyticsPaymentsSection": { "type": "object", "properties": { "avg_transaction_value": { "type": "number" }, "by_method": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelAmount" } }, "by_status": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelAmount" } }, "monthly_revenue_year": { "description": "MonthlyRevenueYear is set when RevenueMonthly is non-empty (the calendar year of those buckets).", "type": "integer" }, "revenue_last_30_days": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsRevenueTimePoint" } }, "revenue_monthly": { "description": "RevenueMonthly is populated only when the request includes year=..., with 12 months (possibly multiple currencies per month).", "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsMonthlyRevenuePoint" } }, "successful_payments": { "type": "integer" }, "total_payments": { "type": "integer" }, "total_revenue": { "type": "number" } } }, "domain.AnalyticsRevenueByPlan": { "type": "object", "properties": { "currency": { "type": "string" }, "plan_name": { "type": "string" }, "revenue": { "type": "number" } } }, "domain.AnalyticsRevenueTimePoint": { "type": "object", "properties": { "date": { "type": "string" }, "revenue": { "type": "number" } } }, "domain.AnalyticsSubscriptionsSection": { "type": "object", "properties": { "active_subscriptions": { "type": "integer" }, "by_status": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "new_month": { "type": "integer" }, "new_subscriptions_last_30_days": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsTimePoint" } }, "new_today": { "type": "integer" }, "new_week": { "type": "integer" }, "revenue_by_plan": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsRevenueByPlan" } }, "total_subscriptions": { "type": "integer" } } }, "domain.AnalyticsTeamSection": { "type": "object", "properties": { "by_role": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_status": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "total_members": { "type": "integer" } } }, "domain.AnalyticsTimePoint": { "type": "object", "properties": { "count": { "type": "integer" }, "date": { "type": "string" } } }, "domain.AnalyticsUsersSection": { "type": "object", "properties": { "by_age_group": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_country": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_education_level": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_knowledge_level": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_language_challange": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_learning_goal": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_occupation": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_region": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_role": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "by_status": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsLabelCount" } }, "new_month": { "type": "integer" }, "new_today": { "type": "integer" }, "new_week": { "type": "integer" }, "registrations_last_30_days": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsTimePoint" } }, "total_users": { "type": "integer" } } }, "domain.AnalyticsVideoDropOffPoint": { "type": "object", "properties": { "checkpoint_percent": { "type": "integer" }, "drop_off_rate": { "type": "number" }, "total_sessions": { "type": "integer" }, "viewers_reached": { "type": "integer" } } }, "domain.AnalyticsVideosSection": { "type": "object", "properties": { "completed_sessions": { "type": "integer" }, "completion_rate": { "type": "number" }, "drop_off_by_checkpoint": { "type": "array", "items": { "$ref": "#/definitions/domain.AnalyticsVideoDropOffPoint" } }, "replay_rate": { "type": "number" }, "replay_sessions": { "type": "integer" }, "total_watch_sessions": { "type": "integer" }, "unique_video_starts": { "type": "integer" }, "users_who_replayed": { "type": "integer" } } }, "domain.BulkAccountsByRoleRequest": { "type": "object", "properties": { "exclude_team_member_id": { "type": "integer" } } }, "domain.CreateCourseInput": { "type": "object", "required": [ "name" ], "properties": { "description": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "description": "SortOrder within the program when set; omit to append after current max within program_id (uniqueness is per-program).", "type": "integer", "minimum": 0 }, "thumbnail": { "type": "string" } } }, "domain.CreateExamPrepCatalogCourseInput": { "type": "object", "required": [ "category", "name" ], "properties": { "category": { "type": "string", "enum": [ "IELTS", "DUOLINGO" ] }, "description": { "type": "string" }, "name": { "type": "string" }, "thumbnail": { "type": "string" } } }, "domain.CreateExamPrepLessonInput": { "type": "object", "required": [ "title" ], "properties": { "description": { "type": "string" }, "thumbnail": { "type": "string" }, "title": { "type": "string" }, "video_url": { "type": "string" } } }, "domain.CreateExamPrepModuleInput": { "type": "object", "required": [ "name" ], "properties": { "description": { "type": "string" }, "icon": { "type": "string" }, "name": { "type": "string" }, "thumbnail": { "type": "string" } } }, "domain.CreateExamPrepPracticeInput": { "type": "object", "required": [ "question_set_id" ], "properties": { "persona_id": { "type": "integer" }, "publish_status": { "type": "string", "enum": [ "DRAFT", "draft", "PUBLISHED", "published" ] }, "question_set_id": { "type": "integer" }, "quick_tips": { "type": "string" }, "story_description": { "type": "string" }, "story_image": { "type": "string" }, "title": { "type": "string" } } }, "domain.CreateExamPrepUnitInput": { "type": "object", "required": [ "name" ], "properties": { "description": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "description": "SortOrder within the catalog course when set; omit to append after current max sort_order within catalog_course_id.", "type": "integer", "minimum": 0 }, "thumbnail": { "type": "string" } } }, "domain.CreateLessonInput": { "type": "object", "required": [ "title" ], "properties": { "description": { "type": "string" }, "publish_status": { "description": "Omit or empty defaults to DRAFT; set PUBLISHED to make visible to learners immediately.", "type": "string", "enum": [ "DRAFT", "draft", "PUBLISHED", "published" ] }, "sort_order": { "description": "SortOrder within the module when set; omit to append after current max within module_id.", "type": "integer", "minimum": 0 }, "thumbnail": { "type": "string" }, "title": { "type": "string" }, "video_url": { "type": "string" } } }, "domain.CreateLmsPersonaInput": { "type": "object", "required": [ "name" ], "properties": { "description": { "type": "string" }, "gender": { "type": "string" }, "is_active": { "type": "boolean" }, "name": { "type": "string" }, "profile_picture": { "type": "string" } } }, "domain.CreateModuleInput": { "type": "object", "required": [ "name" ], "properties": { "description": { "type": "string" }, "icon": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "description": "SortOrder within the course when set; omit to append after current max within course_id (uniqueness is per-course).", "type": "integer", "minimum": 0 } } }, "domain.CreatePracticeInput": { "type": "object", "required": [ "parent_id", "parent_kind", "question_set_id" ], "properties": { "parent_id": { "type": "integer" }, "parent_kind": { "enum": [ "COURSE", "MODULE", "LESSON" ], "allOf": [ { "$ref": "#/definitions/domain.ParentKind" } ] }, "persona_id": { "type": "integer" }, "publish_status": { "description": "Omit or empty for backward compatibility defaults to PUBLISHED; set DRAFT to save hidden from learners until published.", "type": "string", "enum": [ "DRAFT", "draft", "PUBLISHED", "published" ] }, "question_set_id": { "type": "integer" }, "quick_tips": { "type": "string" }, "story_description": { "type": "string" }, "story_image": { "type": "string" }, "title": { "type": "string" } } }, "domain.CreateProgramInput": { "type": "object", "required": [ "category", "name" ], "properties": { "category": { "type": "string", "enum": [ "LEARN_ENGLISH", "IELTS", "DUOLINGO" ] }, "description": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "description": "SortOrder inserts at this global program order when set; omit to append after current max (sort_order uniqueness is enforced).", "type": "integer", "minimum": 0 }, "thumbnail": { "type": "string" } } }, "domain.CreateRoleReq": { "type": "object", "required": [ "name" ], "properties": { "description": { "type": "string" }, "name": { "type": "string", "maxLength": 100, "minLength": 2 } } }, "domain.CreateTeamMemberReq": { "type": "object", "required": [ "email", "first_name", "last_name", "password", "team_role" ], "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": { "type": "string", "minLength": 8 }, "permissions": { "type": "array", "items": { "type": "string" } }, "phone_number": { "type": "string" }, "profile_picture_url": { "type": "string" }, "team_role": { "type": "string" }, "work_phone": { "type": "string" } } }, "domain.DynamicElementDefinition": { "type": "object", "properties": { "config": { "type": "object", "additionalProperties": true }, "id": { "type": "string" }, "kind": { "type": "string" }, "label": { "type": "string" }, "required": { "type": "boolean" } } }, "domain.DynamicElementInstance": { "type": "object", "properties": { "id": { "type": "string" }, "kind": { "type": "string" }, "meta": { "type": "object", "additionalProperties": true }, "value": {} } }, "domain.DynamicQuestionPayload": { "type": "object", "properties": { "response": { "type": "array", "items": { "$ref": "#/definitions/domain.DynamicElementInstance" } }, "stimulus": { "type": "array", "items": { "$ref": "#/definitions/domain.DynamicElementInstance" } } } }, "domain.EmploymentType": { "type": "string", "enum": [ "full_time", "part_time", "contract", "intern" ], "x-enum-varnames": [ "EmploymentTypeFullTime", "EmploymentTypePartTime", "EmploymentTypeContract", "EmploymentTypeIntern" ] }, "domain.ErrorResponse": { "type": "object", "properties": { "error": { "type": "string" }, "message": { "type": "string" } } }, "domain.InviteTeamMemberReq": { "type": "object", "required": [ "email", "team_role" ], "properties": { "email": { "type": "string" }, "team_role": { "type": "string" } } }, "domain.LogEntry": { "type": "object", "properties": { "caller": { "type": "string" }, "env": { "type": "string" }, "fields": { "type": "object", "additionalProperties": true }, "level": { "type": "string" }, "message": { "type": "string" }, "service": { "type": "string" }, "stacktrace": { "type": "string" }, "timestamp": { "type": "string" } } }, "domain.LogResponse": { "type": "object", "properties": { "data": { "type": "array", "items": { "$ref": "#/definitions/domain.LogEntry" } }, "message": { "type": "string" }, "pagination": { "$ref": "#/definitions/domain.Pagination" } } }, "domain.LoginRequest": { "type": "object", "properties": { "email": { "type": "string" }, "otp_code": { "type": "string" }, "password": { "type": "string" }, "phone_number": { "type": "string" } } }, "domain.OtpMedium": { "type": "string", "enum": [ "email", "sms" ], "x-enum-varnames": [ "OtpMediumEmail", "OtpMediumSms" ] }, "domain.Pagination": { "type": "object", "properties": { "current_page": { "type": "integer" }, "limit": { "type": "integer" }, "total": { "type": "integer" }, "total_pages": { "type": "integer" } } }, "domain.ParentKind": { "type": "string", "enum": [ "COURSE", "MODULE", "LESSON" ], "x-enum-varnames": [ "ParentKindCourse", "ParentKindModule", "ParentKindLesson" ] }, "domain.Permission": { "type": "object", "properties": { "created_at": { "type": "string" }, "description": { "type": "string" }, "group_name": { "type": "string" }, "id": { "type": "integer" }, "key": { "type": "string" }, "name": { "type": "string" } } }, "domain.QuestionAudioAnswer": { "type": "object", "properties": { "correctAnswerText": { "type": "string" }, "createdAt": { "type": "string" }, "id": { "type": "integer", "format": "int64" }, "questionID": { "type": "integer", "format": "int64" } } }, "domain.QuestionOption": { "type": "object", "properties": { "createdAt": { "type": "string" }, "id": { "type": "integer", "format": "int64" }, "isCorrect": { "type": "boolean" }, "optionOrder": { "type": "integer", "format": "int32" }, "optionText": { "type": "string" }, "questionID": { "type": "integer", "format": "int64" } } }, "domain.QuestionShortAnswer": { "type": "object", "properties": { "acceptableAnswer": { "type": "string" }, "createdAt": { "type": "string" }, "id": { "type": "integer", "format": "int64" }, "matchType": { "type": "string" }, "questionID": { "type": "integer", "format": "int64" } } }, "domain.QuestionWithDetails": { "type": "object", "properties": { "audioAnswer": { "$ref": "#/definitions/domain.QuestionAudioAnswer" }, "createdAt": { "type": "string" }, "difficultyLevel": { "type": "string" }, "dynamicPayload": { "$ref": "#/definitions/domain.DynamicQuestionPayload" }, "explanation": { "type": "string" }, "id": { "type": "integer", "format": "int64" }, "imageURL": { "type": "string" }, "options": { "type": "array", "items": { "$ref": "#/definitions/domain.QuestionOption" } }, "points": { "type": "integer", "format": "int32" }, "questionText": { "type": "string" }, "questionType": { "type": "string" }, "questionTypeDefinitionID": { "type": "integer", "format": "int64" }, "sampleAnswerVoicePrompt": { "type": "string" }, "shortAnswers": { "type": "array", "items": { "$ref": "#/definitions/domain.QuestionShortAnswer" } }, "status": { "type": "string" }, "tips": { "type": "string" }, "updatedAt": { "type": "string" }, "voicePrompt": { "type": "string" } } }, "domain.RegisterUserReq": { "type": "object", "properties": { "email": { "type": "string" }, "otp_medium": { "$ref": "#/definitions/domain.OtpMedium" }, "password": { "type": "string" }, "phone_number": { "type": "string" }, "role": { "type": "string" } } }, "domain.ReorderIDsRequest": { "type": "object", "properties": { "ordered_ids": { "type": "array", "items": { "type": "integer" } } } }, "domain.ResendOtpReq": { "type": "object", "properties": { "email": { "type": "string" }, "phone_number": { "type": "string" } } }, "domain.Response": { "type": "object", "properties": { "data": {}, "message": { "type": "string" }, "metadata": {}, "status_code": { "type": "integer" }, "success": { "type": "boolean" } } }, "domain.Role": { "type": "string", "enum": [ "SUPER_ADMIN", "ADMIN", "STUDENT", "OPEN_LEARNER", "INSTRUCTOR", "SUPPORT" ], "x-enum-varnames": [ "RoleSuperAdmin", "RoleAdmin", "RoleStudent", "RoleOpenLearner", "RoleInstructor", "RoleSupport" ] }, "domain.RoleRecord": { "type": "object", "properties": { "created_at": { "type": "string" }, "description": { "type": "string" }, "id": { "type": "integer" }, "is_system": { "type": "boolean" }, "name": { "type": "string" }, "updated_at": { "type": "string" } } }, "domain.RoleWithPermissions": { "type": "object", "properties": { "created_at": { "type": "string" }, "description": { "type": "string" }, "id": { "type": "integer" }, "is_system": { "type": "boolean" }, "name": { "type": "string" }, "permissions": { "type": "array", "items": { "$ref": "#/definitions/domain.Permission" } }, "updated_at": { "type": "string" } } }, "domain.SetRolePermissionsReq": { "type": "object", "required": [ "permission_ids" ], "properties": { "permission_ids": { "type": "array", "items": { "type": "integer" } } } }, "domain.TeamMemberLoginReq": { "type": "object", "required": [ "email", "password" ], "properties": { "email": { "type": "string" }, "password": { "type": "string" } } }, "domain.TeamMemberResponse": { "type": "object", "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": { "type": "array", "items": { "type": "string" } }, "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" } } }, "domain.TeamMemberStats": { "type": "object", "properties": { "active_count": { "type": "integer" }, "inactive_count": { "type": "integer" }, "suspended_count": { "type": "integer" }, "terminated_count": { "type": "integer" }, "total_count": { "type": "integer" } } }, "domain.TeamMemberStatus": { "type": "string", "enum": [ "active", "inactive", "suspended", "terminated" ], "x-enum-varnames": [ "TeamMemberStatusActive", "TeamMemberStatusInactive", "TeamMemberStatusSuspended", "TeamMemberStatusTerminated" ] }, "domain.TeamRole": { "type": "string", "enum": [ "SUPER_ADMIN", "ADMIN", "CONTENT_MANAGER", "SUPPORT_AGENT", "INSTRUCTOR", "FINANCE", "HR", "ANALYST" ], "x-enum-varnames": [ "TeamRoleSuperAdmin", "TeamRoleAdmin", "TeamRoleContentManager", "TeamRoleSupportAgent", "TeamRoleInstructor", "TeamRoleFinance", "TeamRoleHR", "TeamRoleAnalyst" ] }, "domain.UpdateCourseInput": { "type": "object", "properties": { "description": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "type": "integer" }, "thumbnail": { "type": "string" } } }, "domain.UpdateExamPrepCatalogCourseInput": { "type": "object", "properties": { "category": { "type": "string", "enum": [ "IELTS", "DUOLINGO" ] }, "description": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "type": "integer" }, "thumbnail": { "type": "string" } } }, "domain.UpdateExamPrepPracticeInput": { "type": "object", "properties": { "persona_id": { "type": "integer" }, "publish_status": { "type": "string", "enum": [ "DRAFT", "draft", "PUBLISHED", "published" ] }, "question_set_id": { "type": "integer" }, "quick_tips": { "type": "string" }, "story_description": { "type": "string" }, "story_image": { "type": "string" }, "title": { "type": "string" } } }, "domain.UpdateExamPrepUnitInput": { "type": "object", "properties": { "description": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "type": "integer" }, "thumbnail": { "type": "string" } } }, "domain.UpdateKnowledgeLevelReq": { "type": "object", "properties": { "knowledge_level": { "description": "BEGINNER, INTERMEDIATE, ADVANCED", "type": "string" }, "user_id": { "type": "integer" } } }, "domain.UpdateLessonInput": { "type": "object", "properties": { "description": { "type": "string" }, "publish_status": { "type": "string", "enum": [ "DRAFT", "draft", "PUBLISHED", "published" ] }, "sort_order": { "type": "integer" }, "thumbnail": { "type": "string" }, "title": { "type": "string" }, "video_url": { "type": "string" } } }, "domain.UpdateLmsPersonaInput": { "type": "object", "properties": { "description": { "type": "string" }, "gender": { "type": "string" }, "is_active": { "type": "boolean" }, "name": { "type": "string" }, "profile_picture": { "type": "string" } } }, "domain.UpdateModuleInput": { "type": "object", "properties": { "description": { "type": "string" }, "icon": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "type": "integer" } } }, "domain.UpdatePracticeInput": { "type": "object", "properties": { "persona_id": { "type": "integer" }, "publish_status": { "type": "string", "enum": [ "DRAFT", "draft", "PUBLISHED", "published" ] }, "question_set_id": { "type": "integer" }, "quick_tips": { "type": "string" }, "story_description": { "type": "string" }, "story_image": { "type": "string" }, "title": { "type": "string" } } }, "domain.UpdateProgramInput": { "type": "object", "properties": { "category": { "type": "string", "enum": [ "LEARN_ENGLISH", "IELTS", "DUOLINGO" ] }, "description": { "type": "string" }, "name": { "type": "string" }, "sort_order": { "type": "integer" }, "thumbnail": { "type": "string" } } }, "domain.UpdateRoleReq": { "type": "object", "required": [ "name" ], "properties": { "description": { "type": "string" }, "name": { "type": "string", "maxLength": 100, "minLength": 2 } } }, "domain.UpdateTeamMemberReq": { "type": "object", "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": { "type": "array", "items": { "type": "string" } }, "phone_number": { "type": "string" }, "profile_picture_url": { "type": "string" }, "team_role": { "type": "string" }, "work_phone": { "type": "string" } } }, "domain.UpdateTeamMemberStatusReq": { "type": "object", "required": [ "status" ], "properties": { "status": { "type": "string" } } }, "domain.UpdateUserReq": { "type": "object", "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" } } }, "domain.UserProfileResponse": { "type": "object", "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" }, "subscription_status": { "type": "string" }, "updated_at": { "type": "string" } } }, "domain.UserStatus": { "type": "string", "enum": [ "PENDING", "ACTIVE", "SUSPENDED", "DEACTIVATED" ], "x-enum-varnames": [ "UserStatusPending", "UserStatusActive", "UserStatusSuspended", "UserStatusDeactivated" ] }, "domain.UserSummary": { "type": "object", "properties": { "active_users": { "type": "integer" }, "joined_this_month": { "type": "integer" }, "total_users": { "type": "integer" } } }, "domain.VerifyOtpReq": { "type": "object", "required": [ "otp" ], "properties": { "email": { "type": "string" }, "otp": { "type": "string" }, "phone_number": { "type": "string" } } }, "domain.VideoEngagementHeartbeatInput": { "type": "object", "required": [ "content_id", "content_kind" ], "properties": { "content_id": { "type": "integer" }, "content_kind": { "type": "string", "enum": [ "lms_lesson", "exam_prep_lesson" ] }, "duration_sec": { "type": "integer", "minimum": 0 }, "ended": { "type": "boolean" }, "position_sec": { "type": "integer", "minimum": 0 } } }, "domain.VideoWatchSessionResponse": { "type": "object", "properties": { "completed": { "type": "boolean" }, "max_position_sec": { "type": "integer" }, "session_id": { "type": "integer" }, "session_number": { "type": "integer" } } }, "domain.WebhookRequest": { "type": "object", "properties": { "nonce": { "type": "string" }, "notificationUrl": { "type": "string" }, "paymentMethod": { "type": "string" }, "phone": { "type": "string" }, "sessionId": { "type": "string" }, "totalAmount": { "type": "integer" }, "transaction": { "type": "object", "properties": { "transactionId": { "type": "string" }, "transactionStatus": { "type": "string" } } }, "transactionStatus": { "type": "string" }, "uuid": { "type": "string" } } }, "handlers.AdminProfileRes": { "type": "object", "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" } } }, "handlers.AdminRes": { "type": "object", "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" } } }, "handlers.CheckPhoneEmailExistReq": { "type": "object", "properties": { "email": { "type": "string", "example": "john.doe@example.com" }, "phone_number": { "type": "string", "example": "1234567890" } } }, "handlers.CheckPhoneEmailExistRes": { "type": "object", "properties": { "email_exist": { "type": "boolean" }, "phone_number_exist": { "type": "boolean" } } }, "handlers.CreateAdminReq": { "type": "object", "properties": { "email": { "type": "string", "example": "john.doe@example.com" }, "first_name": { "type": "string", "example": "John" }, "last_name": { "type": "string", "example": "Doe" }, "password": { "type": "string", "example": "password123" }, "phone_number": { "type": "string", "example": "1234567890" } } }, "handlers.CreatePullUploadRequest": { "type": "object", "required": [ "file_size", "name", "source_url" ], "properties": { "description": { "type": "string" }, "file_size": { "type": "integer" }, "name": { "type": "string" }, "source_url": { "type": "string" } } }, "handlers.CreateTusUploadRequest": { "type": "object", "required": [ "file_size", "name" ], "properties": { "description": { "type": "string" }, "file_size": { "type": "integer" }, "name": { "type": "string" } } }, "handlers.LoginAdminRes": { "type": "object", "properties": { "access_token": { "type": "string" }, "refresh_token": { "type": "string" }, "role": { "type": "string" } } }, "handlers.RegisterCodeReq": { "type": "object", "properties": { "email": { "type": "string", "example": "john.doe@example.com" }, "phone_number": { "type": "string", "example": "1234567890" } } }, "handlers.ResetCodeReq": { "type": "object", "properties": { "email": { "type": "string", "example": "john.doe@example.com" }, "phone_number": { "type": "string", "example": "1234567890" } } }, "handlers.ResetPasswordReq": { "type": "object", "required": [ "otp", "password" ], "properties": { "email": { "type": "string", "example": "john.doe@example.com" }, "otp": { "type": "string", "example": "123456" }, "password": { "type": "string", "minLength": 8, "example": "newpassword123" }, "phone_number": { "type": "string", "example": "1234567890" } } }, "handlers.SearchUserByNameOrPhoneReq": { "type": "object", "properties": { "query": { "type": "string" }, "role": { "$ref": "#/definitions/domain.Role" } } }, "handlers.SendSingleAfroSMSReq": { "type": "object", "required": [ "message", "recipient" ], "properties": { "message": { "type": "string", "example": "Hello world" }, "recipient": { "type": "string", "example": "+251912345678" } } }, "handlers.VimeoEmbedResponse": { "type": "object", "properties": { "embed_html": { "type": "string" }, "embed_url": { "type": "string" }, "video_id": { "type": "string" } } }, "handlers.VimeoUploadResponse": { "type": "object", "properties": { "link": { "type": "string" }, "status": { "type": "string" }, "upload_link": { "type": "string" }, "uri": { "type": "string" }, "vimeo_id": { "type": "string" } } }, "handlers.VimeoVideoResponse": { "type": "object", "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" } } }, "handlers.VimeoVideosListMetadata": { "type": "object", "properties": { "current_page": { "type": "integer" }, "first": { "type": "string" }, "last": { "type": "string" }, "limit": { "type": "integer" }, "next": { "type": "string" }, "previous": { "type": "string" }, "total": { "type": "integer" }, "total_pages": { "type": "integer" } } }, "handlers.addQuestionToSetReq": { "type": "object", "required": [ "question_id" ], "properties": { "display_order": { "type": "integer" }, "question_id": { "type": "integer" } } }, "handlers.addUserPersonaReq": { "type": "object", "required": [ "user_id" ], "properties": { "display_order": { "type": "integer" }, "user_id": { "type": "integer" } } }, "handlers.autoRenewReq": { "type": "object", "properties": { "auto_renew": { "type": "boolean" } } }, "handlers.changePasswordReq": { "type": "object", "required": [ "current_password", "new_password" ], "properties": { "current_password": { "type": "string", "example": "oldpassword123" }, "new_password": { "type": "string", "minLength": 8, "example": "newpassword123" } } }, "handlers.createEmailTemplateReq": { "type": "object", "required": [ "body_html", "body_text", "name", "slug", "subject" ], "properties": { "body_html": { "type": "string" }, "body_text": { "type": "string" }, "name": { "type": "string" }, "slug": { "type": "string" }, "status": { "type": "string" }, "subject": { "type": "string" }, "variables": { "type": "array", "items": { "type": "string" } } } }, "handlers.createFAQReq": { "type": "object", "required": [ "answer", "question" ], "properties": { "answer": { "type": "string" }, "category": { "type": "string" }, "display_order": { "type": "integer" }, "question": { "type": "string" }, "status": { "type": "string" } } }, "handlers.createFieldOptionReq": { "type": "object", "required": [ "code", "field_key", "label" ], "properties": { "code": { "type": "string" }, "display_order": { "type": "integer" }, "field_key": { "type": "string" }, "label": { "type": "string" }, "status": { "type": "string" } } }, "handlers.createIssueReq": { "type": "object", "required": [ "description", "issue_type", "subject" ], "properties": { "description": { "type": "string" }, "issue_type": { "type": "string" }, "metadata": { "type": "object", "additionalProperties": true }, "subject": { "type": "string" } } }, "handlers.createMobileAppVersionReq": { "type": "object", "required": [ "platform", "version_code", "version_name" ], "properties": { "min_supported_version_code": { "type": "integer" }, "platform": { "type": "string" }, "release_notes": { "type": "string" }, "status": { "type": "string" }, "store_url": { "type": "string" }, "update_type": { "type": "string" }, "version_code": { "type": "integer", "minimum": 1 }, "version_name": { "type": "string" } } }, "handlers.createPlanReq": { "type": "object", "required": [ "category", "currency", "duration_unit", "duration_value", "name", "price" ], "properties": { "category": { "type": "string", "enum": [ "LEARN_ENGLISH", "IELTS", "DUOLINGO" ] }, "currency": { "type": "string" }, "description": { "type": "string" }, "duration_unit": { "type": "string", "enum": [ "DAY", "WEEK", "MONTH", "YEAR" ] }, "duration_value": { "type": "integer", "minimum": 1 }, "is_active": { "type": "boolean" }, "name": { "type": "string" }, "price": { "type": "number", "minimum": 0 } } }, "handlers.createQuestionReq": { "type": "object", "required": [ "question_text" ], "properties": { "audio_correct_answer_text": { "type": "string" }, "difficulty_level": { "type": "string" }, "dynamic_payload": { "$ref": "#/definitions/domain.DynamicQuestionPayload" }, "explanation": { "type": "string" }, "image_url": { "type": "string" }, "options": { "type": "array", "items": { "$ref": "#/definitions/handlers.optionInput" } }, "points": { "type": "integer" }, "question_text": { "type": "string" }, "question_type": { "type": "string" }, "question_type_definition_id": { "type": "integer" }, "sample_answer_voice_prompt": { "type": "string" }, "short_answers": { "type": "array", "items": { "$ref": "#/definitions/handlers.shortAnswerInput" } }, "status": { "type": "string" }, "tips": { "type": "string" }, "voice_prompt": { "type": "string" } } }, "handlers.createQuestionSetReq": { "type": "object", "required": [ "set_type", "title" ], "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": { "type": "string", "enum": [ "PRACTICE", "INITIAL_ASSESSMENT", "QUIZ", "EXAM", "SURVEY", "CAPSTONE" ] }, "shuffle_questions": { "type": "boolean" }, "status": { "type": "string" }, "time_limit_minutes": { "type": "integer" }, "title": { "type": "string" } } }, "handlers.createQuestionTypeDefinitionReq": { "type": "object", "required": [ "display_name", "key" ], "properties": { "description": { "type": "string" }, "display_name": { "type": "string" }, "key": { "type": "string" }, "response_component_kinds": { "type": "array", "items": { "type": "string" } }, "response_schema": { "type": "array", "items": { "$ref": "#/definitions/domain.DynamicElementDefinition" } }, "status": { "type": "string" }, "stimulus_component_kinds": { "type": "array", "items": { "type": "string" } }, "stimulus_schema": { "type": "array", "items": { "$ref": "#/definitions/domain.DynamicElementDefinition" } } } }, "handlers.initiateDirectPaymentReq": { "type": "object", "required": [ "email", "payment_method", "phone", "plan_id" ], "properties": { "email": { "type": "string" }, "payment_method": { "type": "string" }, "phone": { "type": "string" }, "plan_id": { "type": "integer" } } }, "handlers.initiatePaymentReq": { "type": "object", "required": [ "email", "phone", "plan_id", "provider" ], "properties": { "email": { "type": "string" }, "phone": { "type": "string" }, "plan_id": { "type": "integer" }, "provider": { "type": "string" } } }, "handlers.issueListRes": { "type": "object", "properties": { "issues": { "type": "array", "items": { "$ref": "#/definitions/handlers.issueRes" } }, "total_count": { "type": "integer" } } }, "handlers.issueRes": { "type": "object", "properties": { "created_at": { "type": "string" }, "description": { "type": "string" }, "id": { "type": "integer" }, "issue_type": { "type": "string" }, "metadata": { "type": "object", "additionalProperties": true }, "status": { "type": "string" }, "subject": { "type": "string" }, "updated_at": { "type": "string" }, "user_id": { "type": "integer" }, "user_role": { "type": "string" } } }, "handlers.loginUserRes": { "type": "object", "properties": { "access_token": { "type": "string" }, "refresh_token": { "type": "string" }, "role": { "type": "string" }, "user_id": { "type": "integer" } } }, "handlers.logoutReq": { "type": "object", "required": [ "refresh_token" ], "properties": { "device_token": { "type": "string", "example": "\u003cfcm-device-token\u003e" }, "refresh_token": { "type": "string", "example": "\u003crefresh-token\u003e" } } }, "handlers.optionInput": { "type": "object", "required": [ "option_text" ], "properties": { "is_correct": { "type": "boolean" }, "option_order": { "type": "integer" }, "option_text": { "type": "string" } } }, "handlers.previewEmailTemplateReq": { "type": "object", "properties": { "variables": { "type": "object", "additionalProperties": {} } } }, "handlers.refreshFileURLReq": { "type": "object", "properties": { "reference": { "type": "string" } } }, "handlers.refreshToken": { "type": "object", "required": [ "access_token", "refresh_token" ], "properties": { "access_token": { "type": "string", "example": "\u003cjwt-token\u003e" }, "refresh_token": { "type": "string", "example": "\u003crefresh-token\u003e" } } }, "handlers.shortAnswerInput": { "type": "object", "required": [ "acceptable_answer" ], "properties": { "acceptable_answer": { "type": "string" }, "match_type": { "type": "string" } } }, "handlers.submitRatingReq": { "type": "object", "required": [ "stars", "target_type" ], "properties": { "review": { "type": "string" }, "stars": { "type": "integer", "maximum": 5, "minimum": 1 }, "target_id": { "type": "integer" }, "target_type": { "type": "string" } } }, "handlers.subscribeReq": { "type": "object", "required": [ "plan_id" ], "properties": { "payment_method": { "type": "string" }, "payment_reference": { "type": "string" }, "plan_id": { "type": "integer" } } }, "handlers.subscribeWithPaymentReq": { "type": "object", "required": [ "email", "phone", "plan_id", "provider" ], "properties": { "email": { "type": "string" }, "phone": { "type": "string" }, "plan_id": { "type": "integer" }, "provider": { "type": "string" } } }, "handlers.teamMemberLoginRes": { "type": "object", "properties": { "access_token": { "type": "string", "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }, "member_id": { "type": "integer", "example": 1 }, "refresh_token": { "type": "string", "example": "\u003copaque-refresh-token\u003e" }, "team_role": { "type": "string", "example": "admin" } } }, "handlers.teamMemberRefreshReq": { "type": "object", "required": [ "refresh_token" ], "properties": { "refresh_token": { "type": "string" } } }, "handlers.updateAdminReq": { "type": "object", "properties": { "first_name": { "type": "string", "example": "John" }, "last_name": { "type": "string", "example": "Doe" }, "suspended": { "type": "boolean", "example": false } } }, "handlers.updateEmailTemplateReq": { "type": "object", "properties": { "body_html": { "type": "string" }, "body_text": { "type": "string" }, "name": { "type": "string" }, "status": { "type": "string" }, "subject": { "type": "string" }, "variables": { "type": "array", "items": { "type": "string" } } } }, "handlers.updateFAQReq": { "type": "object", "properties": { "answer": { "type": "string" }, "category": { "type": "string" }, "display_order": { "type": "integer" }, "question": { "type": "string" }, "status": { "type": "string" } } }, "handlers.updateFieldOptionReq": { "type": "object", "properties": { "display_order": { "type": "integer" }, "label": { "type": "string" }, "status": { "type": "string" } } }, "handlers.updateIssueStatusReq": { "type": "object", "required": [ "status" ], "properties": { "status": { "type": "string", "enum": [ "pending", "in_progress", "resolved", "rejected" ] } } }, "handlers.updateMobileAppVersionReq": { "type": "object", "properties": { "min_supported_version_code": { "type": "integer" }, "release_notes": { "type": "string" }, "status": { "type": "string" }, "store_url": { "type": "string" }, "update_type": { "type": "string" }, "version_code": { "type": "integer" }, "version_name": { "type": "string" } } }, "handlers.updatePlanReq": { "type": "object", "properties": { "category": { "type": "string", "enum": [ "LEARN_ENGLISH", "IELTS", "DUOLINGO" ] }, "currency": { "type": "string" }, "description": { "type": "string" }, "duration_unit": { "type": "string" }, "duration_value": { "type": "integer" }, "is_active": { "type": "boolean" }, "name": { "type": "string" }, "price": { "type": "number" } } }, "handlers.updateQuestionOrderReq": { "type": "object", "required": [ "display_order" ], "properties": { "display_order": { "type": "integer" } } }, "handlers.updateQuestionReq": { "type": "object", "properties": { "audio_correct_answer_text": { "type": "string" }, "difficulty_level": { "type": "string" }, "dynamic_payload": { "$ref": "#/definitions/domain.DynamicQuestionPayload" }, "explanation": { "type": "string" }, "image_url": { "type": "string" }, "options": { "type": "array", "items": { "$ref": "#/definitions/handlers.optionInput" } }, "points": { "type": "integer" }, "question_text": { "type": "string" }, "question_type": { "type": "string" }, "question_type_definition_id": { "type": "integer" }, "sample_answer_voice_prompt": { "type": "string" }, "short_answers": { "type": "array", "items": { "$ref": "#/definitions/handlers.shortAnswerInput" } }, "status": { "type": "string" }, "tips": { "type": "string" }, "voice_prompt": { "type": "string" } } }, "handlers.updateQuestionSetReq": { "type": "object", "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" }, "time_limit_minutes": { "type": "integer" }, "title": { "type": "string" } } }, "handlers.updateQuestionTypeDefinitionReq": { "type": "object", "properties": { "description": { "type": "string" }, "display_name": { "type": "string" }, "response_component_kinds": { "type": "array", "items": { "type": "string" } }, "response_schema": { "type": "array", "items": { "$ref": "#/definitions/domain.DynamicElementDefinition" } }, "status": { "type": "string" }, "stimulus_component_kinds": { "type": "array", "items": { "type": "string" } }, "stimulus_schema": { "type": "array", "items": { "$ref": "#/definitions/domain.DynamicElementDefinition" } } } }, "handlers.validateQuestionTypeDefinitionReq": { "type": "object", "properties": { "response_component_kinds": { "type": "array", "items": { "type": "string" } }, "stimulus_component_kinds": { "type": "array", "items": { "type": "string" } } } }, "handlers.verifyOTPReq": { "type": "object", "required": [ "otp", "session_id" ], "properties": { "otp": { "type": "string" }, "session_id": { "type": "string" } } }, "response.APIResponse": { "type": "object", "properties": { "data": {}, "message": { "type": "string" }, "metadata": {}, "page": { "type": "integer" }, "status": { "$ref": "#/definitions/response.Status" }, "timestamp": { "type": "string" }, "total": { "type": "integer" } } }, "response.Status": { "type": "string", "enum": [ "error", "success" ], "x-enum-varnames": [ "Error", "Success" ] }, "vimeo.OEmbedResponse": { "type": "object", "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" } } } }, "securityDefinitions": { "Bearer": { "type": "apiKey", "name": "Authorization", "in": "header" } } }` // SwaggerInfo holds exported Swagger Info so clients can modify it var SwaggerInfo = &swag.Spec{ Version: "1.0.1", Host: "", BasePath: "", Schemes: []string{}, Title: "Yimaru API", Description: "This is server for Yimaru.", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, LeftDelim: "{{", RightDelim: "}}", } func init() { swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) }