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.

Maleku System’s marketplace is the central hub that connects travelers with Costa Rican tourism vendors. Vendors register on the platform, complete a verification process, and then publish listings across five categories — properties/hotels, tours, vehicles, boats, and flights. Every listing is owned by a specific vendor, gated behind role-based access control, and served through a Redis-backed cache layer for high-throughput browsing. The platform takes a 10% commission on each completed transaction, keeping listing creation completely free for vendors.

Listing Categories

Each category maps to a dedicated FastAPI router and SQLAlchemy model, with its own set of filters, CRUD endpoints, and pricing logic.
CategoryDescription
Properties / HotelsAccommodation listings (hotels, hostels, eco-lodges, resorts, villas, apartments, cabins, glamping sites, boutique hotels, and aparthotels). Supports room-level pricing, weekend rates, and availability calendars.
ToursExperience listings such as adventure, nature, cultural, water, wellness, gastronomy, beach, and wildlife tours. Priced per person with configurable group sizes and schedule days.
VehiclesCar rental listings filtered by VehicleType (car, suv, van, minibus, motorcycle), seat count, and location. Priced per day with optional weekly and monthly rates.
BoatsNautical equipment rental filtered by BoatType (boat, jet_ski, kayak, paddleboard, equipment), location, and passenger capacity.
FlightsFlight listings managed under the same vendor model, allowing operators to list scheduled or charter departures alongside other services.

Vendor Verification

Before any listing appears publicly in search results or the browsable catalogue, the vendor account must be verified by a platform admin. The verification workflow is:
  1. Vendor Registration — A user registers and creates a vendor profile (POST /api/v1/vendors/). The profile is assigned VendorStatus.PENDING and is_verified = False.
  2. Admin Review — A SUPER_ADMIN or ADMIN calls POST /api/v1/vendors/{id}/verify. This flips is_verified to True and transitions the status to VendorStatus.ACTIVE.
  3. Listings Go Live — Only after verification can the vendor’s listings be returned by public endpoints. API queries filter on is_active = True; inactive or unverified vendor listings are silently excluded.
  4. Suspension — Admins can set a vendor status to VendorStatus.SUSPENDED or VendorStatus.REJECTED at any time, immediately hiding all their listings.
The four possible VendorStatus values are pending, active, suspended, and rejected.

Image Management

All listing images are stored and served via Cloudinary CDN. The integration is handled by cloudinary_service.py with the following behaviour:
  • Upload endpoint — Images are uploaded via POST /api/v1/{resource}/{id}/images (e.g. POST /api/v1/properties/{id}/images). The upload handler in upload.py validates file type (jpg, jpeg, png, gif, webp), enforces a maximum file size, and checks the raw bytes before handing off to Cloudinary.
  • Folder prefix — Every asset is stored under the CLOUDINARY_FOLDER_PREFIX configured in settings, which defaults to costaricatravel. Sub-folders are appended per resource type (e.g. costaricatravel/properties, costaricatravel/tours).
  • Automatic optimisation — Cloudinary applies automatic format selection and quality optimisation at delivery time; the backend stores only the secure_url returned by the API.
  • Fallback — If Cloudinary is not configured or the upload fails, the service falls back to local file storage and logs a warning, so development environments work without credentials.
  • Cover image — A separate PUT /api/v1/properties/{id}/cover endpoint sets the cover_image field without re-uploading. Deleting an image via DELETE /api/v1/properties/{id}/images also clears cover_image if it matches the removed URL.

Listing Lifecycle

All listing models (Property, Tour, Vehicle, BoatEquipment) follow the same four-stage lifecycle:
1

Create (Vendor)

An authenticated vendor submits a POST request to the appropriate listing endpoint (e.g. POST /api/v1/properties/). The backend enforces mass-assignment protection via an ALLOWED_FIELDS allowlist, resolves the vendor profile from the JWT identity, auto-generates a URL slug ({name-slug}-{8-char uuid}), and persists the record with is_active = True.
2

Publish / Approve

Properties and tours become publicly visible as soon as is_active = True and the owning vendor is verified. Admins can additionally toggle is_featured to surface listings in featured carousels (cached at a shorter TTL of 180 s).
3

Update

Vendors update their own listings with PUT /api/v1/{resource}/{id}. Ownership is verified by matching the JWT vendor profile against the listing’s vendor_id. SUPER_ADMIN can update any listing. On save, the relevant Redis cache keys are invalidated.
4

Soft Delete

DELETE /api/v1/{resource}/{id} does not remove the database row. For properties and tours it sets is_active = False; the deleted_at timestamp column is available on all models for hard-delete scenarios or audit queries. All cache keys for the listing and the global listing list are invalidated on delete.
The commission model (10% platform fee) is applied at payment time, not at listing creation. Vendors pay nothing to list; the platform deducts its share only when a booking is paid via Stripe Checkout. The default rate is controlled by STRIPE_COMMISSION_RATE=0.10 in the backend environment, and can be overridden per vendor via the commission_rate column on the Vendor model.

Caching

Maleku System caches listing responses in Redis to minimise database load. Cache keys are tagged so they can be bulk-invalidated when a listing is created, updated, or deleted.
Cache Key PatternTTLInvalidated On
vendors:list:{limit}:{offset}300 sAny vendor create/update/delete
vendors:detail:{vendor_id}600 sSpecific vendor update/delete
vendors:slug:{slug}600 sSpecific vendor update/delete
properties:list:{filters}:{page}300 sAny property create/update/delete
properties:detail:{id}600 sSpecific property update/delete
tours:list:{filters}:{page}300 sAny tour create/update/delete
tours:detail:{id}600 sSpecific tour update/delete
Featured listing queries use a shorter 180 s TTL (CACHE_TTL_FEATURED) to reflect promotional changes more quickly.

Build docs developers (and LLMs) love