Precios y Edades
Guía completa para el cálculo de precios, categorías de edad y descuentos.
Vista General
El sistema de precios de LosCenotes soporta:
- Precios basados en edad con 5 categorías y multiplicadores configurables
- Servicios incluidos y opcionales
- Cálculo de transporte con precios basados en distancia
- Descuentos automáticos basados en elegibilidad del usuario
- Códigos de cupón
Categorías de Edad
GET /age-configurations
Listar todas las configuraciones de edad globales.
curl -X GET "https://service-gateway.loscenotes.com/age-configurations" \
-H "Content-Type: application/json" \
-H "Accept-Language: es"
Respuesta:
{
"success": true,
"message": "age_configurations.list_retrieved_successfully",
"data": [
{
"id": "uuid-infant",
"category": "infant",
"displayNames": {
"es": "Bebés",
"en": "Infants"
},
"descriptions": {
"es": "Niños de 0 a 2 años",
"en": "Children from 0 to 2 years old"
},
"minAge": 0,
"maxAge": 2,
"pricingMultiplier": 0.0,
"isActive": true,
"displayOrder": 1
},
{
"id": "uuid-child",
"category": "child",
"displayNames": {
"es": "Niños",
"en": "Children"
},
"descriptions": {
"es": "Niños de 3 a 12 años",
"en": "Children from 3 to 12 years old"
},
"minAge": 3,
"maxAge": 12,
"pricingMultiplier": 0.8,
"isActive": true,
"displayOrder": 2
},
{
"id": "uuid-teen",
"category": "teen",
"displayNames": {
"es": "Adolescentes",
"en": "Teens"
},
"descriptions": {
"es": "Jóvenes de 13 a 17 años",
"en": "Youth from 13 to 17 years old"
},
"minAge": 13,
"maxAge": 17,
"pricingMultiplier": 0.9,
"isActive": true,
"displayOrder": 3
},
{
"id": "uuid-adult",
"category": "adult",
"displayNames": {
"es": "Adultos",
"en": "Adults"
},
"descriptions": {
"es": "Adultos de 18 a 64 años",
"en": "Adults from 18 to 64 years old"
},
"minAge": 18,
"maxAge": 64,
"pricingMultiplier": 1.0,
"isActive": true,
"displayOrder": 4
},
{
"id": "uuid-senior",
"category": "senior",
"displayNames": {
"es": "Adultos Mayores",
"en": "Seniors"
},
"descriptions": {
"es": "Adultos de 65 años o más",
"en": "Adults 65 years or older"
},
"minAge": 65,
"maxAge": null,
"pricingMultiplier": 0.85,
"isActive": true,
"displayOrder": 5
}
]
}
Multiplicadores Automáticos
| Categoría | Rango de Edad | Multiplicador | Descuento |
|---|---|---|---|
infant | 0-2 años | 0.0 | 100% (GRATIS) |
child | 3-12 a ños | 0.8 | 20% |
teen | 13-17 años | 0.9 | 10% |
adult | 18-64 años | 1.0 | 0% (precio completo) |
senior | 65+ años | 0.85 | 15% |
GET /age-configurations/cenote/:cenoteId
Obtener configuraciones de edad específicas para un cenote (pueden anular las predeterminadas globales).
curl -X GET "https://service-gateway.loscenotes.com/age-configurations/cenote/cenote-uuid" \
-H "Content-Type: application/json"
GET /age-configurations/tour/:tourId
Obtener configuraciones de edad específicas para un tour.
curl -X GET "https://service-gateway.loscenotes.com/age-configurations/tour/tour-uuid" \
-H "Content-Type: application/json"
Cálculo de Precios
POST /pricing/calculate-complete
⭐ Endpoint principal para cálculo completo de precios
Este endpoint calcula el precio total incluyendo:
- Ajustes por edad
- Servicios incluidos y opcionales
- Costos de transporte
- Descuentos automáticos
- Códigos de cupón
Solicitud:
curl -X POST "https://service-gateway.loscenotes.com/pricing/calculate-complete" \
-H "Content-Type: application/json" \
-H "X-API-Key: pk_live_your_api_key" \
-d '{
"itemType": "cenote",
"itemId": "cenote-uuid-here",
"ageBreakdown": {
"infant": 0,
"child": 2,
"teen": 1,
"adult": 2,
"senior": 0
},
"selectedServices": ["service-uuid-1", "service-uuid-2"],
"transportationType": "hotel_pickup",
"pickupLocation": "Hotel Xcaret",
"pickupLatitude": 20.4567,
"pickupLongitude": -87.1234,
"couponCode": "VERANO2025",
"currency": "MXN",
"language": "es"
}'
Campos de Solicitud:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
itemType | string | ✅ | "cenote" o "tour" |
itemId | UUID | ✅ | ID del Cenote o Tour |
ageBreakdown | object | ✅ | Conteo de visitantes por categoría de edad |
selectedServices | array | ❌ | IDs de servicios opcionales |
transportationType | string | ❌ | "meeting_point", "hotel_pickup", "private_transfer" |
pickupLocation | string | ❌ | Hotel o lugar de recogida |
pickupLatitude | number | ❌ | Latitud de recogida |
pickupLongitude | number | ❌ | Longitud de recogida |
couponCode | string | ❌ | Código de cupón de descuento |
currency | string | ❌ | Moneda a mostrar (MXN, USD) |
language | string | ❌ | Idioma de respuesta (es, en, fr) |
skipTransportValidation | boolean | ❌ | Saltar validación de transporte para precios progresivos |
Respuesta:
{
"success": true,
"message": "Cálculo de precio completado exitosamente",
"data": {
"basePrice": 35000,
"ageAdjustments": {
"infant": {
"quantity": 0,
"multiplier": 0,
"subtotal": 0
},
"child": {
"quantity": 2,
"multiplier": 0.8,
"subtotal": 56000
},
"teen": {
"quantity": 1,
"multiplier": 0.9,
"subtotal": 31500
},
"adult": {
"quantity": 2,
"multiplier": 1.0,
"subtotal": 70000
},
"senior": {
"quantity": 0,
"multiplier": 0.85,
"subtotal": 0
},
"total": 157500
},
"transportationCost": {
"type": "hotel_pickup",
"strategy": "calculated",
"baseCost": 15000,
"groupDiscount": 0,
"total": 15000,
"pickupLocation": "Hotel Xcaret"
},
"services": {
"included": [
{
"id": "service-included-1",
"name": "Chaleco salvavidas",
"cost": 0,
"reason": "Included in package",
"isTransport": false,
"category": "equipment"
}
],
"selected": [
{
"id": "service-uuid-1",
"name": "Equipo de snorkel",
"cost": 5000,
"isTransport": false,
"category": "equipment"
}
],
"totalServicesCost": 5000
},
"discounts": {
"automatic": [
{
"id": "discount-1",
"name": "Descuento de temporada baja",
"type": "percentage",
"amount": 15750
}
],
"coupon": {
"code": "VERANO2025",
"type": "percentage",
"amount": 10000
}
},
"summary": {
"subtotal": 177500,
"discounts": 25750,
"taxes": 0,
"total": 151750,
"currency": "MXN"
}
},
"currency": {
"code": "MXN",
"symbol": "$"
}
}
⚠️ Importante: Todos los precios están en CENTAVOS. Divide entre 100 para mostrar.
Ejemplo:
35000= $350.00 MXN
GET /pricing/summary/:itemType/:itemId
Resumen rápido de precios para un cenote o tour.
curl -X GET "https://service-gateway.loscenotes.com/pricing/summary/cenote/cenote-uuid?people=4" \
-H "Content-Type: application/json"
Respuesta:
{
"success": true,
"message": "pricing.summary_retrieved_successfully",
"data": {
"itemId": "cenote-uuid",
"itemType": "cenote",
"itemName": "Cenote Dos Ojos",
"basePrice": 35000,
"total": 140000,
"currency": "MXN"
}
}
POST /pricing/validate-age-breakdown
Validar una configuración de edades antes de calcular.
curl -X POST "https://service-gateway.loscenotes.com/pricing/validate-age-breakdown" \
-H "Content-Type: application/json" \
-d '{
"infant": 0,
"child": 2,
"teen": 1,
"adult": 2,
"senior": 0
}'
Respuesta:
{
"success": true,
"message": "pricing.age_breakdown_valid",
"data": {
"isValid": true,
"totalPeople": 5,
"breakdown": [
{ "category": "infant", "count": 0 },
{ "category": "child", "count": 2 },
{ "category": "teen", "count": 1 },
{ "category": "adult", "count": 2 },
{ "category": "senior", "count": 0 }
]
}
}
POST /pricing/calculate-transportation
Calcular costo de transporte por distancia.
curl -X POST "https://service-gateway.loscenotes.com/pricing/calculate-transportation" \
-H "Content-Type: application/json" \
-d '{
"serviceId": "transport-service-uuid",
"distance": 45,
"totalPeople": 4
}'
Ejemplo de Cálculo de Precio
Escenario
- Precio base de cenote: $350.00 MXN (35000 centavos)
- Visitantes: 2 adultos, 2 niños, 1 adolescente
Cálculo
| Categoría | Conteo | Multiplicador | Precio Unitario | Subtotal |
|---|---|---|---|---|
| Adulto | 2 | 1.0 | 35000 | 70000 |
| Niño | 2 | 0.8 | 28000 | 56000 |
| Adolescente | 1 | 0.9 | 31500 | 31500 |
| Total | 5 | 157500 |
Total: $1,575.00 MXN (157500 centavos)
Tipos de Transporte
| Tipo | Descripción |
|---|---|
meeting_point | El huésped llega al punto de encuentro designado |
hotel_pickup | Recogida desde el hotel (requiere coordenadas) |
private_transfer | Transferencia en vehículo privado |
Códigos de Error
| Código | Mensaje | Descripción |
|---|---|---|
CENOTE_NOT_FOUND | error.cenote.not_found | ID de Cenote no encontrado |
TOUR_NOT_FOUND | error.tour.not_found | ID de Tour no encontrado |
INVALID_ITEM_TYPE | error.pricing.invalid_item_type | Debe ser "cenote" o "tour" |
PICKUP_REQUIRED | error.transport.pickup_required_when_included | Info de recogida requerida si incluye transporte |