Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/IvanchoDev89/maleku-system/llms.txt

Use this file to discover all available pages before exploring further.

The Tours API manages activity and guided-experience listings — from volcano hikes to wildlife tours, surf lessons to cooking classes. Public read endpoints return paginated results backed by a 5-minute cache. Write operations require an authenticated vendor. All tour IDs are UUIDs and slugs are auto-generated. Full-text search is available via the q parameter (searches name and description).

GET /api/v1/tours/

Returns a paginated list of active tours with rich filtering and sorting options.
page
integer
default:"1"
Page number (1-indexed).
page_size
integer
default:"20"
Items per page. Maximum 100.
q
string
Full-text search across name and description (case-insensitive ILIKE).
destination
string
Filter by location. Alias for location — either parameter is accepted. Partial match (ILIKE).
category
string
Filter by tour category. Accepted values: adventure, nature, cultural, water, wellness, gastronomy, beach, wildlife.
difficulty
string
Filter by difficulty level. Accepted values: easy, medium, hard.
min_price
number
Minimum price per person (USD).
max_price
number
Maximum price per person (USD).
min_rating
number
Minimum average rating (0–5). Also accepted as rating (legacy alias).
min_duration
number
Minimum duration in hours.
max_duration
number
Maximum duration in hours.
When true, returns only featured tours. Featured tours use a shorter 3-minute cache TTL.
sort
string
Sort order. Accepted values: popular (by rating desc), price_asc, price_desc, rating (alias for popular), newest. Defaults to newest.
Response 200
{
  "items": [
    {
      "id": "d4e5f6a7-b8c9-0123-def0-123456789abc",
      "name": "Arenal Volcano Hike",
      "slug": "arenal-volcano-hike-d4e5f6a7",
      "category": "adventure",
      "difficulty": "medium",
      "duration_hours": 4.0,
      "location": "La Fortuna",
      "price": 89.00,
      "rating": 4.7,
      "cover_image": "https://res.cloudinary.com/maleku/image/upload/v1/tours/arenal.jpg",
      "is_featured": true
    }
  ],
  "total": 45,
  "page": 1,
  "page_size": 20,
  "total_pages": 3,
  "has_next": true,
  "has_prev": false
}

POST /api/v1/tours/

Creates a new tour listing. A slug is generated automatically from name with a UUID suffix. Only whitelisted fields are accepted to prevent mass assignment. Auth: Bearer token — Vendor or SUPER_ADMIN Rate limit: 10 requests/minute per IP Request body
{
  "name": "Arenal Volcano Hike",
  "description": "Hike through lush trails on the slopes of Arenal volcano with a certified naturalist guide.",
  "category": "adventure",
  "difficulty": "medium",
  "location": "La Fortuna, Alajuela",
  "duration_hours": 4,
  "duration_text": "4 hours",
  "meeting_point": "La Fortuna central park",
  "max_group_size": 12,
  "min_age": 8,
  "price": 89.00,
  "currency": "USD",
  "included": ["certified guide", "transport", "entrance fees", "light snacks"],
  "not_included": ["lunch", "tips", "personal travel insurance"],
  "schedule_days": ["monday", "wednesday", "friday", "saturday"],
  "images": [],
  "is_featured": false
}
Response 201 — full TourResponse including generated id and slug.

GET /api/v1/tours/

Returns a single tour by UUID with vendor details. Response is cached for 10 minutes. You can also look up a tour by its slug at GET /api/v1/tours/slug/{slug}. Response 200TourResponse with all fields including included, not_included, itinerary, schedule_days, and nested vendor summary. Response 404{ "detail": "Tour not found" }

PUT /api/v1/tours/

Updates an existing tour. Only the owning vendor or a SUPER_ADMIN may update. Partial updates are supported — only supplied fields are changed. Auth: Bearer token — Owner Vendor or SUPER_ADMIN Rate limit: 10 requests/minute per IP Request body — any subset of TourUpdate fields, for example:
{
  "price": 95.00,
  "max_group_size": 10,
  "is_featured": true,
  "schedule_days": ["tuesday", "thursday", "saturday", "sunday"]
}
Response 200 — updated TourResponse

DELETE /api/v1/tours/

Soft-deletes a tour by setting is_active = false. The record remains in the database with its deleted_at timestamp updated. Auth: Bearer token — Owner Vendor or SUPER_ADMIN Response 200
{ "message": "Tour deleted successfully" }

Additional Endpoints

MethodPathAuthDescription
GET/api/v1/tours/vendor/myVendorPaginated list of the authenticated vendor’s own tours
GET/api/v1/tours/categoriesPublicDistinct list of categories from active tours
POST/api/v1/tours/{id}/galleryVendorUpload gallery images (Cloudinary or local fallback)

Key Model Fields

FieldTypeDescription
idUUIDPrimary key
vendor_idUUIDFK to vendors
namestring(255)Display name
slugstring(255)URL-friendly unique identifier
categoryenumadventure, nature, cultural, water, wellness, gastronomy, beach, wildlife
difficultyenumeasy, medium, hard
descriptiontextFull markdown description
pricenumeric(10,2)Price per person (USD)
duration_hoursfloatDuration in decimal hours (must be > 0)
duration_textstring(50)Human-readable, e.g. "4 hours"
locationstring(255)Region or city name — used for destination filter
meeting_pointstring(500)Meeting point address
max_group_sizeintegerMaximum participants (must be > 0)
min_ageintegerMinimum age requirement (≥ 0)
includedJSONB arrayWhat’s included in the price
not_includedJSONB arrayWhat is not included
itineraryJSONB arrayArray of itinerary stop objects
cover_imagestring(500)Main listing image URL
imagesJSON arrayAll gallery image URLs
schedule_daysJSON arrayDays of the week the tour operates
is_activebooleanControls public visibility
is_featuredbooleanHighlighted in featured sections
ratingfloatComputed average (0–5)
total_reviewsintegerNumber of approved reviews
total_bookingsintegerLifetime booking count
deleted_attimestampSet on soft delete

TourCategory values

adventure · nature · cultural · water · wellness · gastronomy · beach · wildlife

TourDifficulty values

easy · medium · hard

Build docs developers (and LLMs) love