{"openapi":"3.1.0","info":{"version":"1.0.0","title":"Servitrans API","description":"API REST para la plataforma de trámites vehiculares de Servitrans"},"servers":[{"url":"https://api.servitrans.co","description":"API de Producción"}],"components":{"schemas":{},"parameters":{}},"paths":{"/health/database":{"get":{"tags":["Health"],"summary":"Database health check","responses":{"200":{"description":"Database connection status","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok","error"]},"message":{"type":"string"},"latency":{"type":"number"},"timestamp":{"type":"string"}},"required":["status","timestamp"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/register":{"post":{"tags":["Authentication"],"summary":"Register a new user","description":"Create a new user account with the provided credentials","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":8},"fullName":{"type":"string","minLength":1},"documentType":{"type":"string"},"documentNumber":{"type":"string"},"phone":{"type":"string"}},"required":["email","password","fullName"]}}}},"responses":{"201":{"description":"User registered successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"fullName":{"type":"string"},"role":{"type":"string"}},"required":["id","email","role"]},"tokens":{"type":"object","properties":{"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"expiresIn":{"type":"number"}},"required":["accessToken","refreshToken","expiresIn"]}},"required":["message","user","tokens"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/login":{"post":{"tags":["Authentication"],"summary":"Login user","description":"Authenticate user with email and password","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":1}},"required":["email","password"]}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"fullName":{"type":"string"},"role":{"type":"string"}},"required":["id","email","role"]},"tokens":{"type":"object","properties":{"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"expiresIn":{"type":"number"}},"required":["accessToken","refreshToken","expiresIn"]}},"required":["message","user","tokens"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/refresh":{"post":{"tags":["Authentication"],"summary":"Refresh access token","description":"Get a new access token using a valid refresh token","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"refreshToken":{"type":"string","minLength":1}},"required":["refreshToken"]}}}},"responses":{"200":{"description":"Token refreshed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"tokens":{"type":"object","properties":{"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"expiresIn":{"type":"number"}},"required":["accessToken","refreshToken","expiresIn"]}},"required":["message","tokens"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/verify-token":{"post":{"tags":["Authentication"],"summary":"Verify token","description":"Check if an access token is valid","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Token verification result","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"fullName":{"type":"string"},"role":{"type":"string"}},"required":["id","email","role"]},"message":{"type":"string"}},"required":["valid","message"]}}}},"401":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"fullName":{"type":"string"},"role":{"type":"string"}},"required":["id","email","role"]},"message":{"type":"string"}},"required":["valid","message"]}}}}}}},"/auth/verify-email":{"post":{"tags":["Authentication"],"summary":"Verify email address","description":"Verify user email address with verification token","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":1},"email":{"type":"string","format":"email"}},"required":["token","email"]}}}},"responses":{"200":{"description":"Email verified successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"success":{"type":"boolean"}},"required":["message","success"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/resend-verification":{"post":{"tags":["Authentication"],"summary":"Resend email verification","description":"Resend email verification token to user","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}},"responses":{"200":{"description":"Verification email resent successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"success":{"type":"boolean"}},"required":["message","success"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/request-password-reset":{"post":{"tags":["Authentication"],"summary":"Request password reset","description":"Send a password reset email to the user","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}},"responses":{"200":{"description":"Password reset email sent (or email not found)","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"success":{"type":"boolean"}},"required":["message","success"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/reset-password":{"post":{"tags":["Authentication"],"summary":"Reset password","description":"Reset user password with a valid token","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","minLength":1},"newPassword":{"type":"string","minLength":8}},"required":["token","newPassword"]}}}},"responses":{"200":{"description":"Password reset successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"success":{"type":"boolean"}},"required":["message","success"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/logout":{"post":{"tags":["Authentication"],"summary":"Logout user","description":"Invalidate the current user session","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Logout successful","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/me":{"get":{"tags":["Authentication"],"summary":"Get current user","description":"Get the authenticated user information","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User information retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string"},"fullName":{"type":"string"},"documentType":{"type":"string"},"documentNumber":{"type":"string"},"phone":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"department":{"type":"string"},"createdAt":{"nullable":true}},"required":["id","email","role"]}},"required":["user"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/auth/website-token":{"post":{"tags":["Authentication"],"summary":"Generate website JWT (admin only)","description":"Generates a long-lived JWT for the public website. Use this token in Authorization header to call protected website endpoints (e.g. tramites catalog).","responses":{"200":{"description":"Website token generated","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"expiresAt":{"type":"string","description":"ISO date when token expires (100 years)"}},"required":["token","expiresAt"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/countries":{"get":{"tags":["Countries"],"summary":"Get all active countries","responses":{"200":{"description":"List of all active countries","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"code":{"type":"string","nullable":true},"isoName":{"type":"string","nullable":true},"codigoDane":{"type":"string","nullable":true},"isActive":{"type":"boolean"},"odooId":{"type":"number","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","code","isoName","codigoDane","isActive","odooId","createdAt","updatedAt"]}}}}}}}},"/countries/{id}":{"get":{"tags":["Countries"],"summary":"Get country by ID","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Country details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"code":{"type":"string","nullable":true},"isoName":{"type":"string","nullable":true},"codigoDane":{"type":"string","nullable":true},"isActive":{"type":"boolean"},"odooId":{"type":"number","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","name","code","isoName","codigoDane","isActive","odooId","createdAt","updatedAt"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/departments":{"get":{"tags":["Departments"],"summary":"Get all Colombian departments","responses":{"200":{"description":"List of all departments","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"region":{"type":"string"}},"required":["code","name"]}}}}}}}},"/departments/{code}":{"get":{"tags":["Departments"],"summary":"Get department by code","parameters":[{"schema":{"type":"string","example":"05"},"required":true,"name":"code","in":"path"}],"responses":{"200":{"description":"Department details","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"region":{"type":"string"}},"required":["code","name"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/cities":{"get":{"tags":["Cities"],"summary":"Get cities by department code","parameters":[{"schema":{"type":"string","example":"05"},"required":false,"name":"departmentCode","in":"query"}],"responses":{"200":{"description":"List of cities in the department","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"departmentId":{"type":"string"},"departmentCode":{"type":"string"},"departmentName":{"type":"string"},"processingDays":{"type":"number","nullable":true},"specialNotes":{"type":"string","nullable":true},"isActive":{"type":"boolean"}},"required":["id","code","name","departmentId","processingDays","specialNotes","isActive"]}}}}}}}},"/cities/catalog":{"get":{"tags":["Cities"],"summary":"Get cities catalog (website)","description":"Returns cities with id, code, name, department. Auth: Bearer token (portal or website token). Optional filter by department code.","parameters":[{"schema":{"type":"string","description":"Filter by department code (e.g. 05 for Antioquia)","example":"05"},"required":false,"description":"Filter by department code (e.g. 05 for Antioquia)","name":"departmentCode","in":"query"}],"responses":{"200":{"description":"List of cities","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"departmentId":{"type":"string"},"departmentCode":{"type":"string"},"departmentName":{"type":"string"},"processingDays":{"type":"number","nullable":true},"specialNotes":{"type":"string","nullable":true},"isActive":{"type":"boolean"}},"required":["id","code","name","departmentId","processingDays","specialNotes","isActive"]}}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/cities/search":{"get":{"tags":["Cities"],"summary":"Search cities by name","parameters":[{"schema":{"type":"string","minLength":2,"example":"Medellín"},"required":true,"name":"q","in":"query"},{"schema":{"type":"string","example":"10"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"departmentId":{"type":"string"},"departmentCode":{"type":"string"},"departmentName":{"type":"string"},"processingDays":{"type":"number","nullable":true},"specialNotes":{"type":"string","nullable":true},"isActive":{"type":"boolean"}},"required":["id","code","name","departmentId","processingDays","specialNotes","isActive"]}}}}}}}},"/cities/{code}":{"get":{"tags":["Cities"],"summary":"Get city by code","parameters":[{"schema":{"type":"string","example":"05001"},"required":true,"name":"code","in":"path"}],"responses":{"200":{"description":"City details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"departmentId":{"type":"string"},"departmentCode":{"type":"string"},"departmentName":{"type":"string"},"processingDays":{"type":"number","nullable":true},"specialNotes":{"type":"string","nullable":true},"isActive":{"type":"boolean"}},"required":["id","code","name","departmentId","processingDays","specialNotes","isActive"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/transit-agencies":{"get":{"tags":["Transit Agencies"],"summary":"Get all transit agencies","responses":{"200":{"description":"List of all transit agencies","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"odooId":{"type":"number","nullable":true},"name":{"type":"string"},"nit":{"type":"string","nullable":true},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","odooId","name","nit","isActive","createdAt","updatedAt"]}}}}}}}},"/transit-agencies/{id}":{"get":{"tags":["Transit Agencies"],"summary":"Get transit agency by ID","parameters":[{"schema":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Transit agency details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"odooId":{"type":"number","nullable":true},"name":{"type":"string"},"nit":{"type":"string","nullable":true},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","odooId","name","nit","isActive","createdAt","updatedAt"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/deliveries/offices":{"get":{"tags":["Deliveries"],"summary":"List delivery offices","description":"Returns active delivery offices for pickup location selection.","responses":{"200":{"description":"List of active delivery offices","content":{"application/json":{"schema":{"type":"object","properties":{"offices":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"department":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","nullable":true},"isActive":{"type":"boolean"}},"required":["id","code","name","address","city","department","phone","isActive"]}}},"required":["offices"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/deliveries":{"get":{"tags":["Deliveries"],"summary":"List entregas (completed tramites with optional delivery)","description":"Returns completed tramites for the current user (customer: own; operator: assigned; admin: all), each with its delivery data if exists.","responses":{"200":{"description":"List of completed tramites with delivery","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"tramite":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string","nullable":true},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","nullable":true},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"anyOf":[{"type":"number"},{"type":"string"}]},"notes":{"type":"string","nullable":true},"odooSolicitudNumero":{"type":"string","nullable":true},"completedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"type":{"type":"string"},"cityName":{"type":"string"}},"required":["id","userId","tramiteTypeId","status","city","department","totalAmount","createdAt","updatedAt"]},"delivery":{"type":"object","nullable":true,"properties":{"id":{"type":"string","format":"uuid"},"tramiteId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"deliveryType":{"type":"string","enum":["pickup","shipping"]},"status":{"type":"string","enum":["pending","ready","in_transit","delivered","cancelled"]},"pickupLocation":{"type":"string","nullable":true},"pickupDate":{"type":"string","nullable":true},"pickupTime":{"type":"string","nullable":true},"shippingAddress":{"type":"string","nullable":true},"shippingCity":{"type":"string","nullable":true},"shippingDepartment":{"type":"string","nullable":true},"shippingPostalCode":{"type":"string","nullable":true},"shippingCarrier":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"shippingCost":{"type":"object","nullable":true,"properties":{"amount":{"type":"number"},"currency":{"type":"string"},"paid":{"type":"boolean"}},"required":["amount","currency","paid"]},"deliveredAt":{"type":"string","nullable":true},"deliveredTo":{"type":"string","nullable":true},"deliveryProof":{"type":"string","nullable":true},"deliveryNotes":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tramiteId","userId","deliveryType","status","createdAt","updatedAt"]}},"required":["tramite","delivery"]}}},"required":["items"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"post":{"tags":["Deliveries"],"summary":"Create delivery for a completed tramite","description":"Add delivery data (address, carrier, tracking, etc.) for a tramite that is in completed status. One delivery per tramite.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tramiteId":{"type":"string","format":"uuid"},"deliveryType":{"type":"string","enum":["pickup","shipping"]},"status":{"type":"string","enum":["pending","ready","in_transit","delivered","cancelled"],"default":"pending"},"pickupLocation":{"type":"string"},"pickupDate":{"type":"string"},"pickupTime":{"type":"string"},"shippingAddress":{"type":"string"},"shippingCity":{"type":"string"},"shippingDepartment":{"type":"string"},"shippingPostalCode":{"type":"string"},"shippingCarrier":{"type":"string"},"trackingNumber":{"type":"string"},"shippingCost":{"type":"object","properties":{"amount":{"type":"number"},"currency":{"type":"string"},"paid":{"type":"boolean"}},"required":["amount","currency","paid"]},"deliveryNotes":{"type":"string"},"metadata":{"type":"object","properties":{"estimatedDeliveryDate":{"type":"string"},"specialInstructions":{"type":"string"}}}},"required":["tramiteId","deliveryType"]}}}},"responses":{"201":{"description":"Delivery created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tramiteId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"deliveryType":{"type":"string","enum":["pickup","shipping"]},"status":{"type":"string","enum":["pending","ready","in_transit","delivered","cancelled"]},"pickupLocation":{"type":"string","nullable":true},"pickupDate":{"type":"string","nullable":true},"pickupTime":{"type":"string","nullable":true},"shippingAddress":{"type":"string","nullable":true},"shippingCity":{"type":"string","nullable":true},"shippingDepartment":{"type":"string","nullable":true},"shippingPostalCode":{"type":"string","nullable":true},"shippingCarrier":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"shippingCost":{"type":"object","nullable":true,"properties":{"amount":{"type":"number"},"currency":{"type":"string"},"paid":{"type":"boolean"}},"required":["amount","currency","paid"]},"deliveredAt":{"type":"string","nullable":true},"deliveredTo":{"type":"string","nullable":true},"deliveryProof":{"type":"string","nullable":true},"deliveryNotes":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tramiteId","userId","deliveryType","status","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/deliveries/{id}":{"get":{"tags":["Deliveries"],"summary":"Get delivery by id","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Delivery","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tramiteId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"deliveryType":{"type":"string","enum":["pickup","shipping"]},"status":{"type":"string","enum":["pending","ready","in_transit","delivered","cancelled"]},"pickupLocation":{"type":"string","nullable":true},"pickupDate":{"type":"string","nullable":true},"pickupTime":{"type":"string","nullable":true},"shippingAddress":{"type":"string","nullable":true},"shippingCity":{"type":"string","nullable":true},"shippingDepartment":{"type":"string","nullable":true},"shippingPostalCode":{"type":"string","nullable":true},"shippingCarrier":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"shippingCost":{"type":"object","nullable":true,"properties":{"amount":{"type":"number"},"currency":{"type":"string"},"paid":{"type":"boolean"}},"required":["amount","currency","paid"]},"deliveredAt":{"type":"string","nullable":true},"deliveredTo":{"type":"string","nullable":true},"deliveryProof":{"type":"string","nullable":true},"deliveryNotes":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tramiteId","userId","deliveryType","status","createdAt","updatedAt"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"patch":{"tags":["Deliveries"],"summary":"Update delivery","description":"Update delivery data (address, carrier, tracking, status, etc.)","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"deliveryType":{"type":"string","enum":["pickup","shipping"]},"status":{"type":"string","enum":["pending","ready","in_transit","delivered","cancelled"],"default":"pending"},"pickupLocation":{"type":"string"},"pickupDate":{"type":"string"},"pickupTime":{"type":"string"},"shippingAddress":{"type":"string"},"shippingCity":{"type":"string"},"shippingDepartment":{"type":"string"},"shippingPostalCode":{"type":"string"},"shippingCarrier":{"type":"string"},"trackingNumber":{"type":"string"},"shippingCost":{"type":"object","properties":{"amount":{"type":"number"},"currency":{"type":"string"},"paid":{"type":"boolean"}},"required":["amount","currency","paid"]},"deliveryNotes":{"type":"string"},"metadata":{"type":"object","properties":{"estimatedDeliveryDate":{"type":"string"},"specialInstructions":{"type":"string"}}}}}}}},"responses":{"200":{"description":"Delivery updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tramiteId":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"deliveryType":{"type":"string","enum":["pickup","shipping"]},"status":{"type":"string","enum":["pending","ready","in_transit","delivered","cancelled"]},"pickupLocation":{"type":"string","nullable":true},"pickupDate":{"type":"string","nullable":true},"pickupTime":{"type":"string","nullable":true},"shippingAddress":{"type":"string","nullable":true},"shippingCity":{"type":"string","nullable":true},"shippingDepartment":{"type":"string","nullable":true},"shippingPostalCode":{"type":"string","nullable":true},"shippingCarrier":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"shippingCost":{"type":"object","nullable":true,"properties":{"amount":{"type":"number"},"currency":{"type":"string"},"paid":{"type":"boolean"}},"required":["amount","currency","paid"]},"deliveredAt":{"type":"string","nullable":true},"deliveredTo":{"type":"string","nullable":true},"deliveryProof":{"type":"string","nullable":true},"deliveryNotes":{"type":"string","nullable":true},"metadata":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tramiteId","userId","deliveryType","status","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/document-types":{"get":{"tags":["Document Types"],"summary":"Get all document types","responses":{"200":{"description":"List of all document types","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"name":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","code","name","isActive","createdAt","updatedAt"]}}}}}}}},"/document-types/{code}":{"get":{"tags":["Document Types"],"summary":"Get document type by code","parameters":[{"schema":{"type":"string","example":"CC"},"required":true,"name":"code","in":"path"}],"responses":{"200":{"description":"Document type details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string"},"name":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","code","name","isActive","createdAt","updatedAt"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/documents/upload":{"post":{"tags":["Documents"],"summary":"Upload a document to MinIO","description":"Upload a document file (PDF, JPEG, PNG, WEBP) to MinIO storage. Maximum file size is 10MB.","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"nullable":true,"description":"File to upload (PDF, JPEG, PNG, or WEBP). Max size: 10MB","format":"binary"},"tramiteId":{"type":"string","description":"Optional tramite ID to organize the file"}}}}}},"responses":{"200":{"description":"Document uploaded successfully","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"document.pdf","description":"Original filename"},"url":{"type":"string","format":"uri","example":"https://minio.servitrans.co/tramite-documents/tramites/123/1234567890-abc123.pdf","description":"URL to access the uploaded document"},"type":{"type":"string","example":"application/pdf","description":"MIME type of the document"},"size":{"type":"integer","minimum":0,"exclusiveMinimum":true,"example":1024000,"description":"File size in bytes"},"key":{"type":"string","example":"tramites/123/1234567890-abc123.pdf","description":"Storage key for the document"}},"required":["name","url","type","size","key"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/documents/presigned-url":{"get":{"tags":["Documents"],"summary":"Get presigned URL to view a document","description":"Returns a temporary signed URL to access a document in MinIO. Caller must have access to the tramite. URL expires in 1 hour.","parameters":[{"schema":{"type":"string","description":"Stored document URL (MinIO path)"},"required":true,"description":"Stored document URL (MinIO path)","name":"url","in":"query"},{"schema":{"type":"string","format":"uuid","description":"Tramite ID the document belongs to (for authorization)"},"required":true,"description":"Tramite ID the document belongs to (for authorization)","name":"tramiteId","in":"query"}],"responses":{"200":{"description":"Presigned URL generated","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"Temporary presigned URL"}},"required":["url"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/types":{"get":{"tags":["Tramites"],"summary":"Get all tramite types","parameters":[{"schema":{"type":"string","format":"uuid","example":"f51e5131-0540-43b4-9c18-7b29b07fee17","description":"Optional transit agency ID to filter tramite types"},"required":false,"description":"Optional transit agency ID to filter tramite types","name":"transitAgencyId","in":"query"}],"responses":{"200":{"description":"List of all tramite types","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"description":{"type":"string"},"basePrice":{"type":"number"},"estimatedDays":{"type":"number"},"enabled":{"type":"boolean"},"odooId":{"type":"number","nullable":true}},"required":["code","name","category","basePrice","estimatedDays","enabled"]}}}}}}}},"/tramites/catalog":{"get":{"tags":["Tramites"],"summary":"Get tramites catalog (website)","description":"Returns tramites with name, description, requirements (for given city), and price. Auth: Bearer token (portal or website token). Filter by city and/or tramite name.","parameters":[{"schema":{"type":"string","format":"uuid","description":"Filter by city; also used to return requirements for that city"},"required":false,"description":"Filter by city; also used to return requirements for that city","name":"cityId","in":"query"},{"schema":{"type":"string","description":"Filter by tramite name (substring, case-insensitive)"},"required":false,"description":"Filter by tramite name (substring, case-insensitive)","name":"name","in":"query"},{"schema":{"type":"string","format":"uuid","description":"When provided, price returned is the total for this transit agency; otherwise base price"},"required":false,"description":"When provided, price returned is the total for this transit agency; otherwise base price","name":"transitAgencyId","in":"query"}],"responses":{"200":{"description":"List of tramites for catalog","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"requirements":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true},"required":{"type":"boolean"},"documentType":{"type":"string","nullable":true}},"required":["name","description","required","documentType"]}},"price":{"type":"number"}},"required":["id","name","description","requirements","price"]}}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/types/{code}":{"get":{"tags":["Tramites"],"summary":"Get tramite type by code","parameters":[{"schema":{"type":"string","example":"matricula"},"required":true,"name":"code","in":"path"}],"responses":{"200":{"description":"Tramite type details","content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"description":{"type":"string"},"basePrice":{"type":"number"},"estimatedDays":{"type":"number"},"enabled":{"type":"boolean"},"odooId":{"type":"number","nullable":true}},"required":["code","name","category","basePrice","estimatedDays","enabled"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/requirements":{"get":{"tags":["Tramites"],"summary":"Get tramite requirements by type and city","parameters":[{"schema":{"type":"string","format":"uuid","example":"61e22bcd-f54c-4df6-aec6-2bba92cdcd0c"},"required":true,"name":"tramiteTypeId","in":"query"},{"schema":{"type":"string","format":"uuid","example":"a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d"},"required":true,"name":"cityId","in":"query"}],"responses":{"200":{"description":"List of requirements","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"required":{"type":"boolean"},"documentType":{"type":"string"}},"required":["id","name","description","required"]}}}}}}}},"/tramites/price":{"get":{"tags":["Tramites"],"summary":"Get tramite price","parameters":[{"schema":{"type":"string","format":"uuid","example":"61e22bcd-f54c-4df6-aec6-2bba92cdcd0c"},"required":true,"name":"tramiteTypeId","in":"query"},{"schema":{"type":"string","format":"uuid","example":"f51e5131-0540-43b4-9c18-7b29b07fee17"},"required":true,"name":"transitAgencyId","in":"query"},{"schema":{"type":"string","example":"false"},"required":false,"name":"isUrgent","in":"query"}],"responses":{"200":{"description":"Price details","content":{"application/json":{"schema":{"type":"object","properties":{"basePrice":{"type":"number"},"urgentPrice":{"type":"number"},"taxes":{"type":"number"},"total":{"type":"number"}},"required":["basePrice","taxes","total"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/price-batch":{"post":{"tags":["Tramites"],"summary":"Get aggregated price for multiple tramite types","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tramiteTypeIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1},"transitAgencyId":{"type":"string","format":"uuid"},"isUrgent":{"type":"boolean"}},"required":["tramiteTypeIds","transitAgencyId"]}}}},"responses":{"200":{"description":"Aggregated price and breakdown","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"tramiteTypeId":{"type":"string"},"name":{"type":"string"},"basePrice":{"type":"number"},"transitFee":{"type":"number"},"runtFee":{"type":"number"},"urgentFee":{"type":"number"},"total":{"type":"number"}},"required":["tramiteTypeId","name","basePrice","transitFee","runtFee","urgentFee","total"]}},"total":{"type":"number"},"valorTramite":{"type":"number"},"valorManejoEnvio":{"type":"number"},"valorRetencion":{"type":"number"}},"required":["items","total","valorTramite","valorManejoEnvio","valorRetencion"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites":{"get":{"tags":["Tramites"],"summary":"Get all tramites (admin only)","responses":{"200":{"description":"All tramites","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt"]}}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"post":{"tags":["Tramites"],"summary":"Create new tramite","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string","format":"uuid"},"tramiteTypeIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"transitAgencyId":{"type":"string","format":"uuid"},"radicadorData":{"type":"object","properties":{"tipo_identificacion":{"type":"string"},"numero_identificacion":{"type":"string"},"digito_verificacion":{"type":"string"},"razon_social":{"type":"string"},"tipo_persona":{"type":"string","enum":["Natural","Juridica"]},"primer_nombre":{"type":"string"},"segundo_nombre":{"type":"string"},"primer_apellido":{"type":"string"},"segundo_apellido":{"type":"string"},"telefono":{"type":"string"},"direccion":{"type":"string"},"email":{"type":"string","format":"email"},"pais_id":{"type":"string","format":"uuid"},"departamento_id":{"type":"string","format":"uuid"},"ciudad_id":{"type":"string","format":"uuid"},"nacionalidad":{"type":"string"}},"required":["tipo_identificacion","numero_identificacion","razon_social","tipo_persona"]},"titularData":{"type":"object","properties":{"tipo_identificacion":{"type":"string"},"identificacion":{"type":"string"},"digito_verificacion":{"type":"string"},"tipo_persona":{"type":"string","enum":["Natural","Juridica"]},"razon_social":{"type":"string"},"primer_nombre":{"type":"string"},"segundo_nombre":{"type":"string"},"primer_apellido":{"type":"string"},"segundo_apellido":{"type":"string"},"telefono":{"type":"string"},"direccion":{"type":"string"},"email":{"type":"string","format":"email"},"pais_id":{"type":"string","format":"uuid"},"departamento_id":{"type":"string","format":"uuid"},"ciudad_id":{"type":"string","format":"uuid"},"nacionalidad":{"type":"string"},"tipo_contribuyente":{"type":"string"}},"required":["tipo_identificacion","identificacion","tipo_persona","razon_social","telefono","direccion","email","pais_id","departamento_id","ciudad_id"]},"compradorData":{"type":"object","nullable":true,"properties":{"tipo_identificacion":{"type":"string"},"identificacion":{"type":"string"},"digito_verificacion":{"type":"string"},"tipo_persona":{"type":"string","enum":["Natural","Juridica"]},"razon_social":{"type":"string"},"primer_nombre":{"type":"string"},"segundo_nombre":{"type":"string"},"primer_apellido":{"type":"string"},"segundo_apellido":{"type":"string"},"telefono":{"type":"string"},"direccion":{"type":"string"},"email":{"type":"string","format":"email"},"pais_id":{"type":"string","format":"uuid"},"departamento_id":{"type":"string","format":"uuid"},"ciudad_id":{"type":"string","format":"uuid"},"nacionalidad":{"type":"string"}}},"valorMatricula":{"type":"number"},"valorImpuestosPagados":{"type":"number"},"valorRetencion":{"type":"number"},"valorManejoEnvio":{"type":"number"},"valorOtrosConceptos":{"type":"number"},"valorTramite":{"type":"number"}},"required":["userId","city","department","totalAmount","transitAgencyId","radicadorData","titularData"]}}}},"responses":{"201":{"description":"Created tramite","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt"]}}}}}}},"/tramites/my":{"get":{"tags":["Tramites"],"summary":"Get user's tramites (requires authentication)","responses":{"200":{"description":"User's tramites","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt"]}}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/assigned":{"get":{"tags":["Tramites"],"summary":"Get tramites assigned to operator/collaborator (requires operator role)","responses":{"200":{"description":"Assigned tramites","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt"]}}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/{id}":{"get":{"tags":["Tramites"],"summary":"Get tramite by ID (requires authentication)","parameters":[{"schema":{"type":"string","example":"123"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Tramite details with user information","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"fullName":{"type":"string"}},"required":["id","email"]}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt","user"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/{id}/retry-odoo-sync":{"post":{"tags":["Tramites"],"summary":"Retry Odoo sync for a tramite","description":"Reintenta la sincronización con Odoo para un trámite que tenga error o pendiente. Requiere ser dueño del trámite, operador asignado o admin.","parameters":[{"schema":{"type":"string","example":"123"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Trámite actualizado tras reintentar sincronización","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"fullName":{"type":"string"}},"required":["id","email"]}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt","user"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/{id}/refresh-status":{"post":{"tags":["Tramites"],"summary":"Refresh tramite status from Odoo","description":"Obtiene el estado actual de la solicitud en Odoo (pre-solicitud, En Proceso, Rechazado, Terminado, Retrámite) y actualiza el trámite. Requiere operador o admin.","parameters":[{"schema":{"type":"string","example":"123"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Trámite con estado actualizado","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/{id}/status":{"patch":{"tags":["Tramites"],"summary":"Update tramite status (operators can only update assigned tramites)","parameters":[{"schema":{"type":"string","example":"123"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"notes":{"type":"string"}},"required":["status"]}}}},"responses":{"200":{"description":"Updated tramite","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/tramites/{id}/assign":{"patch":{"tags":["Tramites"],"summary":"Assign tramite to a collaborator (admin only)","parameters":[{"schema":{"type":"string","example":"123"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"assignedTo":{"type":"string","format":"uuid","description":"User ID of the collaborator (operator) to assign"}},"required":["assignedTo"]}}}},"responses":{"200":{"description":"Tramite assigned","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"placa":{"type":"string"},"tramiteTypeId":{"type":"string"},"status":{"type":"string","enum":["pending","in_progress","completed","rejected"]},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed"]},"city":{"type":"string"},"department":{"type":"string"},"totalAmount":{"type":"number"},"documents":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"type":{"type":"string"}},"required":["name","url","type"]}},"notes":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"odooSyncStatus":{"type":"string","enum":["pending","synced","failed"]},"odooSolicitudNumero":{"type":"string"}},"required":["id","userId","tramiteTypeId","status","paymentStatus","city","department","totalAmount","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/odoo/info":{"get":{"tags":["Odoo"],"summary":"Get Odoo server information","responses":{"200":{"description":"Odoo server information","content":{"application/json":{"schema":{"type":"object","properties":{"server_version":{"type":"string"},"server_version_info":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"}]}},"server_serie":{"type":"string"},"protocol_version":{"type":"number"}},"required":["server_version","server_version_info","server_serie","protocol_version"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/odoo/test-connection":{"post":{"tags":["Odoo"],"summary":"Test Odoo connection","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"database":{"type":"string"},"username":{"type":"string"},"password":{"type":"string"}},"required":["url","database","username","password"]}}}},"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"uid":{"type":"number"},"message":{"type":"string"}},"required":["success","message"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/odoo/models":{"get":{"tags":["Odoo"],"summary":"Get Odoo models","parameters":[{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"List of Odoo models with metadata","content":{"application/json":{"schema":{"type":"object","properties":{"models":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"model":{"type":"string"},"state":{"type":"string"},"transient":{"type":"boolean"},"info":{"type":"string"},"modules":{"type":"string"},"field_count":{"type":"number"}},"required":["id","name","model"]}},"total":{"type":"number"},"limit":{"type":"number"},"search":{"type":"string"}},"required":["models","total","limit"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/odoo/solicitud-tramite":{"get":{"tags":["Odoo"],"summary":"Get solicitud_tramite records","parameters":[{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"List of solicitud_tramite records with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"records":{"type":"array","items":{"type":"object","properties":{"id":{"type":"number"},"data":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"nullable":true}]}}},"required":["id","data"]}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["records","total","limit","offset"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"post":{"tags":["Odoo"],"summary":"Create solicitud_tramite record","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"nullable":true}]}}},"required":["data"]}}}},"responses":{"201":{"description":"Solicitud_tramite record created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"id":{"type":"number"},"message":{"type":"string"},"record":{"type":"object","properties":{"id":{"type":"number"},"data":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"nullable":true}]}}},"required":["id","data"]}},"required":["success","message"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/odoo/solicitud-tramite/{id}":{"get":{"tags":["Odoo"],"summary":"Get solicitud_tramite record by ID","parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Single solicitud_tramite record","content":{"application/json":{"schema":{"type":"object","properties":{"record":{"type":"object","properties":{"id":{"type":"number"},"data":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"nullable":true}]}}},"required":["id","data"]},"message":{"type":"string"}},"required":["record","message"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/odoo/execute":{"post":{"tags":["Odoo"],"summary":"Execute Odoo method","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string"},"method":{"type":"string"},"args":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"nullable":true},{"type":"object","properties":{},"additionalProperties":{"nullable":true}}]}},"kwargs":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"nullable":true}]}}},"required":["model","method","args"]}}}},"responses":{"200":{"description":"Execution result","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{},"additionalProperties":{"nullable":true}},{"type":"array","items":{"nullable":true}},{"type":"string"},{"type":"number"},{"type":"boolean"},{"nullable":true}]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/odoo/models/{model}/records":{"get":{"tags":["Odoo"],"summary":"Get records from a generic Odoo model","parameters":[{"schema":{"type":"string"},"required":true,"name":"model","in":"path"},{"schema":{"type":"string"},"required":false,"name":"fields","in":"query"},{"schema":{"type":"string"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"List of records from the specified model with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"records":{"type":"array","items":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"nullable":true},{"type":"array","items":{"nullable":true}},{"type":"object","properties":{},"additionalProperties":{"nullable":true}}]}}},"total":{"type":"number"},"limit":{"type":"number"},"offset":{"type":"number"}},"required":["records","total","limit","offset"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/webhook":{"post":{"tags":["Payments"],"summary":"Wompi webhook endpoint","parameters":[{"schema":{"type":"string"},"required":false,"name":"x-event-checksum","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"nullable":true}}}},"responses":{"200":{"description":"Webhook processed","content":{"application/json":{"schema":{"type":"object","properties":{"processed":{"type":"boolean"}},"required":["processed"]}}}}}}},"/payments/methods":{"get":{"tags":["Payments"],"summary":"Get available payment methods","responses":{"200":{"description":"Available payment methods","content":{"application/json":{"schema":{"type":"object","properties":{"methods":{"type":"array","items":{"type":"string"}}},"required":["methods"]}}}}}}},"/payments/pse/banks":{"get":{"tags":["Payments"],"summary":"Get PSE banks list","responses":{"200":{"description":"PSE banks list","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"financial_institution_code":{"type":"string"},"financial_institution_name":{"type":"string"}},"required":["financial_institution_code","financial_institution_name"]}}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/my":{"get":{"tags":["Payments"],"summary":"Get user's payments","parameters":[{"schema":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"userId","in":"query"}],"responses":{"200":{"description":"User's payments","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tramiteId":{"type":"string"},"userId":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","failed","cancelled","refunded"]},"paymentMethod":{"type":"string"},"gateway":{"type":"string"},"gatewayTransactionId":{"type":"string"},"gatewayReference":{"type":"string"},"description":{"type":"string"},"metadata":{"nullable":true},"paidAt":{"type":"string"},"failedAt":{"type":"string"},"failureReason":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tramiteId","userId","amount","currency","status","paymentMethod","gateway","createdAt","updatedAt"]}}}}}}}},"/payments/links":{"get":{"tags":["Payments"],"summary":"Get payment links by tramite ID","parameters":[{"schema":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"tramiteId","in":"query"}],"responses":{"200":{"description":"Payment links for the tramite","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"paymentId":{"type":"string","nullable":true},"tramiteId":{"type":"string"},"userId":{"type":"string"},"createdBy":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"paymentStatus":{"type":"string","enum":["pending","processing","completed","failed","refunded","cancelled"]},"wompiLinkId":{"type":"string"},"wompiLinkUrl":{"type":"string"},"wompiTransactionId":{"type":"string","nullable":true},"customDescription":{"type":"string","nullable":true},"customAmount":{"type":"string","nullable":true},"paidAt":{"type":"string","nullable":true},"failedAt":{"type":"string","nullable":true},"failureReason":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true},"emailSentTo":{"type":"string","nullable":true},"emailSentAt":{"type":"string","nullable":true},"qrCodeGenerated":{"type":"boolean"},"status":{"type":"string","enum":["active","expired","used","cancelled"]},"metadata":{"nullable":true},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","paymentId","tramiteId","userId","createdBy","amount","currency","paymentStatus","wompiLinkId","wompiLinkUrl","wompiTransactionId","customDescription","customAmount","paidAt","failedAt","failureReason","expiresAt","emailSentTo","emailSentAt","qrCodeGenerated","status","createdAt","updatedAt"]}}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/link":{"post":{"tags":["Payments"],"summary":"Create payment link","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tramiteId":{"type":"string"},"amount":{"type":"number","minimum":0,"exclusiveMinimum":true},"description":{"type":"string"},"expiresIn":{"type":"number"},"redirectUrl":{"type":"string","format":"uri"}},"required":["tramiteId","amount","description"]}}}},"responses":{"200":{"description":"Payment link created","content":{"application/json":{"schema":{"type":"object","properties":{"paymentLinkId":{"type":"string"},"paymentUrl":{"type":"string"}},"required":["paymentLinkId","paymentUrl"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/tramite/:tramiteId/history":{"get":{"tags":["Payments"],"summary":"Get all payment receipts for a tramite","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"tramiteId","in":"path"}],"responses":{"200":{"description":"Payment history retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"paymentLinks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"wompiLinkUrl":{"type":"string"},"customDescription":{"type":"string","nullable":true},"customAmount":{"type":"string","nullable":true},"expiresAt":{"type":"string","nullable":true},"emailSentTo":{"type":"string","nullable":true},"emailSentAt":{"type":"string","nullable":true},"qrCodeGenerated":{"type":"boolean"},"status":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","wompiLinkUrl","customDescription","customAmount","expiresAt","emailSentTo","emailSentAt","qrCodeGenerated","status","createdAt"]}}},"required":["paymentLinks"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/receipt":{"post":{"tags":["Payments"],"summary":"Create a payment receipt with custom metadata","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"tramiteId":{"type":"string","format":"uuid"},"customDescription":{"type":"string"},"customAmount":{"type":"string"},"expiresAt":{"type":"string"},"metadata":{"nullable":true}},"required":["tramiteId"]}}}},"responses":{"201":{"description":"Payment receipt created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"paymentLinkId":{"type":"string"},"paymentUrl":{"type":"string"},"message":{"type":"string"}},"required":["paymentLinkId","paymentUrl","message"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/send-email":{"post":{"tags":["Payments"],"summary":"Send payment link via email with QR code","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"paymentLinkId":{"type":"string","format":"uuid"},"emailTo":{"type":"string","format":"email"}},"required":["paymentLinkId","emailTo"]}}}},"responses":{"200":{"description":"Payment email sent successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"emailSentTo":{"type":"string"}},"required":["message","emailSentTo"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/admin/payment-links":{"get":{"tags":["Payments","Admin"],"summary":"Get all payment links with related tramite data (Admin only)","responses":{"200":{"description":"Payment links retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"paymentLinks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tramiteId":{"type":"string"},"tramiteTipo":{"type":"string"},"tramitePlaca":{"type":"string","nullable":true},"wompiLinkUrl":{"type":"string"},"customDescription":{"type":"string","nullable":true},"customAmount":{"type":"string","nullable":true},"status":{"type":"string","enum":["active","expired","completed"]},"createdAt":{"type":"string"},"expiresAt":{"type":"string","nullable":true},"emailSentTo":{"type":"string","nullable":true},"emailSentAt":{"type":"string","nullable":true},"paymentCompletedAt":{"type":"string","nullable":true},"paymentAmount":{"type":"string","nullable":true}},"required":["id","tramiteId","tramiteTipo","tramitePlaca","wompiLinkUrl","customDescription","customAmount","status","createdAt","expiresAt","emailSentTo","emailSentAt","paymentCompletedAt","paymentAmount"]}}},"required":["paymentLinks"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/{id}/refund":{"post":{"tags":["Payments"],"summary":"Request payment refund","parameters":[{"schema":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string"},"amount":{"type":"number","minimum":0,"exclusiveMinimum":true}},"required":["reason"]}}}},"responses":{"200":{"description":"Refund processed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"refundAmount":{"type":"number"}},"required":["success","refundAmount"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/{id}":{"get":{"tags":["Payments"],"summary":"Get payment status","parameters":[{"schema":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Payment details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"tramiteId":{"type":"string"},"userId":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","failed","cancelled","refunded"]},"paymentMethod":{"type":"string"},"gateway":{"type":"string"},"gatewayTransactionId":{"type":"string"},"gatewayReference":{"type":"string"},"description":{"type":"string"},"metadata":{"nullable":true},"paidAt":{"type":"string"},"failedAt":{"type":"string"},"failureReason":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tramiteId","userId","amount","currency","status","paymentMethod","gateway","createdAt","updatedAt"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/payments/tramite/{tramiteId}":{"get":{"tags":["Payments"],"summary":"Get payment by tramite ID","parameters":[{"schema":{"type":"string","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"tramiteId","in":"path"}],"responses":{"200":{"description":"Payment details","content":{"application/json":{"schema":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"tramiteId":{"type":"string"},"userId":{"type":"string"},"amount":{"type":"string"},"currency":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","failed","cancelled","refunded"]},"paymentMethod":{"type":"string"},"gateway":{"type":"string"},"gatewayTransactionId":{"type":"string"},"gatewayReference":{"type":"string"},"description":{"type":"string"},"metadata":{"nullable":true},"paidAt":{"type":"string"},"failedAt":{"type":"string"},"failureReason":{"type":"string"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","tramiteId","userId","amount","currency","status","paymentMethod","gateway","createdAt","updatedAt"]}}}}}}},"/profile":{"get":{"tags":["Profile"],"summary":"Get user profile","description":"Retrieve the profile for a user","parameters":[{"schema":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"userId","in":"query"}],"responses":{"200":{"description":"User profile retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"fullName":{"type":"string","nullable":true},"documentType":{"type":"string","nullable":true,"enum":["CC","CE","NIT","TI","PAS",null]},"documentNumber":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"role":{"type":"string","enum":["customer","operator","admin"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","email","fullName","documentType","documentNumber","phone","role","createdAt","updatedAt"]}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"put":{"tags":["Profile"],"summary":"Update user profile","description":"Update profile information for a user","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"fullName":{"type":"string","nullable":true,"maxLength":200},"documentType":{"type":"string","nullable":true,"maxLength":20},"documentNumber":{"type":"string","nullable":true,"maxLength":50},"phone":{"type":"string","nullable":true,"maxLength":20},"address":{"type":"string","nullable":true},"city":{"type":"string","nullable":true,"maxLength":100},"department":{"type":"string","nullable":true,"maxLength":100},"userId":{"type":"string","format":"uuid"}},"required":["userId"]}}}},"responses":{"200":{"description":"Profile updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"fullName":{"type":"string","nullable":true},"documentType":{"type":"string","nullable":true,"enum":["CC","CE","NIT","TI","PAS",null]},"documentNumber":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"role":{"type":"string","enum":["customer","operator","admin"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","email","fullName","documentType","documentNumber","phone","role","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Profile not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/settings":{"get":{"tags":["Settings"],"summary":"Get user settings","description":"Retrieve the settings for a user","parameters":[{"schema":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"userId","in":"query"}],"responses":{"200":{"description":"User settings retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"preferences":{"type":"object","properties":{"language":{"type":"string","enum":["es","en"]},"notifications":{"type":"object","properties":{"email":{"type":"boolean"},"push":{"type":"boolean"},"sms":{"type":"boolean"}},"required":["email","push","sms"]},"theme":{"type":"string","enum":["light","dark"]}},"required":["language","notifications","theme"]},"notificationSettings":{"type":"object","properties":{"tramiteUpdates":{"type":"boolean"},"paymentConfirmations":{"type":"boolean"},"marketing":{"type":"boolean"}},"required":["tramiteUpdates","paymentConfirmations","marketing"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","userId","preferences","notificationSettings","createdAt","updatedAt"]}}}},"404":{"description":"Settings not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"post":{"tags":["Settings"],"summary":"Create user settings","description":"Create initial settings for a user","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"preferences":{"type":"object","properties":{"language":{"type":"string","enum":["es","en"],"default":"es"},"notifications":{"type":"object","properties":{"email":{"type":"boolean","default":true},"push":{"type":"boolean","default":true},"sms":{"type":"boolean","default":false}},"default":{"email":true,"push":true,"sms":false}},"theme":{"type":"string","enum":["light","dark"],"default":"light"}}},"notificationSettings":{"type":"object","properties":{"tramiteUpdates":{"type":"boolean","default":true},"paymentConfirmations":{"type":"boolean","default":true},"marketing":{"type":"boolean","default":false}}},"lastOdooSync":{"type":"string","nullable":true,"format":"date-time"},"userId":{"type":"string","format":"uuid"}},"required":["userId"]}}}},"responses":{"201":{"description":"Settings created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"preferences":{"type":"object","properties":{"language":{"type":"string","enum":["es","en"]},"notifications":{"type":"object","properties":{"email":{"type":"boolean"},"push":{"type":"boolean"},"sms":{"type":"boolean"}},"required":["email","push","sms"]},"theme":{"type":"string","enum":["light","dark"]}},"required":["language","notifications","theme"]},"notificationSettings":{"type":"object","properties":{"tramiteUpdates":{"type":"boolean"},"paymentConfirmations":{"type":"boolean"},"marketing":{"type":"boolean"}},"required":["tramiteUpdates","paymentConfirmations","marketing"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","userId","preferences","notificationSettings","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Settings already exist","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"put":{"tags":["Settings"],"summary":"Update user settings","description":"Update settings for a user","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"preferences":{"type":"object","properties":{"language":{"type":"string","enum":["es","en"],"default":"es"},"notifications":{"type":"object","properties":{"email":{"type":"boolean","default":true},"push":{"type":"boolean","default":true},"sms":{"type":"boolean","default":false}},"default":{"email":true,"push":true,"sms":false}},"theme":{"type":"string","enum":["light","dark"],"default":"light"}}},"notificationSettings":{"type":"object","properties":{"tramiteUpdates":{"type":"boolean","default":true},"paymentConfirmations":{"type":"boolean","default":true},"marketing":{"type":"boolean","default":false}}},"lastOdooSync":{"type":"string","nullable":true,"format":"date-time"},"userId":{"type":"string","format":"uuid"}},"required":["userId"]}}}},"responses":{"200":{"description":"Settings updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid"},"preferences":{"type":"object","properties":{"language":{"type":"string","enum":["es","en"]},"notifications":{"type":"object","properties":{"email":{"type":"boolean"},"push":{"type":"boolean"},"sms":{"type":"boolean"}},"required":["email","push","sms"]},"theme":{"type":"string","enum":["light","dark"]}},"required":["language","notifications","theme"]},"notificationSettings":{"type":"object","properties":{"tramiteUpdates":{"type":"boolean"},"paymentConfirmations":{"type":"boolean"},"marketing":{"type":"boolean"}},"required":["tramiteUpdates","paymentConfirmations","marketing"]},"createdAt":{"type":"string"},"updatedAt":{"type":"string"}},"required":["id","userId","preferences","notificationSettings","createdAt","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Settings not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"delete":{"tags":["Settings"],"summary":"Delete user settings","description":"Delete settings for a user (resets to defaults)","parameters":[{"schema":{"type":"string","format":"uuid","example":"123e4567-e89b-12d3-a456-426614174000"},"required":true,"name":"userId","in":"query"}],"responses":{"200":{"description":"Settings deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"404":{"description":"Settings not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/admin/plate-pricing":{"get":{"tags":["Admin","Plate Orders"],"summary":"Get plate pricing settings","description":"Returns current plate pricing (unit price, shipping cost, free shipping threshold). Used by portal config.","responses":{"200":{"description":"Plate pricing settings","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","nullable":true,"format":"uuid"},"unitPriceCop":{"type":"number"},"shippingCostCop":{"type":"number"},"freeShippingThresholdCop":{"type":"number"},"updatedAt":{"type":"string","nullable":true}},"required":["id","unitPriceCop","shippingCostCop","freeShippingThresholdCop","updatedAt"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"put":{"tags":["Admin","Plate Orders"],"summary":"Update plate pricing settings","description":"Updates unit price, shipping cost and free shipping threshold (admin only).","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"unitPriceCop":{"type":"integer","minimum":0},"shippingCostCop":{"type":"integer","minimum":0},"freeShippingThresholdCop":{"type":"integer","minimum":0}},"required":["unitPriceCop","shippingCostCop","freeShippingThresholdCop"]}}}},"responses":{"200":{"description":"Updated plate pricing settings","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","nullable":true,"format":"uuid"},"unitPriceCop":{"type":"number"},"shippingCostCop":{"type":"number"},"freeShippingThresholdCop":{"type":"number"},"updatedAt":{"type":"string","nullable":true}},"required":["id","unitPriceCop","shippingCostCop","freeShippingThresholdCop","updatedAt"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/admin/plate-orders":{"get":{"tags":["Admin","Plate Orders"],"summary":"List all plate orders","description":"Returns all plate orders (newest first). Optional query param \"q\" filters by tracking ID, customer name or email. Admin only.","parameters":[{"schema":{"type":"string","minLength":1},"required":false,"name":"q","in":"query"}],"responses":{"200":{"description":"List of plate orders","content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"array","items":{"nullable":true}}},"required":["orders"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/admin/plate-orders/{id}":{"get":{"tags":["Admin","Plate Orders"],"summary":"Get plate order by ID","description":"Returns a single plate order with full details. Admin only.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Plate order details","content":{"application/json":{"schema":{"nullable":true}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}},"patch":{"tags":["Admin","Plate Orders"],"summary":"Update plate order (operational status and tracking)","description":"Update operational status (En producción, Enviado, Entregado) and/or tracking number. Admin only.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"operationalStatus":{"type":"string","enum":["in_production","shipped","delivered"]},"trackingNumber":{"type":"string","nullable":true}}}}}},"responses":{"200":{"description":"Updated plate order","content":{"application/json":{"schema":{"nullable":true}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/sync/tramites":{"post":{"tags":["Sync"],"summary":"Sync all data from Odoo","description":"Synchronizes tramites, transit agencies, pricing, and shipping fees from Odoo. Uses UPSERT strategy (creates new records or updates existing ones). Admin only.","responses":{"200":{"description":"Synchronization completed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"countries":{"type":"object","properties":{"created":{"type":"number"},"updated":{"type":"number"},"skipped":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["created","updated","skipped","errors"]},"departments":{"type":"object","properties":{"created":{"type":"number"},"updated":{"type":"number"},"skipped":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["created","updated","skipped","errors"]},"cities":{"type":"object","properties":{"created":{"type":"number"},"updated":{"type":"number"},"skipped":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["created","updated","skipped","errors"]},"transitAgencies":{"type":"object","properties":{"created":{"type":"number"},"updated":{"type":"number"},"skipped":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["created","updated","skipped","errors"]},"tramites":{"type":"object","properties":{"created":{"type":"number"},"updated":{"type":"number"},"skipped":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["created","updated","skipped","errors"]},"pricing":{"type":"object","properties":{"created":{"type":"number"},"updated":{"type":"number"},"skipped":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["created","updated","skipped","errors"]},"shippingFees":{"type":"object","properties":{"created":{"type":"number"},"updated":{"type":"number"},"skipped":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["created","updated","skipped","errors"]},"lastSync":{"type":"string","nullable":true}},"required":["success","countries","departments","cities","transitAgencies","tramites","pricing","shippingFees","lastSync"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/sync/tramites/retry-failed":{"post":{"tags":["Sync"],"summary":"Retry Odoo sync for all tramites with failed sync","description":"Reintenta la sincronización con Odoo de todos los trámites que tengan estado de error. Solo administradores.","responses":{"200":{"description":"Resultado del reintento por trámite","content":{"application/json":{"schema":{"type":"object","properties":{"synced":{"type":"number"},"failed":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["synced","failed","errors"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/sync/status":{"get":{"tags":["Sync"],"summary":"Get sync status","description":"Returns the last Odoo sync timestamp. Admin only.","responses":{"200":{"description":"Sync status retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"lastSync":{"type":"string","nullable":true},"hasSync":{"type":"boolean"},"failedTramitesCount":{"type":"number"}},"required":["lastSync","hasSync"]}}}},"401":{"description":"No Authorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"403":{"description":"Invalid Permissions","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/webhooks/plate-orders":{"post":{"tags":["Webhooks","Plate Orders"],"summary":"Receive plate order (webhook)","description":"Receives an order payload from external systems (e.g. webstudio). Validates amounts against configurable pricing, stores the order, creates a Wompi payment link and returns it.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"products":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"subtext":{"type":"string"},"color":{"type":"string"},"quantity":{"type":"integer","minimum":0,"exclusiveMinimum":true},"unit_price":{"type":"integer","minimum":0},"subtotal":{"type":"integer","minimum":0}},"required":["text","subtext","color","quantity","unit_price","subtotal"]},"minItems":1},"subtotal":{"type":"integer","minimum":0},"shipping_cost":{"type":"integer","minimum":0},"free_shipping":{"type":"boolean"},"total":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3,"default":"COP"},"item_count":{"type":"integer","minimum":0},"customer":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string","minLength":1},"cedula":{"type":"string","minLength":1},"phone":{"type":"string","minLength":1}},"required":["email","name","cedula","phone"]},"shipping":{"type":"object","properties":{"department":{"type":"string"},"city":{"type":"string"},"address":{"type":"string"},"address_extra":{"type":"string"},"barrio":{"type":"string"},"notes":{"type":"string"}},"required":["department","city","address"]},"billing":{"oneOf":[{"type":"object","properties":{"same_as_shipping":{"type":"boolean"},"type":{"type":"string","enum":["natural"]},"name":{"type":"string"},"cedula":{"type":"string"},"email":{"type":"string","format":"email"},"department":{"type":"string"},"city":{"type":"string"},"address":{"type":"string"},"phone":{"type":"string"}},"required":["same_as_shipping","type","name","cedula","email","department","city","address","phone"]},{"type":"object","properties":{"same_as_shipping":{"type":"boolean"},"type":{"type":"string","enum":["juridica"]},"company_name":{"type":"string"},"nit":{"type":"string"},"name":{"type":"string"},"cedula":{"type":"string"},"email":{"type":"string","format":"email"},"department":{"type":"string"},"city":{"type":"string"},"address":{"type":"string"},"phone":{"type":"string"}},"required":["same_as_shipping","type","company_name","nit","name","cedula","email","department","city","address","phone"]}]},"callback_url":{"type":"string","format":"uri"},"timestamp":{"type":"string","format":"date-time"},"source":{"type":"string"}},"required":["products","subtotal","shipping_cost","free_shipping","total","item_count","customer","shipping","billing"]}}}},"responses":{"200":{"description":"Order created and payment link returned","content":{"application/json":{"schema":{"type":"object","properties":{"orderId":{"type":"string","format":"uuid"},"trackingId":{"type":"string","nullable":true},"paymentUrl":{"type":"string","format":"uri"},"total":{"type":"number"},"currency":{"type":"string"},"priceMismatch":{"type":"boolean"}},"required":["orderId","trackingId","paymentUrl","total","currency"]}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/webhooks/contact":{"post":{"tags":["Contact"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"Nombre":{"type":"string","minLength":1},"Empresa":{"type":"string"},"Selecciona un servicio":{"type":"string"},"email":{"type":"string","format":"email"},"message":{"type":"string","minLength":1}},"required":["Nombre","email","message"]}}}},"responses":{"200":{"description":"Contact submission received","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"id":{"type":"string","format":"uuid"}},"required":["message","id"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/webhooks/newsletter/subscribe":{"post":{"tags":["Newsletter"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}},"responses":{"200":{"description":"Subscription email sent","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"email":{"type":"string"}},"required":["message","email"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"409":{"description":"Email already subscribed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/newsletters/confirm/{token}":{"get":{"tags":["Newsletter"],"parameters":[{"schema":{"type":"string"},"required":true,"name":"token","in":"path"}],"responses":{"200":{"description":"Subscription confirmed","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"email":{"type":"string"}},"required":["message","email"]}}}},"400":{"description":"Invalid or expired token","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/admin/newsletters":{"get":{"tags":["Newsletter","Admin"],"parameters":[{"schema":{"type":"string","enum":["draft","subscribed","unsubscribed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"List of newsletter subscriptions","content":{"application/json":{"schema":{"type":"object","properties":{"subscriptions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","maxLength":255},"subscriptionDate":{"type":"string","format":"date-time"},"subscriptionStatus":{"type":"string","enum":["draft","subscribed","unsubscribed"]},"updatedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","email","subscriptionDate","subscriptionStatus","updatedAt","createdAt"]}},"total":{"type":"number"}},"required":["subscriptions","total"]}}}}}}},"/admin/newsletters/{id}/unsubscribe":{"patch":{"tags":["Newsletter","Admin"],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Subscription updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","maxLength":255},"subscriptionDate":{"type":"string","format":"date-time"},"subscriptionStatus":{"type":"string","enum":["draft","subscribed","unsubscribed"]},"updatedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","email","subscriptionDate","subscriptionStatus","updatedAt","createdAt"]}}}},"404":{"description":"Subscription not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}}}},"/admin/users":{"get":{"tags":["Admin","Users"],"parameters":[{"schema":{"type":"string"},"required":false,"name":"search","in":"query"},{"schema":{"type":"string","enum":["admin","operator","customer"]},"required":false,"name":"role","in":"query"},{"schema":{"type":"number","minimum":1,"maximum":500,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"number","nullable":true,"minimum":0,"default":0},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"List of users (profiles) for admin","content":{"application/json":{"schema":{"type":"object","properties":{"users":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"fullName":{"type":"string","nullable":true},"role":{"type":"string","enum":["admin","operator","customer"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","email","fullName","role","createdAt","updatedAt"]}},"total":{"type":"number"}},"required":["users","total"]}}}}}}},"/admin/users/{id}":{"patch":{"tags":["Admin","Users"],"summary":"Update user role (admin only). Use \"operator\" for collaborator.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["admin","operator","customer"]}},"required":["role"]}}}},"responses":{"200":{"description":"User role updated","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"},"fullName":{"type":"string","nullable":true},"role":{"type":"string","enum":["admin","operator","customer"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","email","fullName","role","createdAt","updatedAt"]}}}},"404":{"description":"User not found"}}}}}}