{"openapi":"3.0.0","info":{"title":"RAH — Rental Discovery Platform API","version":"1.0.0","description":"REST API documentation for RAH. A role-based rental discovery platform supporting Customers, Listing Partners, and Room Owners.","contact":{"name":"RAH Team"}},"servers":[{"url":"http://localhost:{port}/api","description":"Local development server","variables":{"port":{"default":"5000"}}}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Enter your JWT token obtained from /auth/login or /auth/signup"}},"schemas":{"SignupRequest":{"type":"object","required":["name","email","phone","password"],"properties":{"name":{"type":"string","example":"Sanskar Sharma"},"email":{"type":"string","format":"email","example":"sanskar@example.com"},"phone":{"type":"string","example":"9876543210"},"password":{"type":"string","minLength":6,"example":"secret123"},"role":{"type":"string","enum":["customer","listing_partner","owner"],"default":"customer","example":"customer"}}},"LoginRequest":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"sanskar@example.com"},"password":{"type":"string","example":"secret123"}}},"CreatePropertyRequest":{"type":"object","required":["title","description","rent","deposit","area","city"],"properties":{"title":{"type":"string","example":"2 BHK in Malviya Nagar"},"description":{"type":"string","example":"Spacious 2BHK with balcony, near metro station."},"rent":{"type":"number","example":12000},"deposit":{"type":"number","example":24000},"area":{"type":"string","example":"Malviya Nagar"},"city":{"type":"string","example":"Jaipur"},"images":{"type":"array","items":{"type":"string"},"example":["https://example.com/img1.jpg"]},"amenities":{"type":"array","items":{"type":"string"},"example":["WiFi","Parking","AC"]},"latitude":{"type":"number","format":"double","example":26.9124,"description":"Property latitude for map display (optional)"},"longitude":{"type":"number","format":"double","example":75.7873,"description":"Property longitude for map display (optional)"},"ownerId":{"type":"string","description":"Required when a listing partner lists on behalf of an owner","example":"665f1a2b3c4d5e6f7a8b9c0d"}}},"BookAppointmentRequest":{"type":"object","required":["propertyId","date","time"],"properties":{"propertyId":{"type":"string","example":"665f1a2b3c4d5e6f7a8b9c0d"},"date":{"type":"string","format":"date","example":"2026-03-15"},"time":{"type":"string","example":"10:00 AM"}}},"WithdrawRequest":{"type":"object","required":["amount"],"properties":{"amount":{"type":"number","example":50}}},"User":{"type":"object","properties":{"_id":{"type":"string","example":"665f1a2b3c4d5e6f7a8b9c0d"},"name":{"type":"string","example":"Sanskar Sharma"},"email":{"type":"string","example":"sanskar@example.com"},"phone":{"type":"string","example":"9876543210"},"role":{"type":"string","enum":["customer","listing_partner","owner"]},"wallet":{"type":"number","example":0},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Property":{"type":"object","properties":{"_id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"rent":{"type":"number"},"deposit":{"type":"number"},"area":{"type":"string"},"city":{"type":"string"},"images":{"type":"array","items":{"type":"string"}},"amenities":{"type":"array","items":{"type":"string"}},"ownerId":{"$ref":"#/components/schemas/UserSummary"},"listingPartnerId":{"$ref":"#/components/schemas/UserSummary"},"latitude":{"type":"number","format":"double","example":19.0176,"nullable":true},"longitude":{"type":"number","format":"double","example":72.8479,"nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Appointment":{"type":"object","properties":{"_id":{"type":"string"},"propertyId":{"type":"string"},"customerId":{"type":"string"},"ownerId":{"type":"string"},"date":{"type":"string","format":"date-time"},"time":{"type":"string"},"status":{"type":"string","enum":["pending","accepted","rejected"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WalletTransaction":{"type":"object","properties":{"_id":{"type":"string"},"listingPartnerId":{"type":"string"},"amount":{"type":"number"},"type":{"type":"string","enum":["credit","debit"]},"reason":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"UserSummary":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"}}},"Pagination":{"type":"object","properties":{"total":{"type":"integer","example":42},"page":{"type":"integer","example":1},"limit":{"type":"integer","example":10},"totalPages":{"type":"integer","example":5}}},"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"statusCode":{"type":"integer"},"message":{"type":"string"},"data":{"type":"object"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"statusCode":{"type":"integer"},"message":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}},"tags":[{"name":"Auth","description":"Authentication & registration"},{"name":"Properties","description":"Property listings (CRUD, search, filters)"},{"name":"Appointments","description":"Booking & managing property visits"},{"name":"Wallet","description":"Listing Partner wallet & transactions"}],"paths":{"/auth/signup":{"post":{"summary":"Register a new user","tags":["Auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}}},"responses":{"201":{"description":"User registered successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"token":{"type":"string","example":"eyJhbGciOiJIUzI1NiIs..."}}}}}]}}}},"409":{"description":"Email already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/signup-otp":{"post":{"summary":"Register a new user via OTP","tags":["Auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","phone","otp"],"properties":{"name":{"type":"string","example":"John Doe"},"phone":{"type":"string","example":"9876543210"},"otp":{"type":"string","example":"123456"},"role":{"type":"string","enum":["customer","listing_partner","owner"]},"referralCode":{"type":"string"}}}}}},"responses":{"201":{"description":"User registered successfully via OTP"},"409":{"description":"Phone number already exists"},"422":{"description":"Validation error"}}}},"/auth/login":{"post":{"summary":"Authenticate user and receive JWT","tags":["Auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"token":{"type":"string"}}}}}]}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/send-otp":{"post":{"summary":"Send OTP to phone number (demo mode)","tags":["Auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["phone"],"properties":{"phone":{"type":"string","example":"9876543210"}}}}}},"responses":{"200":{"description":"OTP sent successfully"},"400":{"description":"Validation error"}}}},"/auth/verify-otp":{"post":{"summary":"Verify OTP and login","tags":["Auth"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["phone","otp"],"properties":{"phone":{"type":"string","example":"9876543210"},"otp":{"type":"string","example":"123456"}}}}}},"responses":{"200":{"description":"OTP verified, login successful"},"401":{"description":"Invalid OTP"},"404":{"description":"User not found"}}}},"/auth/me":{"get":{"summary":"Get the currently authenticated user's profile","tags":["Auth"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"User profile fetched","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"}}}}}]}}}},"401":{"description":"Unauthorized – missing or invalid token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/properties":{"get":{"summary":"Browse properties with filters and pagination","tags":["Properties"],"parameters":[{"in":"query","name":"area","schema":{"type":"string"},"description":"Filter by area / locality (case-insensitive partial match)"},{"in":"query","name":"city","schema":{"type":"string"},"description":"Filter by city (case-insensitive partial match)"},{"in":"query","name":"minRent","schema":{"type":"number"},"description":"Minimum rent filter"},{"in":"query","name":"maxRent","schema":{"type":"number"},"description":"Maximum rent filter"},{"in":"query","name":"amenities","schema":{"type":"string"},"description":"Comma-separated amenities (match any)","example":"WiFi,Parking"},{"in":"query","name":"page","schema":{"type":"integer","default":1},"description":"Page number"},{"in":"query","name":"limit","schema":{"type":"integer","default":10},"description":"Items per page (max 50)"},{"in":"query","name":"sort","schema":{"type":"string","default":"-createdAt"},"description":"Sort field (prefix with - for descending)"}],"responses":{"200":{"description":"Properties fetched successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"properties":{"type":"array","items":{"$ref":"#/components/schemas/Property"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}]}}}}}},"post":{"summary":"Create a new property listing","description":"**Listing partners** and **Owners** can create listings.\n- Owners are automatically set as the property owner.\n- Listing partners earn wallet coins on successful upload.\n","tags":["Properties"],"security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePropertyRequest"}}}},"responses":{"201":{"description":"Property created successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"property":{"$ref":"#/components/schemas/Property"}}}}}]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden – only listing partners and owners"},"422":{"description":"Validation error"}}}},"/properties/my":{"get":{"summary":"Get properties listed by the current user","tags":["Properties"],"security":[{"BearerAuth":[]}],"parameters":[{"in":"query","name":"page","schema":{"type":"integer","default":1}},{"in":"query","name":"limit","schema":{"type":"integer","default":10}},{"in":"query","name":"sort","schema":{"type":"string","default":"-createdAt"}}],"responses":{"200":{"description":"Your properties fetched","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"properties":{"type":"array","items":{"$ref":"#/components/schemas/Property"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden – only listing partners and owners"}}}},"/properties/{id}":{"get":{"summary":"Get a single property by ID","tags":["Properties"],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Property ID (MongoDB ObjectId)"}],"responses":{"200":{"description":"Property details fetched","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"property":{"$ref":"#/components/schemas/Property"}}}}}]}}}},"404":{"description":"Property not found"}}}},"/wallet":{"get":{"summary":"Get listing partner's wallet balance and transaction history","tags":["Wallet"],"security":[{"BearerAuth":[]}],"parameters":[{"in":"query","name":"page","schema":{"type":"integer","default":1}},{"in":"query","name":"limit","schema":{"type":"integer","default":20}}],"responses":{"200":{"description":"Wallet details fetched","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"balance":{"type":"number","example":120},"transactions":{"type":"array","items":{"$ref":"#/components/schemas/WalletTransaction"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden – listing partners only"}}}},"/wallet/withdraw":{"post":{"summary":"Withdraw coins from listing partner's wallet","description":"Deducts the specified amount from the listing partner's wallet.\nThe withdrawal is atomic – concurrent requests are handled safely.\n","tags":["Wallet"],"security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawRequest"}}}},"responses":{"200":{"description":"Withdrawal successful","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"data":{"type":"object","properties":{"newBalance":{"type":"number","example":70},"transaction":{"$ref":"#/components/schemas/WalletTransaction"}}}}}]}}}},"400":{"description":"Insufficient balance or invalid amount"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden – listing partners only"},"422":{"description":"Validation error"}}}}}}