diff --git a/veza-backend-api/docs/OPENAPI_AUDIT_REPORT.md b/veza-backend-api/docs/OPENAPI_AUDIT_REPORT.md new file mode 100644 index 000000000..fb430c4a3 --- /dev/null +++ b/veza-backend-api/docs/OPENAPI_AUDIT_REPORT.md @@ -0,0 +1,78 @@ +# OpenAPI Specification Audit Report + +**Date**: 2025-01-27 +**Action**: 1.1.1.1 - Audit existing OpenAPI spec +**Status**: ✅ Complete + +## Summary + +An existing OpenAPI specification was found in Swagger 2.0 format: +- **Location**: `veza-backend-api/docs/swagger.json` and `veza-backend-api/docs/swagger.yaml` +- **Format**: Swagger 2.0 +- **Total Endpoints**: 56 documented endpoints +- **Base Path**: `/api/v1` +- **Version**: 1.2.0 + +## Findings + +### ✅ Strengths + +1. **Comprehensive Coverage**: 56 endpoints documented across multiple domains: + - Authentication (`/auth/*`) + - Tracks (`/tracks/*`) + - Playlists (`/playlists/*`) + - Users (`/users/*`) + - Analytics (`/analytics/*`) + - Webhooks (`/webhooks/*`) + - And more... + +2. **Swagger Annotations**: Backend handlers use Swagger annotations (`@Summary`, `@Description`, `@Tags`, `@Router`, etc.) + +3. **Response Format**: Uses consistent `handlers.APIResponse` wrapper format + +4. **Security**: Documents BearerAuth security requirements + +### ⚠️ Issues Identified + +1. **Format**: Uses Swagger 2.0 instead of OpenAPI 3.0+ + - **Impact**: Modern tooling prefers OpenAPI 3.0+ + - **Action**: Consider converting to OpenAPI 3.0 format (Action 1.1.1.2) + +2. **No openapi.yaml**: Only `swagger.json` and `swagger.yaml` exist + - **Impact**: Frontend type generation may expect `openapi.yaml` + - **Action**: Export to `openapi.yaml` (Action 1.1.1.3) + +3. **Version**: Spec version is 1.2.0, may need verification against actual API + +### 📋 Next Steps + +1. ✅ **Action 1.1.1.1**: Audit complete - This document +2. ⏭️ **Action 1.1.1.2**: Generate/update OpenAPI spec from Go code +3. ⏭️ **Action 1.1.1.3**: Export to `openapi.yaml` format + +## Endpoint Coverage + +The spec documents 56 endpoints. Key domains covered: +- Authentication & Authorization +- Track Management +- Playlist Operations +- User Profiles +- Analytics +- Webhooks +- Search +- Social Features +- Marketplace + +## Validation + +✅ Spec file exists and is valid JSON/YAML +✅ All major API domains appear to be documented +✅ Response formats are consistent +⚠️ Format is Swagger 2.0 (consider upgrading to OpenAPI 3.0) + +## Conclusion + +The existing OpenAPI spec provides a solid foundation. The main tasks are: +1. Converting to OpenAPI 3.0 format (if desired) +2. Ensuring it's up-to-date with current handlers +3. Exporting to `openapi.yaml` for frontend consumption diff --git a/veza-backend-api/docs/swagger.json b/veza-backend-api/docs/swagger.json index 46ca07855..89a33de75 100644 --- a/veza-backend-api/docs/swagger.json +++ b/veza-backend-api/docs/swagger.json @@ -1,23 +1,92 @@ { "swagger": "2.0", "info": { - "description": "Backend API for Veza platform.", - "title": "Veza Backend API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.veza.app/support", - "email": "support@veza.app" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.2.0" + "contact": {} }, - "host": "localhost:8080", - "basePath": "/api/v1", "paths": { + "/analytics": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Get aggregated analytics data for tracks and playlists", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Analytics" + ], + "summary": "Get Analytics Data", + "parameters": [ + { + "type": "integer", + "description": "Number of days (default: 30)", + "name": "days", + "in": "query" + }, + { + "type": "string", + "description": "Start date (ISO 8601)", + "name": "start_date", + "in": "query" + }, + { + "type": "string", + "description": "End date (ISO 8601)", + "name": "end_date", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/internal_handlers.APIResponse" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "period": { + "type": "object" + }, + "playlists": { + "type": "object" + }, + "tracks": { + "type": "object" + } + } + } + } + } + ] + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/internal_handlers.APIResponse" + } + }, + "500": { + "description": "Internal Error", + "schema": { + "$ref": "#/definitions/internal_handlers.APIResponse" + } + } + } + } + }, "/analytics/events": { "post": { "security": [ @@ -532,6 +601,42 @@ "description": "Seller ID", "name": "seller_id", "in": "query" + }, + { + "type": "string", + "description": "Search query", + "name": "q", + "in": "query" + }, + { + "type": "string", + "description": "Product type (track, pack, service)", + "name": "type", + "in": "query" + }, + { + "type": "number", + "description": "Minimum price", + "name": "min_price", + "in": "query" + }, + { + "type": "number", + "description": "Maximum price", + "name": "max_price", + "in": "query" + }, + { + "type": "integer", + "description": "Page number", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "Items per page", + "name": "limit", + "in": "query" } ], "responses": { @@ -3376,17 +3481,16 @@ "tags": [ "Comment" ], - "summary": "Get comments", + "summary": "Get track comments", "parameters": [ { "type": "string", - "description": "Track ID (UUID)", + "description": "Track ID", "name": "id", "in": "path", "required": true }, { - "minimum": 1, "type": "integer", "default": 1, "description": "Page number", @@ -3394,8 +3498,6 @@ "in": "query" }, { - "maximum": 100, - "minimum": 1, "type": "integer", "default": 20, "description": "Items per page", @@ -5331,7 +5433,7 @@ "required": [ "email", "password", - "password_confirm" + "password_confirmation" ], "properties": { "email": { @@ -5341,7 +5443,7 @@ "type": "string", "minLength": 12 }, - "password_confirm": { + "password_confirmation": { "type": "string" }, "username": { @@ -5706,12 +5808,5 @@ } } } - }, - "securityDefinitions": { - "BearerAuth": { - "type": "apiKey", - "name": "Authorization", - "in": "header" - } } } \ No newline at end of file diff --git a/veza-backend-api/docs/swagger.yaml b/veza-backend-api/docs/swagger.yaml index 62d4af4cf..9fd46171b 100644 --- a/veza-backend-api/docs/swagger.yaml +++ b/veza-backend-api/docs/swagger.yaml @@ -1,4 +1,3 @@ -basePath: /api/v1 definitions: internal_core_track.BatchDeleteRequest: properties: @@ -403,7 +402,7 @@ definitions: password: minLength: 12 type: string - password_confirm: + password_confirmation: type: string username: maxLength: 50 @@ -412,7 +411,7 @@ definitions: required: - email - password - - password_confirm + - password_confirmation type: object veza-backend-api_internal_dto.RegisterResponse: properties: @@ -654,20 +653,59 @@ definitions: success: type: boolean type: object -host: localhost:8080 info: - contact: - email: support@veza.app - name: API Support - url: http://www.veza.app/support - description: Backend API for Veza platform. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: Veza Backend API - version: 1.2.0 + contact: {} paths: + /analytics: + get: + consumes: + - application/json + description: Get aggregated analytics data for tracks and playlists + parameters: + - description: 'Number of days (default: 30)' + in: query + name: days + type: integer + - description: Start date (ISO 8601) + in: query + name: start_date + type: string + - description: End date (ISO 8601) + in: query + name: end_date + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + period: + type: object + playlists: + type: object + tracks: + type: object + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get Analytics Data + tags: + - Analytics /analytics/events: post: consumes: @@ -985,6 +1023,30 @@ paths: in: query name: seller_id type: string + - description: Search query + in: query + name: q + type: string + - description: Product type (track, pack, service) + in: query + name: type + type: string + - description: Minimum price + in: query + name: min_price + type: number + - description: Maximum price + in: query + name: max_price + type: number + - description: Page number + in: query + name: page + type: integer + - description: Items per page + in: query + name: limit + type: integer produces: - application/json responses: @@ -2451,7 +2513,7 @@ paths: - application/json description: Get paginated list of comments for a track parameters: - - description: Track ID (UUID) + - description: Track ID in: path name: id required: true @@ -2459,14 +2521,11 @@ paths: - default: 1 description: Page number in: query - minimum: 1 name: page type: integer - default: 20 description: Items per page in: query - maximum: 100 - minimum: 1 name: limit type: integer produces: @@ -2498,7 +2557,7 @@ paths: description: Internal server error schema: $ref: '#/definitions/internal_handlers.APIResponse' - summary: Get comments + summary: Get track comments tags: - Comment post: @@ -3574,9 +3633,4 @@ paths: summary: Get webhook statistics tags: - Webhook -securityDefinitions: - BearerAuth: - in: header - name: Authorization - type: apiKey swagger: "2.0" diff --git a/veza-backend-api/openapi.yaml b/veza-backend-api/openapi.yaml new file mode 100644 index 000000000..9fd46171b --- /dev/null +++ b/veza-backend-api/openapi.yaml @@ -0,0 +1,3636 @@ +definitions: + internal_core_track.BatchDeleteRequest: + properties: + track_ids: + items: + type: string + minItems: 1 + type: array + required: + - track_ids + type: object + internal_core_track.CompleteChunkedUploadRequest: + properties: + upload_id: + type: string + required: + - upload_id + type: object + internal_core_track.InitiateChunkedUploadRequest: + properties: + filename: + type: string + total_chunks: + minimum: 1 + type: integer + total_size: + minimum: 1 + type: integer + required: + - filename + - total_chunks + - total_size + type: object + internal_core_track.UpdateTrackRequest: + properties: + album: + maxLength: 255 + type: string + artist: + maxLength: 255 + type: string + genre: + maxLength: 100 + type: string + is_public: + type: boolean + title: + maxLength: 255 + minLength: 1 + type: string + year: + maximum: 2100 + minimum: 1900 + type: integer + type: object + internal_handlers.APIResponse: + properties: + data: {} + error: {} + success: + type: boolean + type: object + internal_handlers.CreateCommentRequest: + properties: + content: + maxLength: 5000 + minLength: 1 + type: string + parent_id: + description: Changed to *uuid.UUID + type: string + required: + - content + type: object + internal_handlers.CreateOrderRequest: + properties: + items: + items: + properties: + product_id: + type: string + required: + - product_id + type: object + minItems: 1 + type: array + required: + - items + type: object + internal_handlers.CreatePlaylistRequest: + properties: + description: + maxLength: 1000 + type: string + is_public: + type: boolean + title: + maxLength: 200 + minLength: 1 + type: string + required: + - title + type: object + internal_handlers.CreateProductRequest: + properties: + description: + maxLength: 2000 + type: string + license_type: + enum: + - standard + - exclusive + - commercial + type: string + price: + minimum: 0 + type: number + product_type: + enum: + - track + - pack + - service + type: string + title: + maxLength: 200 + minLength: 3 + type: string + track_id: + description: UUID string + type: string + required: + - price + - product_type + - title + type: object + internal_handlers.DisableTwoFactorRequest: + properties: + password: + type: string + required: + - password + type: object + internal_handlers.FrontendLogRequest: + properties: + context: + additionalProperties: true + type: object + data: {} + level: + type: string + message: + type: string + timestamp: + type: string + type: object + internal_handlers.RecordEventRequest: + properties: + event_name: + maxLength: 100 + minLength: 1 + type: string + payload: + additionalProperties: true + type: object + required: + - event_name + type: object + internal_handlers.RecordPlayRequest: + properties: + device: + maxLength: 100 + type: string + duration: + minimum: 1 + type: integer + required: + - duration + type: object + internal_handlers.ReorderTracksRequest: + properties: + track_ids: + description: Changed to []uuid.UUID + items: + type: string + minItems: 1 + type: array + required: + - track_ids + type: object + internal_handlers.SetupTwoFactorResponse: + properties: + qr_code_url: + type: string + recovery_codes: + items: + type: string + type: array + secret: + type: string + type: object + internal_handlers.UpdateCommentRequest: + properties: + content: + maxLength: 5000 + minLength: 1 + type: string + required: + - content + type: object + internal_handlers.UpdatePlaylistRequest: + properties: + description: + maxLength: 1000 + type: string + is_public: + type: boolean + title: + maxLength: 200 + minLength: 1 + type: string + type: object + internal_handlers.UpdateProductRequest: + properties: + description: + maxLength: 2000 + type: string + price: + minimum: 0 + type: number + status: + enum: + - draft + - active + - archived + type: string + title: + maxLength: 200 + minLength: 3 + type: string + type: object + internal_handlers.UpdateProfileRequest: + properties: + bio: + maxLength: 500 + type: string + birthdate: + type: string + first_name: + maxLength: 100 + type: string + gender: + enum: + - Male + - Female + - Other + - Prefer not to say + type: string + last_name: + maxLength: 100 + type: string + location: + maxLength: 100 + type: string + social_links: + additionalProperties: true + type: object + username: + maxLength: 30 + minLength: 3 + type: string + type: object + internal_handlers.VerifyTwoFactorRequest: + properties: + code: + description: TOTP code to verify + type: string + secret: + description: Secret from setup step + type: string + required: + - code + - secret + type: object + veza-backend-api_internal_core_marketplace.LicenseType: + enum: + - basic + - premium + - exclusive + type: string + x-enum-varnames: + - LicenseBasic + - LicensePremium + - LicenseExclusive + veza-backend-api_internal_core_marketplace.Order: + properties: + buyer_id: + type: string + created_at: + type: string + currency: + type: string + id: + type: string + items: + items: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.OrderItem' + type: array + payment_intent: + description: Stripe PaymentIntent ID + type: string + status: + description: pending, paid, failed, refunded + type: string + total_amount: + type: number + updated_at: + type: string + type: object + veza-backend-api_internal_core_marketplace.OrderItem: + properties: + id: + type: string + order_id: + type: string + price: + type: number + product_id: + type: string + type: object + veza-backend-api_internal_core_marketplace.Product: + properties: + created_at: + type: string + currency: + type: string + description: + type: string + id: + type: string + license_type: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.LicenseType' + price: + type: number + product_type: + description: '"track", "pack", "service"' + type: string + seller_id: + type: string + status: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.ProductStatus' + title: + type: string + track_id: + description: Liaison optionnelle avec un Track (si ProductType == "track") + type: string + updated_at: + type: string + type: object + veza-backend-api_internal_core_marketplace.ProductStatus: + enum: + - draft + - active + - archived + type: string + x-enum-varnames: + - ProductStatusDraft + - ProductStatusActive + - ProductStatusArchived + veza-backend-api_internal_dto.LoginRequest: + properties: + email: + type: string + password: + type: string + remember_me: + type: boolean + required: + - email + - password + type: object + veza-backend-api_internal_dto.LoginResponse: + properties: + requires_2fa: + description: 'BE-API-001: Flag indicating 2FA is required' + type: boolean + token: + $ref: '#/definitions/veza-backend-api_internal_dto.TokenResponse' + user: + $ref: '#/definitions/veza-backend-api_internal_dto.UserResponse' + type: object + veza-backend-api_internal_dto.RefreshRequest: + properties: + refresh_token: + type: string + required: + - refresh_token + type: object + veza-backend-api_internal_dto.RegisterRequest: + properties: + email: + type: string + password: + minLength: 12 + type: string + password_confirmation: + type: string + username: + maxLength: 50 + minLength: 3 + type: string + required: + - email + - password + - password_confirmation + type: object + veza-backend-api_internal_dto.RegisterResponse: + properties: + token: + $ref: '#/definitions/veza-backend-api_internal_dto.TokenResponse' + user: + $ref: '#/definitions/veza-backend-api_internal_dto.UserResponse' + type: object + veza-backend-api_internal_dto.ResendVerificationRequest: + properties: + email: + type: string + required: + - email + type: object + veza-backend-api_internal_dto.TokenResponse: + properties: + access_token: + type: string + expires_in: + type: integer + refresh_token: + type: string + type: object + veza-backend-api_internal_dto.UserResponse: + properties: + email: + type: string + id: + type: string + username: + type: string + type: object + veza-backend-api_internal_models.Playlist: + properties: + collaborators: + items: + $ref: '#/definitions/veza-backend-api_internal_models.PlaylistCollaborator' + type: array + cover_url: + type: string + created_at: + type: string + description: + type: string + follower_count: + type: integer + id: + type: string + is_public: + type: boolean + title: + type: string + track_count: + type: integer + tracks: + items: + $ref: '#/definitions/veza-backend-api_internal_models.PlaylistTrack' + type: array + updated_at: + type: string + user_id: + type: string + type: object + veza-backend-api_internal_models.PlaylistCollaborator: + properties: + created_at: + type: string + id: + type: string + permission: + $ref: '#/definitions/veza-backend-api_internal_models.PlaylistPermission' + playlist_id: + type: string + updated_at: + type: string + user: + $ref: '#/definitions/veza-backend-api_internal_models.User' + user_id: + type: string + type: object + veza-backend-api_internal_models.PlaylistPermission: + enum: + - read + - write + - admin + type: string + x-enum-varnames: + - PlaylistPermissionRead + - PlaylistPermissionWrite + - PlaylistPermissionAdmin + veza-backend-api_internal_models.PlaylistTrack: + properties: + added_at: + type: string + added_by: + type: string + id: + type: string + playlist_id: + type: string + position: + type: integer + track: + $ref: '#/definitions/veza-backend-api_internal_models.Track' + track_id: + type: string + type: object + veza-backend-api_internal_models.Track: + properties: + album: + type: string + artist: + type: string + bitrate: + description: kbps + type: integer + cover_art_path: + type: string + created_at: + type: string + creator_id: + type: string + duration: + description: seconds + type: integer + file_id: + description: NULL temporairement avant création fichier + type: string + file_path: + type: string + file_size: + description: bytes + type: integer + format: + description: mp3, flac, wav, etc. + type: string + genre: + type: string + id: + type: string + is_public: + type: boolean + like_count: + type: integer + play_count: + type: integer + sample_rate: + description: Hz + type: integer + status: + $ref: '#/definitions/veza-backend-api_internal_models.TrackStatus' + status_message: + type: string + stream_manifest_url: + type: string + stream_status: + description: pending, processing, ready, error + type: string + title: + type: string + updated_at: + type: string + waveform_path: + type: string + year: + type: integer + type: object + veza-backend-api_internal_models.TrackStatus: + enum: + - uploading + - processing + - completed + - failed + type: string + x-enum-varnames: + - TrackStatusUploading + - TrackStatusProcessing + - TrackStatusCompleted + - TrackStatusFailed + veza-backend-api_internal_models.User: + properties: + avatar: + type: string + bio: + type: string + birthdate: + type: string + created_at: + type: string + email: + type: string + first_name: + type: string + gender: + type: string + id: + type: string + is_active: + type: boolean + is_admin: + type: boolean + is_banned: + type: boolean + is_public: + type: boolean + is_verified: + type: boolean + last_login_at: + type: string + last_name: + type: string + location: + type: string + login_count: + type: integer + password: + description: Virtual field for input + type: string + role: + type: string + slug: + type: string + social_links: + type: string + token_version: + type: integer + updated_at: + type: string + username: + type: string + username_changed_at: + type: string + type: object + veza-backend-api_internal_response.APIResponse: + properties: + data: {} + error: {} + success: + type: boolean + type: object +info: + contact: {} +paths: + /analytics: + get: + consumes: + - application/json + description: Get aggregated analytics data for tracks and playlists + parameters: + - description: 'Number of days (default: 30)' + in: query + name: days + type: integer + - description: Start date (ISO 8601) + in: query + name: start_date + type: string + - description: End date (ISO 8601) + in: query + name: end_date + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + period: + type: object + playlists: + type: object + tracks: + type: object + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get Analytics Data + tags: + - Analytics + /analytics/events: + post: + consumes: + - application/json + description: Record a custom analytics event + parameters: + - description: Event Data + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_handlers.RecordEventRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Record Analytics Event + tags: + - Analytics + /analytics/tracks/{id}: + get: + consumes: + - application/json + description: Get comprehensive analytics dashboard for a track + parameters: + - description: Track ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + dashboard: + type: object + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get Track Analytics Dashboard + tags: + - Analytics + /analytics/tracks/top: + get: + consumes: + - application/json + description: Get list of top tracks by play count, optionally filtered by date + range + parameters: + - default: 10 + description: Number of tracks to return + in: query + maximum: 100 + minimum: 1 + name: limit + type: integer + - description: Start date filter (RFC3339 format) + in: query + name: start_date + type: string + - description: End date filter (RFC3339 format) + in: query + name: end_date + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + tracks: + type: array + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Get top tracks + tags: + - Analytics + /api/v1/logs/frontend: + post: + consumes: + - application/json + description: Receive and store a log entry from the frontend application + parameters: + - description: Frontend log entry + in: body + name: log + required: true + schema: + $ref: '#/definitions/internal_handlers.FrontendLogRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + received: + type: boolean + type: object + type: object + "400": + description: Invalid log entry + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Receive frontend log + tags: + - Logging + /api/v1/marketplace/download/{product_id}: + get: + consumes: + - application/json + description: Get a secure download URL for a purchased product + parameters: + - description: Product ID + in: path + name: product_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "403": + description: No license + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Get download URL + tags: + - Marketplace + /api/v1/marketplace/orders: + get: + consumes: + - application/json + description: Get all orders for the authenticated user + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.Order' + type: array + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: List user orders + tags: + - Marketplace + post: + consumes: + - application/json + description: Purchase products + parameters: + - description: Order items + in: body + name: order + required: true + schema: + $ref: '#/definitions/internal_handlers.CreateOrderRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.Order' + "400": + description: Validation Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Create a new order + tags: + - Marketplace + /api/v1/marketplace/orders/{id}: + get: + consumes: + - application/json + description: Get details of a specific order (only order owner can access) + parameters: + - description: Order ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.Order' + "400": + description: Validation Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "403": + description: Forbidden - Not order owner + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "404": + description: Order not found + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Get order details + tags: + - Marketplace + /api/v1/marketplace/products: + get: + consumes: + - application/json + description: List marketplace products with filters + parameters: + - description: Product status + in: query + name: status + type: string + - description: Seller ID + in: query + name: seller_id + type: string + - description: Search query + in: query + name: q + type: string + - description: Product type (track, pack, service) + in: query + name: type + type: string + - description: Minimum price + in: query + name: min_price + type: number + - description: Maximum price + in: query + name: max_price + type: number + - description: Page number + in: query + name: page + type: integer + - description: Items per page + in: query + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.Product' + type: array + summary: List products + tags: + - Marketplace + post: + consumes: + - application/json + description: Create a product (Track, Pack, Service) for sale + parameters: + - description: Product info + in: body + name: product + required: true + schema: + $ref: '#/definitions/internal_handlers.CreateProductRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.Product' + "400": + description: Validation Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Create a new product + tags: + - Marketplace + /api/v1/marketplace/products/{id}: + put: + consumes: + - application/json + description: Update product details (only seller can update) + parameters: + - description: Product ID + in: path + name: id + required: true + type: string + - description: Product updates + in: body + name: product + required: true + schema: + $ref: '#/definitions/internal_handlers.UpdateProductRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/veza-backend-api_internal_core_marketplace.Product' + "400": + description: Validation Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "403": + description: Forbidden - Not product owner + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "404": + description: Product not found + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Update a product + tags: + - Marketplace + /audit/activity: + get: + consumes: + - application/json + description: Get recent activity logs for the current user + parameters: + - default: 50 + description: Number of activities to return + in: query + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + activities: + type: array + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get user activity + tags: + - Audit + /audit/logs: + get: + consumes: + - application/json + description: Search and filter audit logs with pagination support. Supports + filtering by action, resource, date range, IP address, and user agent. + parameters: + - description: Filter by action type + in: query + name: action + type: string + - description: Filter by resource type + in: query + name: resource + type: string + - description: Filter by resource ID (UUID) + in: query + name: resource_id + type: string + - description: Filter by IP address + in: query + name: ip_address + type: string + - description: Filter by user agent + in: query + name: user_agent + type: string + - description: Start date filter (YYYY-MM-DD) + in: query + name: start_date + type: string + - description: End date filter (YYYY-MM-DD) + in: query + name: end_date + type: string + - default: 1 + description: Page number + in: query + name: page + type: integer + - default: 20 + description: Items per page + in: query + name: limit + type: integer + - description: Offset for pagination + in: query + name: offset + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + logs: + type: array + pagination: + type: object + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Search audit logs + tags: + - Audit + /audit/stats: + get: + consumes: + - application/json + description: Get audit statistics for the current user, optionally filtered + by date range + parameters: + - description: Start date (YYYY-MM-DD) + in: query + name: start_date + type: string + - description: End date (YYYY-MM-DD) + in: query + name: end_date + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + stats: + type: object + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get audit statistics + tags: + - Audit + /auth/2fa/disable: + post: + consumes: + - application/json + description: Disable 2FA for user (requires password confirmation) + parameters: + - description: Password Confirmation + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_handlers.DisableTwoFactorRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Invalid password or 2FA not enabled + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Disable 2FA + tags: + - Auth + /auth/2fa/setup: + post: + consumes: + - application/json + description: Generate 2FA secret and QR code for setup + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + $ref: '#/definitions/internal_handlers.SetupTwoFactorResponse' + type: object + "400": + description: 2FA already enabled + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Setup 2FA + tags: + - Auth + /auth/2fa/status: + get: + consumes: + - application/json + description: Get 2FA enabled status for authenticated user + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + enabled: + type: boolean + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get 2FA Status + tags: + - Auth + /auth/2fa/verify: + post: + consumes: + - application/json + description: Verify 2FA code and enable 2FA for user + parameters: + - description: 2FA Code + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_handlers.VerifyTwoFactorRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Invalid code + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Verify and Enable 2FA + tags: + - Auth + /auth/check-username: + get: + consumes: + - application/json + description: Check if a username is already taken + parameters: + - description: Username to check + in: query + name: username + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + available: + type: boolean + username: + type: string + type: object + type: object + "400": + description: Missing Username + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Check Username Availability + tags: + - Auth + /auth/login: + post: + consumes: + - application/json + description: Authenticate user and return access token. Refresh token is set + in httpOnly cookie. + parameters: + - description: Login Credentials + in: body + name: request + required: true + schema: + $ref: '#/definitions/veza-backend-api_internal_dto.LoginRequest' + produces: + - application/json + responses: + "200": + description: Access token returned in body, refresh token in httpOnly cookie + schema: + $ref: '#/definitions/veza-backend-api_internal_dto.LoginResponse' + "400": + description: Validation or Bad Request + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Invalid credentials + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: User Login + tags: + - Auth + /auth/logout: + post: + consumes: + - application/json + description: Revoke refresh token and current session + parameters: + - description: Refresh Token to revoke + in: body + name: request + required: true + schema: + properties: + refresh_token: + type: string + type: object + produces: + - application/json + responses: + "200": + description: Success message + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Logout + tags: + - Auth + /auth/me: + get: + consumes: + - application/json + description: Get profile information of the currently logged-in user + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: User not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get Current User + tags: + - Auth + /auth/refresh: + post: + consumes: + - application/json + description: Get a new access token using a refresh token + parameters: + - description: Refresh Token + in: body + name: request + required: true + schema: + $ref: '#/definitions/veza-backend-api_internal_dto.RefreshRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/veza-backend-api_internal_dto.TokenResponse' + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Invalid/Expired Refresh Token + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Refresh Token + tags: + - Auth + /auth/register: + post: + consumes: + - application/json + description: Register a new user account + parameters: + - description: Registration Data + in: body + name: request + required: true + schema: + $ref: '#/definitions/veza-backend-api_internal_dto.RegisterRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/veza-backend-api_internal_dto.RegisterResponse' + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "409": + description: User already exists + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: User Registration + tags: + - Auth + /auth/resend-verification: + post: + consumes: + - application/json + description: Resend the email verification link + parameters: + - description: Email + in: body + name: request + required: true + schema: + $ref: '#/definitions/veza-backend-api_internal_dto.ResendVerificationRequest' + produces: + - application/json + responses: + "200": + description: Success message + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Resend Verification Email + tags: + - Auth + /auth/verify-email: + post: + consumes: + - application/json + description: Verify user email address using a token + parameters: + - description: Verification Token + in: query + name: token + required: true + type: string + produces: + - application/json + responses: + "200": + description: Success message + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "400": + description: Invalid Token + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Verify Email + tags: + - Auth + /chat/token: + get: + consumes: + - application/json + description: Generate a short-lived token for chat authentication + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + token: + type: string + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get Chat Token + tags: + - Chat + /comments/{id}: + put: + consumes: + - application/json + description: Update a comment (only by owner) + parameters: + - description: Comment ID (UUID) + in: path + name: id + required: true + type: string + - description: Updated comment content + in: body + name: comment + required: true + schema: + $ref: '#/definitions/internal_handlers.UpdateCommentRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + comment: + type: object + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "403": + description: Forbidden - can only edit own comments + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Comment not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Update comment + tags: + - Comment + /comments/{id}/replies: + get: + consumes: + - application/json + description: Get paginated list of replies to a comment + parameters: + - description: Parent Comment ID (UUID) + in: path + name: id + required: true + type: string + - default: 1 + description: Page number + in: query + minimum: 1 + name: page + type: integer + - default: 20 + description: Items per page + in: query + maximum: 100 + minimum: 1 + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + pagination: + type: object + replies: + type: array + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Parent comment not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Get comment replies + tags: + - Comment + /playlists: + get: + consumes: + - application/json + description: Get a paginated list of playlists + parameters: + - default: 1 + description: Page number + in: query + name: page + type: integer + - default: 20 + description: Items per page + in: query + name: limit + type: integer + - description: Filter by User ID + in: query + name: user_id + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + pagination: + type: object + playlists: + items: + $ref: '#/definitions/veza-backend-api_internal_models.Playlist' + type: array + type: object + type: object + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get Playlists + tags: + - Playlist + post: + consumes: + - application/json + description: Create a new playlist + parameters: + - description: Playlist Metadata + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_handlers.CreatePlaylistRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + playlist: + $ref: '#/definitions/veza-backend-api_internal_models.Playlist' + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Create Playlist + tags: + - Playlist + /playlists/{id}: + delete: + consumes: + - application/json + description: Permanently delete a playlist + parameters: + - description: Playlist ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Playlist not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Delete Playlist + tags: + - Playlist + get: + consumes: + - application/json + description: Get detailed information about a playlist + parameters: + - description: Playlist ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + playlist: + $ref: '#/definitions/veza-backend-api_internal_models.Playlist' + type: object + type: object + "400": + description: Invalid ID + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Playlist not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get Playlist by ID + tags: + - Playlist + put: + consumes: + - application/json + description: Update playlist metadata + parameters: + - description: Playlist ID + in: path + name: id + required: true + type: string + - description: Playlist Metadata + in: body + name: playlist + required: true + schema: + $ref: '#/definitions/internal_handlers.UpdatePlaylistRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + playlist: + $ref: '#/definitions/veza-backend-api_internal_models.Playlist' + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Playlist not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Update Playlist + tags: + - Playlist + /playlists/{id}/tracks: + post: + consumes: + - application/json + description: Add a track to the playlist + parameters: + - description: Playlist ID + in: path + name: id + required: true + type: string + - description: Track ID (in body) + in: body + name: trackId + required: true + schema: + properties: + track_id: + type: string + type: object + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Track already present or invalid ID + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Playlist or Track not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Add Track to Playlist + tags: + - Playlist + /playlists/{id}/tracks/{trackId}: + delete: + consumes: + - application/json + description: Remove a track from the playlist + parameters: + - description: Playlist ID + in: path + name: id + required: true + type: string + - description: Track ID + in: path + name: trackId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "404": + description: Playlist or Track not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Remove Track from Playlist + tags: + - Playlist + /playlists/{id}/tracks/reorder: + put: + consumes: + - application/json + description: Reorder tracks in the playlist + parameters: + - description: Playlist ID + in: path + name: id + required: true + type: string + - description: New Track Order + in: body + name: order + required: true + schema: + $ref: '#/definitions/internal_handlers.ReorderTracksRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Reorder Tracks + tags: + - Playlist + /tracks: + get: + consumes: + - application/json + description: Get a paginated list of tracks with filters + parameters: + - default: 1 + description: Page number + in: query + name: page + type: integer + - default: 20 + description: Items per page + in: query + name: limit + type: integer + - description: Filter by User ID + in: query + name: user_id + type: string + - description: Filter by Genre + in: query + name: genre + type: string + - description: Filter by Format + in: query + name: format + type: string + - default: created_at + description: Sort field + in: query + name: sort_by + type: string + - default: desc + description: Sort order (asc/desc) + in: query + name: sort_order + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + pagination: + type: object + tracks: + items: + $ref: '#/definitions/veza-backend-api_internal_models.Track' + type: array + type: object + type: object + "500": + description: Internal Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + summary: List Tracks + tags: + - Track + post: + consumes: + - multipart/form-data + description: Upload a new track (audio file) + parameters: + - description: Audio File (MP3, WAV, FLAC, OGG) + in: formData + name: file + required: true + type: file + produces: + - application/json + responses: + "201": + description: Created + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + track: + $ref: '#/definitions/veza-backend-api_internal_models.Track' + type: object + type: object + "400": + description: No file or validation error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "403": + description: Quota exceeded + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Upload Track + tags: + - Track + /tracks/{id}: + delete: + consumes: + - application/json + description: Permanently delete a track + parameters: + - description: Track ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Delete Track + tags: + - Track + get: + consumes: + - application/json + description: Get detailed information about a track + parameters: + - description: Track ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + track: + $ref: '#/definitions/veza-backend-api_internal_models.Track' + type: object + type: object + "400": + description: Invalid ID + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + summary: Get Track by ID + tags: + - Track + put: + consumes: + - application/json + description: Update track metadata + parameters: + - description: Track ID + in: path + name: id + required: true + type: string + - description: Track Metadata + in: body + name: track + required: true + schema: + $ref: '#/definitions/internal_core_track.UpdateTrackRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + track: + $ref: '#/definitions/veza-backend-api_internal_models.Track' + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Update Track + tags: + - Track + /tracks/{id}/analytics/plays: + get: + consumes: + - application/json + description: Get play statistics over time for a track, grouped by time period + parameters: + - description: Track ID (UUID) + in: path + name: id + required: true + type: string + - description: Start date (RFC3339 format) + in: query + name: start_date + type: string + - description: End date (RFC3339 format) + in: query + name: end_date + type: string + - default: day + description: Time period grouping (hour, day, week, month) + in: query + name: interval + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + points: + type: array + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Get plays over time + tags: + - Analytics + /tracks/{id}/comments: + get: + consumes: + - application/json + description: Get paginated list of comments for a track + parameters: + - description: Track ID + in: path + name: id + required: true + type: string + - default: 1 + description: Page number + in: query + name: page + type: integer + - default: 20 + description: Items per page + in: query + name: limit + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + comments: + type: array + pagination: + type: object + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Get track comments + tags: + - Comment + post: + consumes: + - application/json + description: Create a new comment on a track. Can be a top-level comment or + a reply to another comment (using parent_id). + parameters: + - description: Track ID (UUID) + in: path + name: id + required: true + type: string + - description: Comment data + in: body + name: comment + required: true + schema: + $ref: '#/definitions/internal_handlers.CreateCommentRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + comment: + type: object + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Create comment + tags: + - Comment + /tracks/{id}/comments/{comment_id}: + delete: + consumes: + - application/json + description: Delete a comment (only by owner or admin) + parameters: + - description: Track ID + in: path + name: id + required: true + type: string + - description: Comment ID + in: path + name: comment_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "403": + description: Forbidden - not comment owner + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Comment not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Delete comment + tags: + - Comment + /tracks/{id}/play: + post: + consumes: + - application/json + description: Record a play event for a track. Can be called anonymously or with + authentication. + parameters: + - description: Track ID (UUID) + in: path + name: id + required: true + type: string + - description: Play event data + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_handlers.RecordPlayRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Record play + tags: + - Analytics + /tracks/{id}/stats: + get: + consumes: + - application/json + description: Get statistics for a track (plays, likes, etc.) + parameters: + - description: Track ID (UUID) + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + stats: + type: object + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Get track statistics + tags: + - Analytics + /tracks/{id}/status: + get: + consumes: + - application/json + description: Get the processing status of an uploaded track + parameters: + - description: Track ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + progress: + type: integer + type: object + type: object + "400": + description: Invalid ID + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "404": + description: Track not found + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Get Upload Status + tags: + - Track + /tracks/batch/delete: + post: + consumes: + - application/json + description: Delete multiple tracks at once + parameters: + - description: List of Track IDs + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_core_track.BatchDeleteRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + deleted: + items: + type: string + type: array + failed: + type: object + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "500": + description: Internal Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Batch Delete Tracks + tags: + - Track + /tracks/chunk: + post: + consumes: + - multipart/form-data + description: Upload a single chunk of a file + parameters: + - description: Chunk Data + in: formData + name: chunk + required: true + type: file + - description: Upload ID + in: formData + name: upload_id + required: true + type: string + - description: Chunk Number + in: formData + name: chunk_number + required: true + type: integer + - description: Total Chunks + in: formData + name: total_chunks + required: true + type: integer + - description: Total Size + format: int64 + in: formData + name: total_size + required: true + type: integer + - description: Filename + in: formData + name: filename + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + message: + type: string + progress: + format: float64 + type: number + received_chunks: + type: integer + upload_id: + type: string + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Upload Chunk + tags: + - Track + /tracks/complete: + post: + consumes: + - application/json + description: Finish upload session and assemble file + parameters: + - description: Upload ID + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_core_track.CompleteChunkedUploadRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + md5: + type: string + message: + type: string + track: + $ref: '#/definitions/veza-backend-api_internal_models.Track' + type: object + type: object + "400": + description: Validation or Assemblage Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Complete Chunked Upload + tags: + - Track + /tracks/initiate: + post: + consumes: + - application/json + description: Start a new chunked upload session + parameters: + - description: Upload Metadata + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_core_track.InitiateChunkedUploadRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + message: + type: string + upload_id: + type: string + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Initiate Chunked Upload + tags: + - Track + /tracks/quota/{id}: + get: + consumes: + - application/json + description: Get remaining upload quota for the user + parameters: + - description: User ID (optional, defaults to current user) + in: path + name: id + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + quota: + type: object + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Get Upload Quota + tags: + - Track + /tracks/resume/{uploadId}: + get: + consumes: + - application/json + description: Get state of an interrupted upload + parameters: + - description: Upload ID + in: path + name: uploadId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + - properties: + data: + properties: + chunks_received: + type: integer + upload_id: + type: string + type: object + type: object + "404": + description: Upload session not found + schema: + $ref: '#/definitions/veza-backend-api_internal_response.APIResponse' + security: + - BearerAuth: [] + summary: Resume Upload + tags: + - Track + /users: + get: + consumes: + - application/json + description: Get a paginated list of users with optional filtering + parameters: + - default: 1 + description: Page number + in: query + name: page + type: integer + - default: 20 + description: Items per page + in: query + name: limit + type: integer + - description: Filter by role + in: query + name: role + type: string + - description: Filter by active status + in: query + name: is_active + type: boolean + - description: Filter by verified status + in: query + name: is_verified + type: boolean + - description: Search by username, email, first_name, last_name + in: query + name: search + type: string + - default: created_at + description: Sort field (created_at, username, email, last_login_at) + in: query + name: sort_by + type: string + - default: desc + description: Sort order (asc, desc) + in: query + name: sort_order + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + pagination: + type: object + users: + type: array + type: object + type: object + "500": + description: Internal Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: List Users + tags: + - User + /users/{id}: + delete: + consumes: + - application/json + description: Soft delete a user (only user owner or admin can delete) + parameters: + - description: User ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: User deleted successfully + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "400": + description: Invalid ID + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "403": + description: Forbidden - Not user owner or admin + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: User not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Delete user + tags: + - User + get: + consumes: + - application/json + description: Get public profile information for a user + parameters: + - description: User ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + profile: + type: object + type: object + type: object + "400": + description: Invalid ID + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: User not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Get Profile by ID + tags: + - User + put: + consumes: + - application/json + description: Update user profile details + parameters: + - description: User ID + in: path + name: id + required: true + type: string + - description: Profile Data + in: body + name: profile + required: true + schema: + $ref: '#/definitions/internal_handlers.UpdateProfileRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + profile: + type: object + type: object + type: object + "400": + description: Validation Error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Update Profile + tags: + - User + /users/{id}/analytics/stats: + get: + consumes: + - application/json + description: Get analytics statistics for a user (total plays, tracks, etc.) + parameters: + - description: User ID (UUID) + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + stats: + type: object + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "403": + description: Forbidden - can only view own stats + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: User not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get user statistics + tags: + - Analytics + /users/{id}/completion: + get: + consumes: + - application/json + description: Get profile completion percentage and missing fields + parameters: + - description: User ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + type: object + type: object + "400": + description: Invalid ID + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "403": + description: Forbidden + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Get Profile Completion + tags: + - User + /users/by-username/{username}: + get: + consumes: + - application/json + description: Get public profile information for a user by username + parameters: + - description: Username + in: path + name: username + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + profile: + type: object + type: object + type: object + "400": + description: Missing username + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: User not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + summary: Get Profile by Username + tags: + - User + /webhooks: + get: + consumes: + - application/json + description: Get a list of all webhooks registered by the current user + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + webhooks: + type: array + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: List webhooks + tags: + - Webhook + post: + consumes: + - application/json + description: Register a new webhook for receiving events + parameters: + - description: Webhook registration data + in: body + name: webhook + required: true + schema: + type: object + produces: + - application/json + responses: + "201": + description: Created + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + webhook: + type: object + type: object + type: object + "400": + description: Validation error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Register webhook + tags: + - Webhook + /webhooks/{id}: + delete: + consumes: + - application/json + description: Delete a webhook by ID + parameters: + - description: Webhook ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Invalid webhook ID + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Webhook not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Delete webhook + tags: + - Webhook + /webhooks/{id}/regenerate-key: + post: + consumes: + - application/json + description: Generate a new API key for a webhook (invalidates the old one) + parameters: + - description: Webhook ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + api_key: + type: string + message: + type: string + type: object + type: object + "400": + description: Invalid webhook ID + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Webhook not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Regenerate webhook API key + tags: + - Webhook + /webhooks/{id}/test: + post: + consumes: + - application/json + description: Send a test event to a webhook to verify it's working + parameters: + - description: Webhook ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + message: + type: string + type: object + type: object + "400": + description: Invalid webhook ID + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "404": + description: Webhook not found + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Test webhook + tags: + - Webhook + /webhooks/stats: + get: + consumes: + - application/json + description: Get statistics for webhook delivery and performance + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/internal_handlers.APIResponse' + - properties: + data: + properties: + stats: + type: object + type: object + type: object + "401": + description: Unauthorized + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + "500": + description: Internal server error + schema: + $ref: '#/definitions/internal_handlers.APIResponse' + security: + - BearerAuth: [] + summary: Get webhook statistics + tags: + - Webhook +swagger: "2.0"