ResytechResytech Docs

Activities, Calendar & Timeslots

Browse activities, check availability calendars, retrieve time slots, and discover eligible add-ons using the ResytechApi client.

This page covers the read-side of the booking flow: fetching activity details, checking calendar availability, loading time slots for a given date, and discovering eligible add-ons.

All examples assume you have already initialized the API client:

const api = new ResytechApi({ debug: true });
const init = await api.initialization.initialize({ identifier: 'session-1' });

Activities

getActivity

Retrieve full details for a single activity, including equipment, durations, media, custom fields, agreements, and trip protection settings.

const result = await api.activity.getActivity('activity-uuid');

if (result.success) {
  const activity = result.activity;
  console.log(activity.name, '- Base price:', activity.basePrice);
}

Parameters

ParameterTypeRequiredDescription
uuidstringYesActivity unique identifier

ActivityResponse

FieldTypeDescription
successbooleanWhether the request succeeded
activityActivityFull activity details (see below)

Activity Type

FieldTypeDescription
uuidstringUnique identifier
namestringDisplay name
basePricenumberBase price in cents
descriptionstringFull description
cancellationPolicystringCancellation policy text
detailsstringAdditional details
mediaMedia[]Images and videos
durationsDuration[]Available booking durations
equipmentEquipment[]Available equipment (boats, kayaks, etc.)
manifestManifestGuest limits, age restrictions, demographics
firstAvailableDateDateEarliest bookable date
allowEquipmentMixingbooleanWhether customers can book multiple equipment types
maxEquipmentPerBookingnumberMax equipment items per booking
customFieldsCustomField[]Custom form fields for checkout
agreementsActivityAgreement[]Agreements the customer must accept
typenumberActivity type identifier
allowPrivateToursbooleanWhether private tours are available
dynamicDurationSettingsActivityDynamicDurationSettingDynamic duration config
schedulingActivitySchedulingDate range and cutoff settings
tripProtectionTripProtectionTrip protection configuration

Supporting Types

Duration

FieldTypeDescription
uuidstringDuration identifier (pass to cart/calendar requests)
minutesnumberDuration length in minutes

Equipment

FieldTypeDescription
uuidstringEquipment identifier
namestringDisplay name
descriptionstringShort description
detailsstringDetailed info
quantitynumberTotal inventory
capacitynumberSeats per unit
mediaMedia[]Images
addonsAddon[]Equipment-specific add-ons
amenitiesAmenity[]Equipment amenities
propertiesEquipmentProperty[]Custom properties (e.g., length, weight)

Manifest

FieldTypeDescription
guestLimitnumberMaximum guests per booking
ageRestrictionnumberMinimum age
guestMinimumnumberMinimum guests per booking
demographicsDemographic[]Guest demographics (adults, children, etc.)

Media

FieldTypeDescription
uuidstringMedia identifier
ordernumberDisplay order
typenumberMedia type (image, video, etc.)
uristringFull-size URL
thumbnailUristringThumbnail URL

Calendar

Calendar endpoints return monthly availability data. Use them to build date pickers that show which days have open slots.

getActivityCalendar

Get availability for a specific activity in a given month.

const calendar = await api.calendar.getActivityCalendar({
  activity: 'activity-uuid',
  month: 7,
  year: 2025,
  includePrices: true
});

if (calendar.success) {
  calendar.calendar.days.forEach(day => {
    console.log(day.date, day.isAvailable ? `$${day.price}` : 'unavailable');
  });
}

getCartCalendar

Same as getActivityCalendar, but returns availability that accounts for items already in the cart. Use this when the customer is adding a second activity to an existing booking.

const calendar = await api.calendar.getCartCalendar({
  activity: 'activity-uuid',
  month: 7,
  year: 2025,
  cartId: 'existing-cart-id'
});

ActivityCalendarRequest

FieldTypeRequiredDescription
activitystringYesActivity UUID
monthnumberYesMonth (1-12)
yearnumberYesYear (e.g. 2025)
includePricesbooleanNoInclude per-day pricing
durationstringNoDuration UUID to filter by
startTimestringNoFilter by start time
equipmentClientShoppingCartEquipment[]NoEquipment selection to check against
durationMinsnumberNoDuration in minutes (for dynamic durations)
cartIdstringNoCart ID (used by getCartCalendar)

CalendarResponse

FieldTypeDescription
successbooleanWhether the request succeeded
calendarCalendarMonthMonth data with daily availability

CalendarMonth

FieldTypeDescription
monthnumberMonth number (1-12)
yearnumberYear
daysActivityCalendarDay[]Array of day objects

ActivityCalendarDay

FieldTypeDescription
datestringDate string (YYYY-MM-DD)
isAvailablebooleanWhether there is availability on this day
pricenumberStarting price for this day (if includePrices was true)
isEstimatedPricebooleanWhether the price is an estimate
blackoutMessagestringReason the day is blacked out (if applicable)

Time Slots

Once the customer selects a date, load the available time slots for that day.

getActivityTimeSlots

Get time slots for a specific activity on a given date.

const slots = await api.timeslots.getActivityTimeSlots({
  activity: 'activity-uuid',
  date: '2025-07-15',
  durationMins: 60
});

if (slots.success) {
  slots.timeSlots.forEach(slot => {
    console.log(`Price: $${slot.price}, Seats left: ${slot.remainingSeats}`);
  });
}

getLocationTimeSlots

Get time slots for all activities at the location. Useful for location-wide availability views.

const locationSlots = await api.timeslots.getLocationTimeSlots({
  date: '2025-07-15',
  durationMins: 60
});

