{"openapi":"3.0.0","info":{"title":"Joyryde API","description":"Direct vehicle rental API for Joyryde Denver. Designed for both human-facing applications and AI agent access.","version":"1.0.0","contact":{"email":"joyrydelimited@gmail.com"}},"servers":[{"url":"https://joy-ryde-platform-v2-production.up.railway.app","description":"Production"}],"paths":{"/api/vehicles":{"get":{"summary":"List vehicle categories with live fleet counts","parameters":[{"name":"type","in":"query","schema":{"type":"string","enum":["long-term","short-term"]},"description":"Filter by rental type"}],"responses":{"200":{"description":"Vehicle categories with availability counts","content":{"application/json":{"schema":{"type":"object","properties":{"vehicles":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"image":{"type":"string"},"description":{"type":"string"},"rental_types":{"type":"array","items":{"type":"string"}},"available_count":{"type":"integer"}}}},"total_listed":{"type":"integer"},"source":{"type":"string"},"rental_type_filter":{"type":"string"}}}}}}}}},"/api/vehicles/{slug}":{"get":{"summary":"Get single vehicle category by slug","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"Vehicle category slug (e.g. economy-sedan)"}],"responses":{"200":{"description":"Vehicle category details"},"404":{"description":"Category not found"}}}},"/api/bookings":{"post":{"summary":"Submit a new booking","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["bookingType","firstName","lastName","email","phone"],"properties":{"bookingType":{"type":"string","enum":["standard","gig"]},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"vehicleClass":{"type":"string"},"vehicleLabel":{"type":"string"},"dailyRate":{"type":"number"},"monthlyRate":{"type":"number"},"pickupDate":{"type":"string","format":"date"},"returnDate":{"type":"string","format":"date"},"pickupLocation":{"type":"string"},"totalAmount":{"type":"number"}}}}}},"responses":{"200":{"description":"Booking created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"refNumber":{"type":"string"},"bookingId":{"type":"integer"},"status":{"type":"string"}}}}}}}},"get":{"summary":"List all bookings (admin)","parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pending","confirmed","active","returned","cancelled"]}},{"name":"type","in":"query","schema":{"type":"string","enum":["standard","gig"]}},{"name":"limit","in":"query","schema":{"type":"integer","default":50}},{"name":"offset","in":"query","schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"List of bookings with pagination"}}}},"/api/bookings/{ref}":{"get":{"summary":"Get single booking by reference number","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string"},"description":"Booking reference (e.g. JR-123456)"}],"responses":{"200":{"description":"Booking details"},"404":{"description":"Booking not found"}}}},"/api/bookings/{ref}/status":{"patch":{"summary":"Update booking status","parameters":[{"name":"ref","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","confirmed","active","returned","cancelled"]}}}}}},"responses":{"200":{"description":"Status updated"}}}},"/api/checkout/long-term":{"post":{"summary":"Initialize long-term booking checkout (Stripe enrollment)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["firstName","lastName","email","phone","vehicleClass","pickupDate"],"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"vehicleClass":{"type":"string","enum":["Economy Sedan","Midsize Sedan"]},"pickupDate":{"type":"string","format":"date"},"rentalTerm":{"type":"string","enum":["3","6","12"]},"insuranceTier":{"type":"string","enum":["basic","standard","zero"]},"typedSignature":{"type":"string"},"signedAt":{"type":"string"}}}}}},"responses":{"200":{"description":"Stripe checkout session created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"refNumber":{"type":"string"},"checkoutUrl":{"type":"string"},"sessionId":{"type":"string"}}}}}}}}},"/api/checkout/short-term":{"post":{"summary":"Initialize short-term booking checkout (Stripe payment)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["firstName","lastName","email","phone","vehicleClass","pickupDate","returnDate","totalAmount"],"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"vehicleClass":{"type":"string"},"vehicleLabel":{"type":"string"},"dailyRate":{"type":"number"},"pickupDate":{"type":"string","format":"date"},"returnDate":{"type":"string","format":"date"},"totalAmount":{"type":"number"}}}}}},"responses":{"200":{"description":"Payment intent created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"refNumber":{"type":"string"},"clientSecret":{"type":"string"},"reservationAmount":{"type":"string"},"totalAmount":{"type":"string"},"remainingAmount":{"type":"string"}}}}}}}}},"/api/checkout/success":{"get":{"summary":"Verify booking after successful payment","parameters":[{"name":"ref","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Booking verification result"}}}},"/api/contact":{"post":{"summary":"Submit contact form message","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","email"],"properties":{"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"message":{"type":"string"},"source":{"type":"string","default":"website"}}}}}},"responses":{"200":{"description":"Message received"}}}},"/api/leads":{"post":{"summary":"Capture lead from form submission","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["contact_preference"],"properties":{"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"contact_preference":{"type":"string","enum":["newsletter","email","text","call"]},"monthly_miles":{"type":"number"},"car_payment":{"type":"number"},"utm_source":{"type":"string"},"utm_medium":{"type":"string"},"utm_campaign":{"type":"string"}}}}}},"responses":{"200":{"description":"Lead captured","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"leadId":{"type":"integer"}}}}}}}}},"/api/leads/unsubscribe":{"post":{"summary":"Unsubscribe from newsletter","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Unsubscribed successfully"}}}},"/api/leads/resubscribe":{"post":{"summary":"Resubscribe to newsletter","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Resubscribed successfully"}}}},"/api/smart/chat":{"post":{"summary":"AI financial advisor chatbot","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["messages"],"properties":{"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string","maxLength":2000}}}}}}}}},"responses":{"200":{"description":"AI response","content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string"},"usage":{"type":"object","properties":{"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"}}}}}}}}}}},"/api/ask":{"post":{"summary":"Natural language query endpoint for AI agents","description":"Accepts plain English questions and returns structured JSON. Stub endpoint — full NL processing will be added in a future release.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["query"],"properties":{"query":{"type":"string","description":"Plain English question about vehicles, availability, or booking"}}}}}},"responses":{"200":{"description":"Structured response with available endpoints"}}}},"/api/webhooks/twilio/sms":{"post":{"summary":"Twilio inbound SMS webhook + Rocky kill switch","description":"Receives inbound SMS. Validates Twilio signature. Owner can send !STOP ALL / !STOP <agent> to halt Rocky agents, !RESUME ALL / !RESUME <agent> to resume.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"From":{"type":"string"},"Body":{"type":"string"},"MessageSid":{"type":"string"}}}}}},"responses":{"200":{"description":"TwiML response","content":{"text/xml":{}}}}}},"/rocky/mcp/tools":{"get":{"summary":"List available Rocky MCP tools for authenticated user","description":"Returns tools scoped to the user's tenant and permission tier. Requires Bearer token auth.","parameters":[{"name":"tenant_id","in":"query","schema":{"type":"string"},"description":"Tenant to scope tools for"}],"responses":{"200":{"description":"List of MCP tools"}}}},"/rocky/mcp/call":{"post":{"summary":"Execute a Rocky MCP tool","description":"Calls a registered Rocky agent tool. Rate limited. Requires Bearer token auth.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tool_name"],"properties":{"tool_name":{"type":"string"},"input":{"type":"object"},"tenant_id":{"type":"string"},"conversation_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Tool execution result"}}}},"/rocky/mcp/conversation":{"post":{"summary":"Chat with Rocky AI (Owner Console / Camille PWA)","description":"Sends a message to Rocky with all available MCP tools attached. Rocky can use tools to answer questions about fleet, operations, etc.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"conversation_id":{"type":"string"},"tenant_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Rocky AI response"}}}},"/rocky/mcp/kill":{"post":{"summary":"Rocky kill switch (owner only)","description":"Halts all or specific Rocky agents by reverting trust stage to shadow mode.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"agent_name":{"type":"string","description":"Agent to halt (null = halt all)"}}}}}},"responses":{"200":{"description":"Agent halted confirmation"}}}},"/api/checkin/validate-token":{"post":{"summary":"Validate check-in token and return booking state","tags":["Check-In"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]}}}},"responses":{"200":{"description":"Token validation result with booking details"}}}},"/api/checkin/upload-photo":{"post":{"summary":"Upload identity or vehicle condition photo","tags":["Check-In"],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"token":{"type":"string"},"photo_type":{"type":"string","enum":["license_front","license_back","selfie","vehicle_front","vehicle_back","vehicle_left","vehicle_right"]},"photo":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"Upload result"}}}},"/api/checkin/authorize-payment":{"post":{"summary":"Authorize remaining balance hold on saved card","tags":["Check-In"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Authorization result with amount"}}}},"/api/checkin/vehicle-photos-complete":{"post":{"summary":"Complete check-in — captures payment and reveals lockbox code","tags":["Check-In"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Lockbox code and completion status"}}}},"/api/checkin/status":{"get":{"summary":"Get current check-in progress","tags":["Check-In"],"parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Check-in status with photo and payment state"}}}},"/api/admin/bookings/{bookingId}/assign-vehicle":{"post":{"summary":"Assign vehicle details to a booking","tags":["Admin"],"parameters":[{"name":"bookingId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Vehicle assignment result"}}}},"/api/admin/bookings/{bookingId}/send-checkin-email":{"post":{"summary":"Manually trigger check-in email","tags":["Admin"],"parameters":[{"name":"bookingId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email send result"}}}},"/api/admin/bookings/{bookingId}/manual-checkin":{"post":{"summary":"Override check-in steps manually","tags":["Admin"],"parameters":[{"name":"bookingId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Manual check-in result with lockbox code"}}}},"/api/admin/bookings/{bookingId}/reset-checkin":{"post":{"summary":"Reset check-in state for re-testing","tags":["Admin"],"parameters":[{"name":"bookingId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Reset result"}}}},"/health":{"get":{"summary":"Health check","responses":{"200":{"description":"Service status","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"service":{"type":"string"},"version":{"type":"string"},"timestamp":{"type":"string"}}}}}}}}}}}