openapi: 3.0.3 info: title: 'Wave API Documentation Gama prueba' description: 'funciona alg' version: 1.0.0 servers: - url: 'https://www.nexasplay.com' tags: - name: Autenticación description: '' - name: Endpoints description: '' - name: Filtros description: '' - name: Rooms description: '' paths: /api/login: post: summary: 'Iniciar sesión' operationId: iniciarSesin description: "Este endpoint permite autenticar a un usuario mediante correo y contraseña.\nSi las credenciales son correctas, devuelve un token que se utilizará\npara autenticar las siguientes peticiones." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... token_type: bearer expires_in: 60 properties: access_token: type: string example: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... token_type: type: string example: bearer expires_in: type: integer example: 60 401: description: '' content: application/json: schema: type: object example: error: Unauthorized properties: error: type: string example: Unauthorized tags: - Autenticación requestBody: required: true content: application/json: schema: type: object properties: email: type: string description: 'Correo electrónico del usuario. Ejemplo: cliente1@nexaxplay.com' example: qkunze@example.com nullable: false password: type: string description: 'Contraseña del usuario. Ejemplo: 123456789' example: 'O[2UZ5ij-e/dl4m{o,' nullable: false required: - email - password security: [] /api/register: post: summary: 'Registrar un nuevo usuario.' operationId: registrarUnNuevoUsuario description: "Permite crear un nuevo usuario en el sistema proporcionando los datos personales requeridos.\nRetorna un token JWT para autenticación posterior." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... token_type: bearer expires_in: 60 properties: access_token: type: string example: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... token_type: type: string example: bearer expires_in: type: integer example: 60 422: description: '' content: application/json: schema: type: object example: email: - 'The email has already been taken.' properties: email: type: array example: - 'The email has already been taken.' items: type: string tags: - Autenticación requestBody: required: true content: application/json: schema: type: object properties: first_name: type: string description: 'Nombre del usuario. Ejemplo: Sean' example: consequatur nullable: false last_name: type: string description: 'Apellido del usuario. Ejemplo: paul' example: consequatur nullable: false email: type: string description: 'Correo electrónico válido y único. Ejemplo: seanpuol@gmail.com' example: qkunze@example.com nullable: false password: type: string description: 'Contraseña con mínimo 8 caracteres. Ejemplo: 123456789' example: 'O[2UZ5ij-e/dl4m{o,' nullable: false phone: type: string description: 'Número de teléfono único. Ejemplo: 30243614512' example: consequatur nullable: false password_confirmation: type: string description: 'Confirmación de la contraseña. Ejemplo: 123456789' example: consequatur nullable: false birthdate: type: date description: 'Fecha de nacimiento en formato Y-m-d. Ejemplo: 1989-04-15' example: consequatur nullable: false gender: type: string description: 'Género del usuario (M o F). Ejemplo: M' example: consequatur nullable: false current_city: type: string description: 'Ciudad actual del usuario. Ejemplo: Pasto' example: consequatur nullable: false required: - first_name - last_name - email - password - phone - password_confirmation - birthdate - gender - current_city security: [] /api/logout: post: summary: 'Cerrar sesión' operationId: cerrarSesin description: "Este endpoint cierra la sesión del usuario autenticado invalidando su token JWT.\nDespués de cerrar sesión, el token ya no será válido para futuras peticiones." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: message: 'Successfully logged out' properties: message: type: string example: 'Successfully logged out' 401: description: '' content: application/json: schema: type: object example: message: 'Token inválido o expirado' properties: message: type: string example: 'Token inválido o expirado' tags: - Autenticación security: [] /api/refresh: post: summary: 'Refrescar token JWT' operationId: refrescarTokenJWT description: "Este endpoint permite renovar el token JWT del usuario autenticado cuando está próximo a expirar.\nDevuelve un nuevo token válido que debe reemplazar al anterior en las siguientes peticiones." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... token_type: bearer expires_in: 60 properties: access_token: type: string example: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... token_type: type: string example: bearer expires_in: type: integer example: 60 401: description: '' content: application/json: schema: type: object example: message: 'Token inválido o expirado' properties: message: type: string example: 'Token inválido o expirado' tags: - Autenticación security: [] /api/token: post: summary: 'Obtener token de acceso desde una API Key' operationId: obtenerTokenDeAccesoDesdeUnaAPIKey description: "Este endpoint genera un token JWT válido para el usuario asociado a una API Key.\nSe usa cuando un sistema externo necesita autenticarse sin usar usuario y contraseña." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: access_token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... properties: access_token: type: string example: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9... 400: description: '' content: application/json: schema: type: object example: message: 'Invalid Api Key' properties: message: type: string example: 'Invalid Api Key' 401: description: '' content: application/json: schema: type: object example: message: Unauthorized properties: message: type: string example: Unauthorized tags: - Autenticación requestBody: required: true content: application/json: schema: type: object properties: key: type: string description: 'Clave API válida asociada a un usuario. Ejemplo: 4f9b28b5e912f7a2b1d4c8e7' example: consequatur nullable: false required: - key security: [] /api/match/join: post: summary: '' operationId: postApiMatchJoin description: '' parameters: [] responses: { } tags: - Endpoints security: [] '/api/match/playcard/{room_name}': post: summary: '' operationId: postApiMatchPlaycardRoom_name description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: room_name description: '' example: consequatur required: true schema: type: string '/api/rooms/{room_id}': get: summary: '' operationId: getApiRoomsRoom_id description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] parameters: - in: path name: room_id description: 'The ID of the room.' example: 17 required: true schema: type: integer /api/user/balances: post: summary: 'Devuelve los saldos actuales del usuario autenticado.' operationId: devuelveLosSaldosActualesDelUsuarioAutenticado description: 'Corresponde al endpoint GET /api/user/balances' parameters: [] responses: { } tags: - Endpoints security: [] /api/user: get: summary: '' operationId: getApiUser description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] '/api/minigames/{minigame_id}/play': post: summary: 'Inicia una partida para el usuario autenticado.' operationId: iniciaUnaPartidaParaElUsuarioAutenticado description: 'Corresponde al endpoint: POST /api/minigames/{minigame}/play' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: payment_method: type: string description: '' example: consequatur nullable: false event_id: type: string description: 'The id of an existing record in the events table.' example: consequatur nullable: false required: - payment_method - event_id security: [] parameters: - in: path name: minigame_id description: 'The ID of the minigame.' example: 1 required: true schema: type: integer /api/scores: post: summary: 'Guarda la puntuación del usuario al finalizar una partida.' operationId: guardaLaPuntuacinDelUsuarioAlFinalizarUnaPartida description: 'Corresponde al endpoint: POST /api/scores' parameters: [] responses: { } tags: - Endpoints requestBody: required: true content: application/json: schema: type: object properties: minigame_id: type: string description: 'The id of an existing record in the minigames table.' example: consequatur nullable: false event_id: type: string description: 'The id of an existing record in the events table.' example: consequatur nullable: false score: type: integer description: 'Must be at least 0.' example: 45 nullable: false required: - minigame_id - event_id - score security: [] '/api/{datatype}': get: summary: '' operationId: getApiDatatype description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] post: summary: '' operationId: postApiDatatype description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: datatype description: '' example: consequatur required: true schema: type: string '/api/{datatype}/{id}': get: summary: '' operationId: getApiDatatypeId description: '' parameters: [] responses: 401: description: '' content: application/json: schema: type: object example: message: Unauthenticated. properties: message: type: string example: Unauthenticated. tags: - Endpoints security: [] put: summary: '' operationId: putApiDatatypeId description: '' parameters: [] responses: { } tags: - Endpoints security: [] delete: summary: '' operationId: deleteApiDatatypeId description: '' parameters: [] responses: { } tags: - Endpoints security: [] parameters: - in: path name: datatype description: '' example: consequatur required: true schema: type: string - in: path name: id description: 'The ID of the {datatype}.' example: consequatur required: true schema: type: string /api/companies-filters: get: summary: 'Listar y Filtrar Compañías' operationId: listarYFiltrarCompaas description: "Muestra una lista paginada de compañías.\nPermite múltiples filtros y opciones de ordenamiento para descubrir compañías." parameters: - in: query name: label description: 'Filtrar compañías por el nombre de una etiqueta.' example: Restaurante required: false schema: type: string description: 'Filtrar compañías por el nombre de una etiqueta.' example: Restaurante nullable: false - in: query name: has_active_events description: 'Filtrar compañías que tengan al menos un evento activo.' example: true required: false schema: type: boolean description: 'Filtrar compañías que tengan al menos un evento activo.' example: true nullable: false - in: query name: sort_by description: "Ordenar los resultados. Opciones: 'rating' (mejor a peor calificada)." example: rating required: false schema: type: string description: "Ordenar los resultados. Opciones: 'rating' (mejor a peor calificada)." example: rating nullable: false responses: 200: description: '' content: application/json: schema: type: object example: data: - id: 1 name: 'Company 1' logoUrl: null description: 'This company.' phone: '3121231230' catalogUrl: null schedule: null address: null city: Pasto location: '1.2136,-77.2793' gameRoomUrl: null properties: data: type: array example: - id: 1 name: 'Company 1' logoUrl: null description: 'This company.' phone: '3121231230' catalogUrl: null schedule: null address: null city: Pasto location: '1.2136,-77.2793' gameRoomUrl: null items: type: object properties: id: type: integer example: 1 name: type: string example: 'Company 1' logoUrl: type: string example: null description: type: string example: 'This company.' phone: type: string example: '3121231230' catalogUrl: type: string example: null schedule: type: string example: null address: type: string example: null city: type: string example: Pasto location: type: string example: '1.2136,-77.2793' gameRoomUrl: type: string example: null 404: description: '' content: application/json: schema: type: object example: message: 'No query results for model [App\Models\Company] 99' properties: message: type: string example: 'No query results for model [App\Models\Company] 99' tags: - Filtros security: [] /api/companies-filters/nearby: get: summary: 'Buscar compañías cercanas' operationId: buscarCompaasCercanas description: 'Este endpoint permite buscar compañías cercanas a una ubicación geográfica utilizando latitud, longitud y un radio (en km).' parameters: - in: query name: lat description: 'float Latitud actual del usuario.' example: '-12.0464' required: true schema: type: string description: 'float Latitud actual del usuario.' example: '-12.0464' nullable: false - in: query name: lng description: 'float Longitud actual del usuario.' example: '-77.0428' required: true schema: type: string description: 'float Longitud actual del usuario.' example: '-77.0428' nullable: false - in: query name: radius description: 'Radio de búsqueda en kilómetros (por defecto: 25 km). Mínimo: 1, máximo: 100.' example: 10.0 required: false schema: type: number description: 'Radio de búsqueda en kilómetros (por defecto: 25 km). Mínimo: 1, máximo: 100.' example: 10.0 nullable: false responses: 200: description: '' content: text/plain: schema: type: string example: "{\n\"data\": [\n {\n \"id\": 1,\n \"name\": \"Arcade Central Pasto\",\n \"logoUrl\": null,\n \"description\": \"La mejor sala de juegos de Nariño.\",\n \"phone\": null,\n \"catalogUrl\": null,\n \"schedule\": null,\n \"address\": null,\n \"city\": \"Pasto\",\n \"location\": \"1.213615,-77.279343\",\n \"gameRoomUrl\": null,\n \"distance\": 0.01\n },\n]}" tags: - Filtros requestBody: required: true content: application/json: schema: type: object properties: lat: type: number description: 'Must be between -90 and 90.' example: -89 nullable: false lng: type: number description: 'Must be between -180 and 180.' example: -180 nullable: false radius: type: number description: 'Must be at least 1. Must not be greater than 100.' example: 16 nullable: true required: - lat - lng security: [] '/api/companies-filters/{company_id}/average-rating': get: summary: 'Obtener calificación compañia' operationId: obtenerCalificacinCompaia description: 'Calcula y devuelve la calificación promedio (de 1 a 5) y el número total de reseñas para una compañía específica.' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: data: company_id: 1 average_rating: '4.3' review_count: 15 properties: data: type: object properties: company_id: type: integer example: 1 average_rating: type: string example: '4.3' review_count: type: integer example: 15 404: description: '' content: application/json: schema: type: object example: message: 'No query results for model [App\Models\Company] 99' properties: message: type: string example: 'No query results for model [App\Models\Company] 99' tags: - Filtros security: [] parameters: - in: path name: company_id description: 'El ID de la compañía.' example: '1' required: true schema: type: string /api/events-filters: get: summary: 'Listar y filtrar Eventos' operationId: listarYFiltrarEventos description: "Muestra una lista paginada de todos los eventos que están actualmente activos.\nPermite filtrar por ciudad, compañía o por los minijuegos incluidos en el evento.\nLos eventos se ordenan por los más recientes primero." parameters: - in: query name: city description: 'Filtrar eventos por ciudad (búsqueda parcial).' example: Pasto required: false schema: type: string description: 'Filtrar eventos por ciudad (búsqueda parcial).' example: Pasto nullable: false - in: query name: company_id description: 'Filtrar eventos por el ID de la compañía organizadora.' example: 1 required: false schema: type: integer description: 'Filtrar eventos por el ID de la compañía organizadora.' example: 1 nullable: false - in: query name: minigame_id description: 'Filtrar eventos que incluyan un minijuego específico por su ID.' example: 2 required: false schema: type: integer description: 'Filtrar eventos que incluyan un minijuego específico por su ID.' example: 2 nullable: false responses: 200: description: '' content: text/plain: schema: type: string example: "{\n\"data\": [\n {\n \"id\": 1,\n \"description\": \"Gran Torneo de Verano\",\n \"duration\": \"7 days\",\n \"isActive\": true,\n \"city\": \"Pasto\",\n \"company\": {\n \"id\": 1,\n \"name\": \"Arcade Central Pasto\"\n },\n \"minigames\": [\n {\n \"id\": 1,\n \"name\": \"Space Invaders\"\n },\n {\n \"id\": 2,\n \"name\": \"Tetris Challenge\"\n }\n ]\n }\n],\n}" tags: - Filtros security: [] /api/match/create: post: summary: 'Crear una nueva sala de juego.' operationId: crearUnaNuevaSalaDeJuego description: "Este endpoint permite crear una sala automáticamente con un nombre único\ny asignar al usuario autenticado como propietario. La sala puede ser\npública o privada según el parámetro enviado." parameters: [] responses: 201: description: '' content: text/plain: schema: type: string example: "{\n \"status\": \"success\",\n \"data\": {\n \"id\": 1,\n \"name\": \"Room-ABCD12\",\n \"owner_id\": 5,\n \"status\": \"creada\",\n \"privacidad\": \"publica\",\n \"created_at\": \"2025-10-08T16:41:12.000000Z\",\n \"updated_at\": \"2025-10-08T16:41:12.000000Z\"\n }\n} \"La respuesta incluye los datos completos de la sala creada, mostrando su estado inicial, privacidad y propietario.\"" 401: description: '' content: text/plain: schema: type: string example: "{\n \"message\": \"Unauthenticated.\"\n} \"Se retorna cuando el usuario no está autenticado y no puede crear la sala.\"" tags: - Rooms requestBody: required: true content: application/json: schema: type: object properties: privacidad: type: string description: 'Define la privacidad de la sala. Puede ser "publica" o "privada".' example: publica nullable: false required: - privacidad '/api/match/join/{room_name}': post: summary: 'Unirse a una sala privada.' operationId: unirseAUnaSalaPrivada description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: status: success data: room_name: Room-ABCD12 users: - id: 1 name: Harvey - id: 2 name: Pablo user_count: 2 properties: status: type: string example: success data: type: object properties: room_name: type: string example: Room-ABCD12 users: type: array example: - id: 1 name: Harvey - id: 2 name: Pablo items: type: object properties: id: type: integer example: 1 name: type: string example: Harvey user_count: type: integer example: 2 403: description: '' content: application/json: schema: type: object example: status: error message: 'La sala ya está completa.' properties: status: type: string example: error message: type: string example: 'La sala ya está completa.' 404: description: '' content: application/json: schema: type: object example: status: error message: 'Sala no encontrada.' properties: status: type: string example: error message: type: string example: 'Sala no encontrada.' 423: description: '' content: application/json: schema: type: object example: status: error message: 'Otro usuario está uniéndose a la sala, intenta de nuevo.' properties: status: type: string example: error message: type: string example: 'Otro usuario está uniéndose a la sala, intenta de nuevo.' tags: - Rooms parameters: - in: path name: room_name description: 'Nombre de la sala a la que el usuario quiere unirse.' example: Room-ABCD12 required: true schema: type: string /api/match/joinramdon: post: summary: 'Unirse a una sala pública de forma aleatoria.' operationId: unirseAUnaSalaPblicaDeFormaAleatoria description: "Busca una sala pública con espacio disponible (máximo 2 jugadores).\nSi existe, el usuario se une a ella.\nSi no existe, se crea una nueva sala pública y el usuario se convierte en su propietario." parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: status: success message: 'Te uniste a una sala pública existente.' data: room_name: Room-XYZ123 users: - id: 5 first_name: Harvey - id: 7 first_name: Carlos user_count: 2 properties: status: type: string example: success message: type: string example: 'Te uniste a una sala pública existente.' data: type: object properties: room_name: type: string example: Room-XYZ123 users: type: array example: - id: 5 first_name: Harvey - id: 7 first_name: Carlos items: type: object properties: id: type: integer example: 5 first_name: type: string example: Harvey user_count: type: integer example: 2 201: description: '' content: application/json: schema: type: object example: status: created message: 'No había sala disponible, se creó una nueva pública.' data: room_name: Room-ABCD12 users: - id: 5 first_name: Harvey user_count: 1 properties: status: type: string example: created message: type: string example: 'No había sala disponible, se creó una nueva pública.' data: type: object properties: room_name: type: string example: Room-ABCD12 users: type: array example: - id: 5 first_name: Harvey items: type: object properties: id: type: integer example: 5 first_name: type: string example: Harvey user_count: type: integer example: 1 423: description: '' content: application/json: schema: type: object example: status: error message: 'Otro usuario está uniéndose a una sala, intenta de nuevo.' properties: status: type: string example: error message: type: string example: 'Otro usuario está uniéndose a una sala, intenta de nuevo.' tags: - Rooms '/api/match/start/{room_name}': post: summary: 'Iniciar una partida.' operationId: iniciarUnaPartida description: "Verifica si el usuario pertenece a la sala y si hay al menos 2 jugadores\npara poder iniciar la partida , la idea general es que cuando se cree la sala o se una a la sala ramdon o privada lo pase al star para ver el contrincante." parameters: [] responses: 200: description: '' content: application/json: schema: oneOf: - description: '' type: object example: status: incompleto users: - id: 5 first_name: Carlos message: 'Esperando jugadores.' properties: status: type: string example: incompleto users: type: array example: - id: 5 first_name: Carlos items: type: object properties: id: type: integer example: 5 first_name: type: string example: Carlos message: type: string example: 'Esperando jugadores.' - description: '' type: object example: status: success message: 'Partida iniciada.' data: room_name: Room-ABCD12 users: - id: 5 first_name: Carlos - id: 6 first_name: Ana properties: status: type: string example: success message: type: string example: 'Partida iniciada.' data: type: object properties: room_name: type: string example: Room-ABCD12 users: type: array example: - id: 5 first_name: Carlos - id: 6 first_name: Ana items: type: object properties: id: type: integer example: 5 first_name: type: string example: Carlos 403: description: '' content: application/json: schema: type: object example: status: error message: 'No tienes acceso a esta sala.' properties: status: type: string example: error message: type: string example: 'No tienes acceso a esta sala.' 404: description: '' content: application/json: schema: type: object example: status: error message: 'Sala no encontrada.' properties: status: type: string example: error message: type: string example: 'Sala no encontrada.' tags: - Rooms parameters: - in: path name: room_name description: 'El nombre único de la sala.' example: Room-ABCD12 required: true schema: type: string '/api/match/deal/{room_name}': post: summary: 'Repartir cartas a un jugador en la sala.' operationId: repartirCartasAUnJugadorEnLaSala description: '' parameters: [] responses: 200: description: '' content: application/json: schema: type: object example: status: success message: 'Cartas asignadas.' cards: - id: 12 name: 'Fuego Básico' element: fire power: 3 sprite_key: fire_basic win_effect: fire_blast lose_effect: smoke - id: 20 name: 'Agua Básica' element: water power: 2 sprite_key: water_basic win_effect: water_splash lose_effect: drowned properties: status: type: string example: success message: type: string example: 'Cartas asignadas.' cards: type: array example: - id: 12 name: 'Fuego Básico' element: fire power: 3 sprite_key: fire_basic win_effect: fire_blast lose_effect: smoke - id: 20 name: 'Agua Básica' element: water power: 2 sprite_key: water_basic win_effect: water_splash lose_effect: drowned items: type: object properties: id: type: integer example: 12 name: type: string example: 'Fuego Básico' element: type: string example: fire power: type: integer example: 3 sprite_key: type: string example: fire_basic win_effect: type: string example: fire_blast lose_effect: type: string example: smoke 403: description: '' content: application/json: schema: type: object example: status: error message: 'No tienes acceso a esta sala.' properties: status: type: string example: error message: type: string example: 'No tienes acceso a esta sala.' 404: description: '' content: application/json: schema: type: object example: status: error message: 'Sala no encontrada.' properties: status: type: string example: error message: type: string example: 'Sala no encontrada.' tags: - Rooms parameters: - in: path name: room_name description: 'Nombre único de la sala.' example: Room-ABCD12 required: true schema: type: string