================================================================================ CANYGOO API — DOCUMENTACIÓN DE ENDPOINTS REST Base URL: https://api.canygoo.com/v1 Versión: 1.0.0 Fecha: 31/05/2026 ================================================================================ AUTENTICACIÓN ───────────── Todos los endpoints marcados con [AUTH] requieren el header: Authorization: Bearer El token se obtiene en POST /auth/login o POST /auth/register. Expiración del token: 24 horas. ================================================================================ 1. AUTENTICACIÓN — /auth ================================================================================ POST /auth/register Descripción : Registrar un nuevo usuario Auth : No requerida Body (JSON) : { "name" : "string (requerido)", "email" : "string (requerido, único)", "password" : "string (requerido, mín. 6 caracteres)" } Respuesta 201: { "token" : "JWT_STRING", "user" : { "id" : "string", "name" : "string", "email" : "string", "avatar": "string|null" } } Errores : 400 Datos inválidos | 409 Email ya registrado ──────────────────────────────────────────────────────────────────────────────── POST /auth/login Descripción : Iniciar sesión con email y contraseña Auth : No requerida Body (JSON) : { "email" : "string (requerido)", "password" : "string (requerido)" } Respuesta 200: { "token" : "JWT_STRING", "user" : { "id" : "string", "name" : "string", "email" : "string", "avatar": "string|null" } } Errores : 400 Datos inválidos | 401 Credenciales incorrectas ──────────────────────────────────────────────────────────────────────────────── POST /auth/logout Descripción : Cerrar sesión (invalidar token en blacklist del servidor) Auth : [AUTH] Requerida Body : vacío Respuesta 200: { "message": "Sesión cerrada correctamente" } ──────────────────────────────────────────────────────────────────────────────── GET /auth/me Descripción : Obtener datos del usuario autenticado Auth : [AUTH] Requerida Respuesta 200: { "id" : "string", "name" : "string", "email" : "string", "avatar": "string|null" } Errores : 401 Token inválido o expirado ──────────────────────────────────────────────────────────────────────────────── PATCH /auth/me Descripción : Actualizar perfil del usuario autenticado Auth : [AUTH] Requerida Body (JSON) : { "name" : "string (opcional)", "avatar" : "string URL (opcional)" } Respuesta 200: { usuario actualizado } ──────────────────────────────────────────────────────────────────────────────── POST /auth/change-password Descripción : Cambiar contraseña del usuario autenticado Auth : [AUTH] Requerida Body (JSON) : { "currentPassword" : "string (requerido)", "newPassword" : "string (requerido, mín. 6 caracteres)" } Respuesta 200: { "message": "Contraseña actualizada correctamente" } Errores : 400 Contraseña actual incorrecta ================================================================================ 2. PASEADORES — /walkers ================================================================================ GET /walkers Descripción : Listar todos los paseadores disponibles Auth : No requerida Query params: ?city=string &minPrice=number &maxPrice=number &minRating=number &availability=string (día de la semana) Respuesta 200: [ { "id" : "string", "name" : "string", "photo" : "string URL", "description" : "string", "pricePerHour": "number", "maxPets" : "number", "rating" : "number", "reviews" : "number", "availability": ["string"], "location" : { "latitude": number, "longitude": number }, "services" : ["string"], "city" : "string|null" } ] ──────────────────────────────────────────────────────────────────────────────── GET /walkers/:id Descripción : Obtener detalle completo de un paseador Auth : No requerida Respuesta 200: { "id" : "string", "name" : "string", "photo" : "string URL", "description" : "string", "pricePerHour": "number", "maxPets" : "number", "rating" : "number", "reviews" : "number", "availability": ["string"], "location" : { "latitude": number, "longitude": number }, "route" : [{ "latitude": number, "longitude": number }], "services" : ["string"], "phone" : "string", "email" : "string", "city" : "string|null" } Errores : 404 Paseador no encontrado ================================================================================ 3. SOLICITUDES DE SERVICIO — /requests ================================================================================ POST /requests/walker Descripción : Crear solicitud de servicio de paseo Auth : [AUTH] Requerida Body (JSON) : { "walkerId" : "string (requerido)", "clientName" : "string (requerido)", "clientEmail" : "string (requerido)", "clientPhone" : "string (requerido)", "requestedDate" : "string YYYY-MM-DD (requerido)", "requestedTime" : "string HH:MM (requerido)", "numPets" : "number", "duration" : "string", "message" : "string" } Respuesta 201: { "id" : "string", "type" : "walker", "status" : "pending", "createdAt" : "ISO8601 string", ...campos del body } Errores : 400 Datos inválidos | 404 Paseador no encontrado ──────────────────────────────────────────────────────────────────────────────── POST /requests/adoption Descripción : Crear solicitud de adopción de mascota en refugio Auth : [AUTH] Requerida Body (JSON) : { "shelterId" : "string (requerido)", "petId" : "string (requerido)", "clientName" : "string (requerido)", "clientEmail" : "string (requerido)", "clientPhone" : "string (requerido)", "requestedDate" : "string YYYY-MM-DD (requerido)", "requestedTime" : "string HH:MM (requerido)", "experience" : "string", "homeType" : "string", "message" : "string" } Respuesta 201: { "id" : "string", "type" : "shelter", "status" : "pending", "createdAt" : "ISO8601 string", ...campos del body } Errores : 400 Datos inválidos | 404 Refugio/Mascota no encontrado 409 Mascota ya reservada o adoptada ──────────────────────────────────────────────────────────────────────────────── POST /requests/trainer Descripción : Crear solicitud de servicio de adiestramiento Auth : [AUTH] Requerida Body (JSON) : { "trainerId" : "string (requerido)", "serviceId" : "string (requerido)", "clientName" : "string (requerido)", "clientEmail" : "string (requerido)", "clientPhone" : "string (requerido)", "requestedDate" : "string YYYY-MM-DD (requerido)", "requestedTime" : "string HH:MM (requerido)", "dogName" : "string", "dogAge" : "string", "behaviorIssues" : "string", "message" : "string" } Respuesta 201: { "id" : "string", "type" : "trainer", "status" : "pending", "createdAt" : "ISO8601 string", ...campos del body } Errores : 400 Datos inválidos | 404 Adiestrador/Servicio no encontrado ──────────────────────────────────────────────────────────────────────────────── GET /requests/me Descripción : Listar todas las solicitudes del usuario autenticado Auth : [AUTH] Requerida Query params: ?type=walker|shelter|trainer &status=pending|accepted|rejected Respuesta 200: [ { ...ServiceRequest } ] ──────────────────────────────────────────────────────────────────────────────── GET /requests/:id Descripción : Obtener detalle de una solicitud específica del usuario Auth : [AUTH] Requerida Respuesta 200: { ...ServiceRequest } Errores : 403 No autorizado | 404 Solicitud no encontrada ──────────────────────────────────────────────────────────────────────────────── DELETE /requests/:id Descripción : Cancelar una solicitud (solo si está en estado "pending") Auth : [AUTH] Requerida Respuesta 200: { "message": "Solicitud cancelada" } Errores : 403 No autorizado | 404 No encontrada 409 No se puede cancelar (ya aceptada/rechazada) ================================================================================ 4. REFUGIOS — /shelters ================================================================================ GET /shelters Descripción : Listar todos los refugios Auth : No requerida Query params: ?city=string &hasPetsAvailable=boolean Respuesta 200: [ { "id" : "string", "name" : "string", "logo" : "string URL", "description" : "string", "address" : "string", "phone" : "string", "email" : "string", "website" : "string", "openingHours": "string", "location" : { "latitude": number, "longitude": number }, "petsCount" : "number (total mascotas disponibles)" } ] ──────────────────────────────────────────────────────────────────────────────── GET /shelters/:id Descripción : Obtener detalle de un refugio con sus mascotas Auth : No requerida Respuesta 200: { "id" : "string", "name" : "string", "logo" : "string URL", "description" : "string", "address" : "string", "phone" : "string", "email" : "string", "website" : "string", "openingHours": "string", "location" : { "latitude": number, "longitude": number }, "pets" : [ { ...Pet } ] } Errores : 404 Refugio no encontrado ──────────────────────────────────────────────────────────────────────────────── GET /shelters/:id/pets Descripción : Listar mascotas de un refugio con filtros Auth : No requerida Query params: ?type=perro|gato|... &status=available|adopted|reserved &size=pequeño|mediano|grande &gender=macho|hembra Respuesta 200: [ { ...Pet } ] ──────────────────────────────────────────────────────────────────────────────── GET /shelters/:shelterId/pets/:petId Descripción : Obtener detalle de una mascota concreta Auth : No requerida Respuesta 200: { ...Pet } Errores : 404 Mascota o refugio no encontrado ================================================================================ 5. ADIESTRADORES — /trainers ================================================================================ GET /trainers Descripción : Listar todos los adiestradores Auth : No requerida Query params: ?city=string &specialty=string &minRating=number Respuesta 200: [ { "id" : "string", "name" : "string", "logo" : "string URL", "description" : "string", "trainer" : "string (nombre del adiestrador)", "trainerPhoto": "string URL", "rating" : "number", "reviews" : "number", "experience" : "string", "specialties" : ["string"], "address" : "string", "city" : "string|null" } ] ──────────────────────────────────────────────────────────────────────────────── GET /trainers/:id Descripción : Obtener detalle completo de un adiestrador con sus servicios Auth : No requerida Respuesta 200: { "id" : "string", "name" : "string", "logo" : "string URL", "description" : "string", "trainer" : "string", "trainerPhoto" : "string URL", "rating" : "number", "reviews" : "number", "experience" : "string", "certifications": ["string"], "specialties" : ["string"], "address" : "string", "phone" : "string", "email" : "string", "website" : "string", "location" : { "latitude": number, "longitude": number }, "services" : [ { ...TrainerService } ] } Errores : 404 Adiestrador no encontrado ──────────────────────────────────────────────────────────────────────────────── GET /trainers/:id/services Descripción : Listar servicios de un adiestrador Auth : No requerida Respuesta 200: [ { ...TrainerService } ] ──────────────────────────────────────────────────────────────────────────────── GET /trainers/:trainerId/services/:serviceId Descripción : Obtener detalle de un servicio de adiestrador Auth : No requerida Respuesta 200: { "id" : "string", "name" : "string", "description" : "string", "duration" : "string", "price" : "number", "sessionsPerWeek": "number", "groupSize" : "number", "availableDays" : ["string"], "image" : "string URL", "includes" : ["string"], "requirements" : ["string"] } Errores : 404 Servicio no encontrado ================================================================================ 6. TIENDA — /products ================================================================================ GET /products Descripción : Listar productos de la tienda con filtros y paginación Auth : No requerida Query params: ?category=string (ej. Alimentación, Higiene, Salud, Accesorios) &subcategory=string &brand=string &minPrice=number &maxPrice=number &onSale=boolean &featured=boolean &new=boolean &minRating=number &sortBy=price_asc|price_desc|rating|newest &page=number (default 1) &limit=number (default 20) Respuesta 200: { "data" : [ { ...Product } ], "total" : "number", "page" : "number", "totalPages": "number" } ──────────────────────────────────────────────────────────────────────────────── GET /products/featured Descripción : Listar productos destacados para la página principal Auth : No requerida Query params: ?limit=number (default 6) Respuesta 200: [ { ...Product } ] ──────────────────────────────────────────────────────────────────────────────── GET /products/categories Descripción : Obtener lista de categorías y subcategorías disponibles Auth : No requerida Respuesta 200: [ { "name" : "string", "subcategories": ["string"] } ] ──────────────────────────────────────────────────────────────────────────────── GET /products/:id Descripción : Obtener detalle completo de un producto Auth : No requerida Respuesta 200: { "id" : "string", "name" : "string", "category" : "string", "subcategory" : "string", "price" : "number", "originalPrice": "number", "discount" : "number (porcentaje)", "image" : "string URL", "images" : ["string URL"], "description" : "string", "features" : ["string"], "weight" : "string", "brand" : "string", "stock" : "number", "rating" : "number", "reviews" : "number", "featured" : "boolean", "new" : "boolean", "onSale" : "boolean" } Errores : 404 Producto no encontrado ================================================================================ 7. PEDIDOS (CARRITO) — /orders ================================================================================ POST /orders Descripción : Crear un nuevo pedido a partir del carrito Auth : [AUTH] Requerida Body (JSON) : { "items": [ { "productId" : "string (requerido)", "quantity" : "number (requerido, mín. 1)" } ], "shippingAddress": { "name" : "string", "address" : "string", "city" : "string", "postalCode": "string", "country" : "string (default: ES)" }, "paymentMethod": "card|paypal|bizum" } Respuesta 201: { "id" : "string", "status" : "pending", "items" : [ { producto + cantidad + precio } ], "subtotal" : "number", "shippingCost" : "number", "total" : "number", "shippingAddress": { ...dirección }, "createdAt" : "ISO8601 string", "estimatedDelivery": "string" } Errores : 400 Datos inválidos | 409 Stock insuficiente para algún producto ──────────────────────────────────────────────────────────────────────────────── GET /orders/me Descripción : Listar todos los pedidos del usuario autenticado Auth : [AUTH] Requerida Query params: ?status=pending|processing|shipped|delivered|cancelled Respuesta 200: [ { "id" : "string", "status" : "string", "total" : "number", "itemCount": "number", "createdAt": "ISO8601 string" } ] ──────────────────────────────────────────────────────────────────────────────── GET /orders/:id Descripción : Obtener detalle completo de un pedido del usuario Auth : [AUTH] Requerida Respuesta 200: { ...Order completo } Errores : 403 No autorizado | 404 Pedido no encontrado ──────────────────────────────────────────────────────────────────────────────── DELETE /orders/:id Descripción : Cancelar un pedido (solo si está en estado "pending") Auth : [AUTH] Requerida Respuesta 200: { "message": "Pedido cancelado correctamente" } Errores : 403 No autorizado | 404 No encontrado 409 No se puede cancelar (ya en procesamiento o enviado) ================================================================================ 8. VALORACIONES — /reviews ================================================================================ POST /reviews/walker/:walkerId Descripción : Añadir valoración a un paseador Auth : [AUTH] Requerida Body (JSON) : { "rating" : "number 1-5 (requerido)", "comment" : "string (opcional)" } Respuesta 201: { "id": "string", "rating": number, "comment": "string", "createdAt": "ISO8601" } Errores : 400 Rating inválido | 409 Ya valorado ──────────────────────────────────────────────────────────────────────────────── POST /reviews/trainer/:trainerId Descripción : Añadir valoración a un adiestrador Auth : [AUTH] Requerida Body/Respuesta: igual que /reviews/walker/:walkerId ──────────────────────────────────────────────────────────────────────────────── POST /reviews/product/:productId Descripción : Añadir valoración a un producto (requiere haberlo comprado) Auth : [AUTH] Requerida Body (JSON) : { "rating" : "number 1-5 (requerido)", "comment" : "string (opcional)" } Respuesta 201: { "id": "string", "rating": number, "comment": "string", "createdAt": "ISO8601" } Errores : 400 Rating inválido | 403 Debes comprar el producto antes 409 Ya valorado ================================================================================ RESUMEN DE ENDPOINTS ================================================================================ MÓDULO | MÉTODO | ENDPOINT | AUTH ──────────────────────────────────────────────────────────────────────────── Auth | POST | /auth/register | No Auth | POST | /auth/login | No Auth | POST | /auth/logout | Sí Auth | GET | /auth/me | Sí Auth | PATCH | /auth/me | Sí Auth | POST | /auth/change-password | Sí ──────────────────────────────────────────────────────────────────────────── Paseadores | GET | /walkers | No Paseadores | GET | /walkers/:id | No ──────────────────────────────────────────────────────────────────────────── Solicitudes | POST | /requests/walker | Sí Solicitudes | POST | /requests/adoption | Sí Solicitudes | POST | /requests/trainer | Sí Solicitudes | GET | /requests/me | Sí Solicitudes | GET | /requests/:id | Sí Solicitudes | DELETE | /requests/:id | Sí ──────────────────────────────────────────────────────────────────────────── Refugios | GET | /shelters | No Refugios | GET | /shelters/:id | No Refugios | GET | /shelters/:id/pets | No Refugios | GET | /shelters/:shelterId/pets/:petId | No ──────────────────────────────────────────────────────────────────────────── Adiestradores | GET | /trainers | No Adiestradores | GET | /trainers/:id | No Adiestradores | GET | /trainers/:id/services | No Adiestradores | GET | /trainers/:trainerId/services/:serviceId| No ──────────────────────────────────────────────────────────────────────────── Tienda | GET | /products | No Tienda | GET | /products/featured | No Tienda | GET | /products/categories | No Tienda | GET | /products/:id | No ──────────────────────────────────────────────────────────────────────────── Pedidos | POST | /orders | Sí Pedidos | GET | /orders/me | Sí Pedidos | GET | /orders/:id | Sí Pedidos | DELETE | /orders/:id | Sí ──────────────────────────────────────────────────────────────────────────── Valoraciones | POST | /reviews/walker/:walkerId | Sí Valoraciones | POST | /reviews/trainer/:trainerId | Sí Valoraciones | POST | /reviews/product/:productId | Sí ──────────────────────────────────────────────────────────────────────────── TOTAL | 30 endpoints ================================================================================ NOTAS TÉCNICAS PARA EL BACKEND ================================================================================ 1. TECNOLOGÍA RECOMENDADA Node.js + Express o NestJS Base de datos: PostgreSQL o MongoDB ORM: Prisma (SQL) o Mongoose (MongoDB) JWT: jsonwebtoken (HS256), expiración 24h Almacenamiento imágenes: AWS S3 o Cloudinary 2. CABECERAS CORS NECESARIAS Access-Control-Allow-Origin : * (dev) / dominio específico (prod) Access-Control-Allow-Methods : GET, POST, PATCH, DELETE, OPTIONS Access-Control-Allow-Headers : Authorization, Content-Type 3. FORMATO DE RESPUESTA DE ERROR Todos los errores devuelven: { "error" : "CODIGO_ERROR", "message": "Descripción legible del error" } 4. PAGINACIÓN (donde aplica) Parámetros : ?page=1&limit=20 Respuesta : { "data": [...], "total": N, "page": N, "totalPages": N } 5. VALIDACIONES RECOMENDADAS - Email: formato RFC 5322 - Contraseñas: mínimo 6 caracteres - Teléfonos: formato E.164 o nacional español - Fechas: ISO 8601 (YYYY-MM-DD) - IDs: UUID v4 recomendado 6. VARIABLE A CAMBIAR EN LA APP (authService.ts) Línea: export const API_URL = 'https://api.canygoo.com/v1'; Cambiar a la URL real del servidor cuando esté desplegado. ================================================================================ FIN DEL DOCUMENTO ================================================================================