Skip to main content

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

ParameterTypeRequiredDescriptionExample
pageintegerNoPage number (default: 1)?page=1
perPageintegerNoItems per page (default: 15, max: 100)?perPage=20
cursorstringNoCursor for cursor-based pagination?cursor=eyJpZCI6InJlc18xMjM0In0
statusstringNoFilter by status?status=confirmed
cenoteIdstringNoFilter by cenote ID?cenoteId=c3n0t3-1234
guestEmailstringNoFilter by guest email?guestEmail=guest@example.com
dateFromstringNoFilter from date (ISO 8601)?dateFrom=2024-07-01
dateTostringNoFilter to date (ISO 8601)?dateTo=2024-07-31
createdAfterstringNoFilter by creation date?createdAfter=2024-01-01
sortBystringNoSort field?sortBy=visitDate
sortDirectionstringNoSort direction (asc or desc)?sortDirection=desc
expandstringNoRelated resources to include?expand=cenote,guest

Status Values

StatusDescription
pendingReservation created, awaiting payment
confirmedPayment received, reservation confirmed
cancelledReservation cancelled
no_showGuest didn't arrive
completedVisit completed successfully
refundedReservation 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

FieldTypeRequiredDescription
cenoteIdstringYesUUID of the cenote
visitDatestringYesVisit date (YYYY-MM-DD)
visitTimestringNoPreferred time slot (HH:MM)
visitorsobjectYesVisitor count by type
guestobjectYesPrimary guest information
servicesarrayNoAdditional services
specialRequestsstringNoSpecial requests or notes
promoCodestringNoPromotional code
metadataobjectNoAdditional 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

ParameterTypeRequiredDescription
idstringYesReservation ID or booking reference
expandstringNoRelated resources to include

Expansion Options

ValueDescription
cenoteInclude complete cenote information
paymentInclude detailed payment information
servicesInclude full service details
reviewsInclude 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

ActionDescription
addAdd a new service
removeRemove an existing service
updateUpdate 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

ReasonDescription
guest_requestGuest-initiated cancellation
weatherWeather-related cancellation
maintenanceCenote maintenance required
capacity_issueCapacity or availability issue
force_majeureUnforeseeable 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