Reservations API
Complete reference for managing cenote reservations and bookings.
Overview
The Reservations API handles the complete booking lifecycle for cenote visits, from initial reservation creation to confirmation, modification, and cancellation. This API integrates with payment systems and capacity management.
Endpoints
List Reservations
Retrieve reservations with filtering and pagination.
GET /partner/reservations
Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
page | integer | No | Page number (default: 1) | ?page=1 |
perPage | integer | No | Items per page (default: 15, max: 100) | ?perPage=20 |
cursor | string | No | Cursor for cursor-based pagination | ?cursor=eyJpZCI6InJlc18xMjM0In0 |
status | string | No | Filter by status | ?status=confirmed |
cenoteId | string | No | Filter by cenote ID | ?cenoteId=c3n0t3-1234 |
guestEmail | string | No | Filter by guest email | ?guestEmail=guest@example.com |
dateFrom | string | No | Filter from date (ISO 8601) | ?dateFrom=2024-07-01 |
dateTo | string | No | Filter to date (ISO 8601) | ?dateTo=2024-07-31 |
createdAfter | string | No | Filter by creation date | ?createdAfter=2024-01-01 |
sortBy | string | No | Sort field | ?sortBy=visitDate |
sortDirection | string | No | Sort direction (asc or desc) | ?sortDirection=desc |
expand | string | No | Related resources to include | ?expand=cenote,guest |
Status Values
| Status | Description |
|---|---|
pending | Reservation created, awaiting payment |
confirmed | Payment received, reservation confirmed |
cancelled | Reservation cancelled |
no_show | Guest didn't arrive |
completed | Visit completed successfully |
refunded | Reservation refunded |
Example Request
curl -X GET "https://service-gateway.loscenotes.com/partner/reservations?status=confirmed&dateFrom=2024-07-15" \
-H "X-API-Key: pk_live_your_api_key" \
-H "Content-Type: application/json"
Example Response
{
"success": true,
"message": "reservations.list_retrieved_successfully",
"data": [
{
"id": "res_1234567890abcdef",
"bookingReference": "LC-2024-001234",
"status": "confirmed",
"cenoteId": "c3n0t3-1234-5678-90ab",
"visitDate": "2024-07-15",
"visitTime": "10:00",
"visitors": {
"total": 4,
"breakdown": {
"adults": 2,
"children": 2,
"seniors": 0
}
},
"guest": {
"name": "John Smith",
"email": "john@example.com",
"phone": "+1-555-123-4567",
"nationality": "US",
"emergencyContact": {
"name": "Jane Smith",
"phone": "+1-555-987-6543"
}
},
"pricing": {
"subtotal": 1100,
"taxes": 176,
"fees": 50,
"total": 1326,
"currency": "MXN",
"breakdown": [
{
"type": "adult",
"quantity": 2,
"unitPrice": 350,
"total": 700
},
{
"type": "child",
"quantity": 2,
"unitPrice": 200,
"total": 400
}
],
"discounts": [
{
"type": "group_discount",
"name": "Group of 4+",
"amount": 110,
"percentage": 0.1
}
]
},
"payment": {
"id": "pay_abcd1234",
"status": "completed",
"method": "credit_card",
"provider": "stripe",
"transactionId": "txn_stripe_123456",
"paidAt": "2024-07-10T14:30:00Z"
},
"services": [
{
"id": "srv_guide_001",
"name": "Professional Guide",
"type": "guide",
"price": 150,
"duration": 120,
"included": false
},
{
"id": "srv_transport_001",
"name": "Hotel Pickup",
"type": "transport",
"price": 300,
"pickup": {
"location": "Hotel Xcaret",
"time": "08:00"
},
"included": false
}
],
"specialRequests": "Vegetarian lunch option for 2 people",
"notes": {
"internal": "First-time visitors, extra guidance needed",
"guest": "Celebrating anniversary"
},
"cancellation": {
"allowed": true,
"deadline": "2024-07-13T23:59:59Z",
"policy": {
"fullRefund": "48_hours",
"partialRefund": "24_hours",
"noRefund": "same_day"
}
},
"confirmationSent": true,
"reminderSent": false,
"checkIn": null,
"cenote": {
"id": "c3n0t3-1234-5678-90ab",
"name": "Cenote Dos Ojos",
"location": {
"latitude": 20.327423,
"longitude": -87.382118,
"address": "Carretera Tulum-Coba Km 5.5"
},
"contact": {
"phone": "+52 984 123 4567"
}
},
"metadata": {
"source": "website",
"userAgent": "Mozilla/5.0...",
"referrer": "https://google.com",
"affiliateId": null
},
"createdAt": "2024-07-10T14:25:00Z",
"updatedAt": "2024-07-10T14:30:00Z"
}
],
"pagination": {
"total": 156,
"perPage": 15,
"currentPage": 1,
"lastPage": 11,
"hasNextPage": true,
"hasPreviousPage": false
}
}
Create Reservation
Create a new cenote reservation.
POST /partner/reservations
Request Body
{
"cenoteId": "c3n0t3-1234-5678-90ab",
"visitDate": "2024-07-15",
"visitTime": "10:00",
"visitors": {
"adults": 2,
"children": 2,
"seniors": 0
},
"guest": {
"name": "John Smith",
"email": "john@example.com",
"phone": "+1-555-123-4567",
"nationality": "US",
"dateOfBirth": "1985-03-15",
"emergencyContact": {
"name": "Jane Smith",
"phone": "+1-555-987-6543",
"relationship": "spouse"
}
},
"services": [
{
"id": "srv_guide_001",
"quantity": 1
},
{
"id": "srv_transport_001",
"pickup": {
"location": "Hotel Xcaret",
"time": "08:00"
}
}
],
"specialRequests": "Vegetarian lunch option for 2 people",
"promoCode": "SUMMER2024",
"metadata": {
"source": "mobile_app",
"affiliateId": "partner_123"
}
}
Field Descriptions
| Field | Type | Required | Description |
|---|---|---|---|
cenoteId | string | Yes | UUID of the cenote |
visitDate | string | Yes | Visit date (YYYY-MM-DD) |
visitTime | string | No | Preferred time slot (HH:MM) |
visitors | object | Yes | Visitor count by type |
guest | object | Yes | Primary guest information |
services | array | No | Additional services |
specialRequests | string | No | Special requests or notes |
promoCode | string | No | Promotional code |
metadata | object | No | Additional metadata |
Example Request
curl -X POST "https://service-gateway.loscenotes.com/partner/reservations" \
-H "X-API-Key: pk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"cenoteId": "c3n0t3-1234-5678-90ab",
"visitDate": "2024-07-15",
"visitTime": "10:00",
"visitors": {
"adults": 2,
"children": 2
},
"guest": {
"name": "John Smith",
"email": "john@example.com",
"phone": "+1-555-123-4567"
}
}'
Example Response
{
"success": true,
"message": "reservation.created_successfully",
"data": {
"id": "res_1234567890abcdef",
"bookingReference": "LC-2024-001234",
"status": "pending",
"cenoteId": "c3n0t3-1234-5678-90ab",
"visitDate": "2024-07-15",
"visitTime": "10:00",
"visitors": {
"total": 4,
"breakdown": {
"adults": 2,
"children": 2,
"seniors": 0
}
},
"pricing": {
"subtotal": 1100,
"taxes": 176,
"fees": 50,
"total": 1326,
"currency": "MXN",
"breakdown": [
{
"type": "adult",
"quantity": 2,
"unitPrice": 350,
"total": 700
},
{
"type": "child",
"quantity": 2,
"unitPrice": 200,
"total": 400
}
]
},
"payment": {
"required": true,
"deadline": "2024-07-12T23:59:59Z",
"methods": ["credit_card", "paypal", "cash"],
"instructions": {
"creditCard": {
"url": "https://checkout.loscenotes.com/pay/res_1234567890abcdef"
}
}
},
"cancellation": {
"allowed": true,
"deadline": "2024-07-13T23:59:59Z",
"policy": {
"fullRefund": "48_hours",
"partialRefund": "24_hours",
"noRefund": "same_day"
}
},
"confirmationCode": "LC001234",
"qrCode": {
"url": "https://service-gateway.loscenotes.com/partner/reservations/res_1234567890abcdef/qr",
"data": "loscenotes://reservation/res_1234567890abcdef"
},
"createdAt": "2024-07-10T14:25:00Z",
"expiresAt": "2024-07-12T23:59:59Z"
}
}
Get Reservation Details
Retrieve detailed information about a specific reservation.
GET /partner/reservations/{id}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Reservation ID or booking reference |
expand | string | No | Related resources to include |
Expansion Options
| Value | Description |
|---|---|
cenote | Include complete cenote information |
payment | Include detailed payment information |
services | Include full service details |
reviews | Include guest reviews (if completed) |
Example Request
curl -X GET "https://service-gateway.loscenotes.com/partner/reservations/res_1234567890abcdef?expand=cenote,payment" \
-H "X-API-Key: pk_live_your_api_key"
Example Response
{
"success": true,
"message": "reservation.retrieved_successfully",
"data": {
"id": "res_1234567890abcdef",
"bookingReference": "LC-2024-001234",
"status": "confirmed",
"statusHistory": [
{
"status": "pending",
"timestamp": "2024-07-10T14:25:00Z",
"note": "Reservation created"
},
{
"status": "confirmed",
"timestamp": "2024-07-10T14:30:00Z",
"note": "Payment received"
}
],
"timeline": {
"created": "2024-07-10T14:25:00Z",
"paymentDeadline": "2024-07-12T23:59:59Z",
"cancellationDeadline": "2024-07-13T23:59:59Z",
"visitDate": "2024-07-15T10:00:00Z",
"completionDeadline": "2024-07-15T23:59:59Z"
},
"documents": [
{
"type": "confirmation",
"name": "Booking Confirmation",
"url": "https://documents.loscenotes.com/confirmations/res_1234567890abcdef.pdf",
"generatedAt": "2024-07-10T14:30:00Z"
},
{
"type": "ticket",
"name": "Entry Ticket",
"url": "https://documents.loscenotes.com/tickets/res_1234567890abcdef.pdf",
"qrCode": "https://service-gateway.loscenotes.com/partner/reservations/res_1234567890abcdef/qr"
}
],
"communications": [
{
"type": "confirmation_email",
"status": "sent",
"sentAt": "2024-07-10T14:31:00Z",
"recipient": "john@example.com"
},
{
"type": "reminder_sms",
"status": "scheduled",
"scheduledFor": "2024-07-14T18:00:00Z",
"recipient": "+1-555-123-4567"
}
],
"modifications": {
"allowed": true,
"deadline": "2024-07-13T23:59:59Z",
"allowedChanges": ["visitTime", "visitorCount", "services"],
"restrictions": ["Visit date cannot be changed within 48 hours"]
}
}
}
Update Reservation
Modify an existing reservation.
Request Body
{
"visitTime": "14:00",
"visitors": {
"adults": 3,
"children": 1
},
"specialRequests": "Updated dietary requirements: gluten-free options needed",
"guest": {
"phone": "+1-555-999-8888"
},
"services": [
{
"id": "srv_photography_001",
"quantity": 1,
"action": "add"
},
{
"id": "srv_guide_001",
"action": "remove"
}
]
}
Service Actions
| Action | Description |
|---|---|
add | Add a new service |
remove | Remove an existing service |
update | Update service parameters |
Example Response
{
"success": true,
"message": "reservation.updated_successfully",
"data": {
"id": "res_1234567890abcdef",
"changes": [
{
"field": "visitTime",
"oldValue": "10:00",
"newValue": "14:00"
},
{
"field": "visitors.adults",
"oldValue": 2,
"newValue": 3
},
{
"field": "services",
"added": ["srv_photography_001"],
"removed": ["srv_guide_001"]
}
],
"pricing": {
"previousTotal": 1326,
"newTotal": 1485,
"difference": 159,
"currency": "MXN"
},
"payment": {
"additionalPaymentRequired": true,
"amount": 159,
"deadline": "2024-07-13T23:59:59Z",
"paymentUrl": "https://checkout.loscenotes.com/pay/res_1234567890abcdef/additional"
}
}
}
Confirm Reservation
Confirm a pending reservation (typically after payment).
POST /partner/reservations/{id}/cancel
Request Body
{
"paymentId": "pay_abcd1234",
"paymentMethod": "credit_card",
"transactionId": "txn_stripe_123456",
"confirmationEmail": true,
"generateDocuments": true
}
Example Response
{
"success": true,
"message": "reservation.confirmed_successfully",
"data": {
"id": "res_1234567890abcdef",
"status": "confirmed",
"confirmationCode": "LC001234",
"payment": {
"id": "pay_abcd1234",
"status": "completed",
"confirmedAt": "2024-07-10T14:30:00Z"
},
"documents": {
"confirmation": "https://documents.loscenotes.com/confirmations/res_1234567890abcdef.pdf",
"ticket": "https://documents.loscenotes.com/tickets/res_1234567890abcdef.pdf"
},
"communications": {
"confirmationEmail": {
"sent": true,
"sentAt": "2024-07-10T14:31:00Z"
}
}
}
}
Cancel Reservation
Cancel an existing reservation.
POST /partner/reservations/{id}/cancel
Request Body
{
"reason": "guest_request",
"note": "Change of travel plans",
"refund": {
"requested": true,
"method": "original_payment_method",
"amount": "auto"
},
"notifyGuest": true
}
Cancellation Reasons
| Reason | Description |
|---|---|
guest_request | Guest-initiated cancellation |
weather | Weather-related cancellation |
maintenance | Cenote maintenance required |
capacity_issue | Capacity or availability issue |
force_majeure | Unforeseeable circumstances |
Example Response
{
"success": true,
"message": "reservation.cancelled_successfully",
"data": {
"id": "res_1234567890abcdef",
"status": "cancelled",
"cancellation": {
"reason": "guest_request",
"cancelledAt": "2024-07-12T10:15:00Z",
"cancelledBy": "guest",
"note": "Change of travel plans"
},
"refund": {
"eligible": true,
"amount": 1195.4,
"fees": 130.6,
"processingTime": "5-10 business days",
"refundId": "ref_xyz789",
"status": "processing"
},
"communications": {
"cancellationEmail": {
"sent": true,
"sentAt": "2024-07-12T10:16:00Z"
}
}
}
}
Check-In Guest
Mark a guest as checked in for their reservation.
POST /partner/reservations/{id}/checkin
Request Body
{
"checkedInAt": "2024-07-15T10:05:00Z",
"actualVisitors": {
"adults": 2,
"children": 2
},
"staff": {
"name": "Maria Rodriguez",
"id": "staff_456"
},
"notes": "Guests arrived on time, provided safety briefing"
}
Example Response
{
"success": true,
"message": "reservation.checked_in_successfully",
"data": {
"id": "res_1234567890abcdef",
"status": "in_progress",
"checkIn": {
"checkedInAt": "2024-07-15T10:05:00Z",
"expectedDeparture": "2024-07-15T12:05:00Z",
"actualVisitors": {
"adults": 2,
"children": 2
},
"staff": {
"name": "Maria Rodriguez",
"id": "staff_456"
}
}
}
}
Complete Visit
Mark a reservation as completed after the guest visit.
POST /partner/reservations/{id}/complete
Request Body
{
"completedAt": "2024-07-15T12:30:00Z",
"actualDuration": 150,
"feedback": {
"requestReview": true,
"followUpEmail": true
},
"staff": {
"name": "Maria Rodriguez",
"id": "staff_456"
},
"notes": "Great experience, guests very satisfied"
}
Example Response
{
"success": true,
"message": "reservation.completed_successfully",
"data": {
"id": "res_1234567890abcdef",
"status": "completed",
"completion": {
"completedAt": "2024-07-15T12:30:00Z",
"actualDuration": 150,
"totalVisitTime": "10:05-12:30"
},
"reviewRequest": {
"sent": true,
"link": "https://reviews.loscenotes.com/res_1234567890abcdef",
"expires": "2024-08-15T23:59:59Z"
}
}
}
Data Models
Reservation Object
interface Reservation {
id: string; // UUID identifier
bookingReference: string; // Human-readable reference
status: ReservationStatus; // Current status
cenoteId: string; // Cenote UUID
visitDate: string; // Visit date (YYYY-MM-DD)
visitTime: string; // Time slot (HH:MM)
visitors: VisitorCount; // Visitor breakdown
guest: Guest; // Primary guest info
pricing: PricingBreakdown; // Price calculation
payment?: Payment; // Payment information
services?: Service[]; // Additional services
specialRequests?: string; // Special requests
notes?: Notes; // Internal/guest notes
cancellation?: Cancellation; // Cancellation policy
checkIn?: CheckIn; // Check-in information
timeline?: Timeline; // Important dates
documents?: Document[]; // Generated documents
communications?: Communication[]; // Email/SMS history
metadata?: Metadata; // Additional metadata
createdAt: string; // Creation timestamp
updatedAt: string; // Last update timestamp
}
Guest Object
interface Guest {
name: string; // Full name
email: string; // Email address
phone: string; // Phone number
nationality?: string; // Country code (ISO 3166)
dateOfBirth?: string; // Date of birth
emergencyContact?: EmergencyContact; // Emergency contact
preferences?: GuestPreferences; // Guest preferences
loyaltyMember?: LoyaltyInfo; // Loyalty program info
}
interface EmergencyContact {
name: string; // Contact name
phone: string; // Contact phone
relationship: string; // Relationship to guest
}
Pricing Breakdown Object
interface PricingBreakdown {
subtotal: number; // Before taxes and fees
taxes: number; // Tax amount
fees: number; // Service fees
total: number; // Final total
currency: string; // ISO currency code
breakdown: PriceItem[]; // Itemized breakdown
discounts?: Discount[]; // Applied discounts
}
interface PriceItem {
type: "adult" | "child" | "senior" | "service"; // Item type
name?: string; // Item name
quantity: number; // Quantity
unitPrice: number; // Price per unit
total: number; // Total for this item
}
Error Responses
Reservation Not Found
{
"success": false,
"error": {
"code": "RESERVATION_NOT_FOUND",
"message": "The requested reservation was not found",
"status": 404,
"details": {
"reservationId": "invalid-id"
}
}
}
Cenote Not Available
{
"success": false,
"error": {
"code": "CENOTE_NOT_AVAILABLE",
"message": "The cenote is not available for the selected date and time",
"status": 422,
"details": {
"cenoteId": "c3n0t3-1234",
"date": "2024-07-15",
"time": "10:00",
"reason": "fully_booked",
"alternatives": [
{
"date": "2024-07-15",
"time": "14:00",
"available": true
},
{
"date": "2024-07-16",
"time": "10:00",
"available": true
}
]
}
}
}
Insufficient Capacity
{
"success": false,
"error": {
"code": "INSUFFICIENT_CAPACITY",
"message": "Not enough capacity for the requested number of visitors",
"status": 422,
"details": {
"requested": 8,
"available": 3,
"cenoteId": "c3n0t3-1234",
"date": "2024-07-15",
"time": "10:00"
}
}
}
Modification Not Allowed
{
"success": false,
"error": {
"code": "MODIFICATION_NOT_ALLOWED",
"message": "Reservation cannot be modified at this time",
"status": 422,
"details": {
"reason": "too_close_to_visit_date",
"deadline": "2024-07-13T23:59:59Z",
"currentTime": "2024-07-14T10:00:00Z"
}
}
}
Code Examples
JavaScript (fetch)
const apiKey = process.env.LOSCENOTES_API_KEY;
const baseUrl = 'https://service-gateway.loscenotes.com';
const headers = {
'X-API-Key': apiKey,
'Content-Type': 'application/json',
'Accept-Language': 'es'
};
// List reservations
const listResponse = await fetch(
`${baseUrl}/partner/reservations?status=confirmed`,
{ headers }
);
const reservations = await listResponse.json();
console.log('Reservations:', reservations.data);
// Get single reservation
const getResponse = await fetch(
`${baseUrl}/partner/reservations/reservation-uuid`,
{ headers }
);
const reservation = await getResponse.json();
console.log('Reservation:', reservation.data);
// Cancel reservation
const cancelResponse = await fetch(
`${baseUrl}/partner/reservations/reservation-uuid/cancel`,
{
method: 'POST',
headers,
body: JSON.stringify({
reason: 'guest_request',
notes: 'Change of travel plans'
})
}
);
const cancelled = await cancelResponse.json();
console.log('Cancelled:', cancelled.data);
Python (requests)
import os
import requests
api_key = os.environ.get('LOSCENOTES_API_KEY')
base_url = 'https://service-gateway.loscenotes.com'
headers = {
'X-API-Key': api_key,
'Content-Type': 'application/json',
'Accept-Language': 'es'
}
# List reservations
response = requests.get(
f'{base_url}/partner/reservations',
headers=headers,
params={'status': 'confirmed'}
)
reservations = response.json()
print('Reservations:', reservations['data'])
# Get reservation
response = requests.get(
f'{base_url}/partner/reservations/reservation-uuid',
headers=headers
)
reservation = response.json()
print('Reservation:', reservation['data'])
PHP (cURL)
<?php
$apiKey = getenv('LOSCENOTES_API_KEY');
$baseUrl = 'https://service-gateway.loscenotes.com';
$headers = [
'X-API-Key: ' . $apiKey,
'Content-Type: application/json',
'Accept-Language: es'
];
// List reservations
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $baseUrl . '/partner/reservations?status=confirmed',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($ch);
curl_close($ch);
$reservations = json_decode($response, true);
print_r($reservations['data']);
?>
Next Steps
- Pricing & Age Groups - Price calculations and age multipliers
- Services - Cenote and tour services
- Checkout & Payments - Payment processing
- Discounts & Coupons - Apply discounts