if (locationSlots.success) {
  locationSlots.results.forEach(activitySlots => {
    console.log('Activity:', activitySlots.uuid);
    console.log('Slots:', activitySlots.slots?.length);
    console.log('Next available:', activitySlots.nextAvailableDate);
  });
}

getCartTimeSlots

Get time slots that account for items already in the active cart.

const cartSlots = await api.timeslots.getCartTimeSlots({
  date: '2025-07-15',
  durationMins: 60
});

TimeSlotRequest

FieldTypeRequiredDescription
datestringYesDate in YYYY-MM-DD format
activitystringNoActivity UUID (recommended for activity-specific queries)
durationstringNoDuration UUID
durationMinsnumberNoDuration in minutes (for dynamic durations)
equipmentClientShoppingCartEquipment[]NoEquipment selection to check availability against
isPrivateTourbooleanNoFilter for private tour availability
ignoreEarlyCutoffbooleanNoIgnore early booking cutoff rules

ActivityTimeSlotsResponse

Returned by getActivityTimeSlots and getCartTimeSlots.

FieldTypeDescription
successbooleanWhether the request succeeded
timeSlotsActivityTimeSlot[]Available time slots

LocationTimeSlotsResponse

Returned by getLocationTimeSlots.

FieldTypeDescription
successbooleanWhether the request succeeded
resultsLocationAllActivityTimeSlots[]Slots grouped by activity

ActivityTimeSlot

FieldTypeDescription
pricenumberPrice for this time slot
remainingSeatsnumberNumber of seats still available
canBookPrivateTourbooleanWhether a private tour can be booked at this time

LocationAllActivityTimeSlots

FieldTypeDescription
uuidstringActivity UUID
slotsActivityTimeSlot[]Available slots for this activity
nextAvailableDatestringNext date with availability (if no slots on requested date)

Add-ons

getEligibleAddons

Retrieve add-ons that are available for a given activity, date, and time combination.

const addons = await api.addon.getEligibleAddons({
  activity: 'activity-uuid',
  date: '2025-07-15',
  time: '10:00'
});

if (addons.success) {
  addons.addons.forEach(addon => {
    console.log(`${addon.name} - $${addon.price} (${addon.quantity} available)`);
  });
}

GetEligibleAddonsRequest

FieldTypeRequiredDescription
activitystringYesActivity UUID
datestringYesDate in YYYY-MM-DD format
timestringYesTime in HH:mm format
durationstringNoDuration UUID
dynamicDurationMinutesnumberNoDuration in minutes (for dynamic durations)
equipmentClientShoppingCartEquipment[]NoEquipment selection for context

GetEligibleAddonsResponse

FieldTypeDescription
successbooleanWhether the request succeeded
addonsEligibleAddon[]List of eligible add-ons

EligibleAddon

FieldTypeDescription
uuidstringAdd-on identifier
namestringDisplay name
descriptionstringDescription
pricenumberPrice per unit
quantitynumberAvailable quantity
mediaUristringImage URL

Full Example: Browse to Book

This example walks through the complete read-side flow: list activities, check the calendar, get time slots, and discover add-ons.

const api = new ResytechApi({ debug: true });

// 1. Initialize and get available activities
const init = await api.initialization.initialize({
  identifier: 'booking-session'
});

if (!init.success) {
  console.error('Init failed:', init.message);
  return;
}

const activities = init.activities;
console.log(`Found ${activities.length} activities`);

// 2. Get full details for the first activity
const activityUuid = activities[0].uuid;
const activityResult = await api.activity.getActivity(activityUuid);
const activity = activityResult.activity;

console.log(`${activity.name} - ${activity.durations.length} durations available`);
console.log(`Equipment: ${activity.equipment.map(e => e.name).join(', ')}`);

// 3. Check calendar for next month
const now = new Date();
const nextMonth = now.getMonth() + 2; // getMonth() is 0-indexed, API is 1-indexed
const year = nextMonth > 12 ? now.getFullYear() + 1 : now.getFullYear();
const month = nextMonth > 12 ? 1 : nextMonth;

const calendar = await api.calendar.getActivityCalendar({
  activity: activityUuid,
  month: month,
  year: year,
  includePrices: true,
  duration: activity.durations[0]?.uuid
});

if (!calendar.success) {
  console.error('Calendar failed:', calendar.message);
  return;
}

// Find the first available date
const availableDay = calendar.calendar.days.find(d => d.isAvailable);
if (!availableDay) {
  console.log('No availability this month');
  return;
}

console.log(`First available: ${availableDay.date} at $${availableDay.price}`);

// 4. Get time slots for that date
const slots = await api.timeslots.getActivityTimeSlots({
  activity: activityUuid,
  date: availableDay.date,
  duration: activity.durations[0]?.uuid
});

if (!slots.success || !slots.timeSlots?.length) {
  console.log('No slots available');
  return;
}

console.log(`${slots.timeSlots.length} time slots available`);
const firstSlot = slots.timeSlots[0];
console.log(`First slot: $${firstSlot.price}, ${firstSlot.remainingSeats} seats`);

// 5. Check for eligible add-ons
const addons = await api.addon.getEligibleAddons({
  activity: activityUuid,
  date: availableDay.date,
  time: '10:00',
  duration: activity.durations[0]?.uuid
});

if (addons.success && addons.addons?.length) {
  console.log('Available add-ons:');
  addons.addons.forEach(a => console.log(`  ${a.name}: $${a.price}`));
}

// Ready to build a cart! See the Cart & Checkout guide.

On this page