# Vehicle Search Operations Vehicle search endpoints allow you to find available car rental options based on location, dates, and other criteria. The search system provides comprehensive vehicle listings with pricing and the ability to retrieve additional products and services. ## Search Results Ranking Logic The vehicle search system utilizes an advanced location-based algorithm to optimize user experience. The system performs dynamic radius scanning around specified coordinates to present the most suitable vehicle options. Search results are primarily ranked by proximity - vehicles at locations closest to the user's specified pickup/drop-off points appear at the top of the list. The algorithm employs intelligent filtering to prevent duplicate listings of the same vehicle model from different suppliers. This ensures users see a clean, organized list when comparing vehicles with similar features. Ranking criteria include not only distance priority but also factors such as price-performance balance, supplier reliability, and vehicle availability. Optimized approaches for both domestic and international searches ensure fast response times while delivering comprehensive results. The system maintains a balance between performance and user experience, efficiently listing the most relevant vehicle options. ## Vehicle Search Search for available vehicles for specified locations and dates. This endpoint returns comprehensive results including pricing, vehicle details, and availability information. ### Endpoint ``` POST /search/point ``` ### Authentication This endpoint requires authentication. Include your JWT access token in the Authorization header: ``` Authorization: Bearer YOUR_ACCESS_TOKEN ``` ### Currency Support You can specify the currency for price responses using the `X-Currency` header. If not provided, Turkish Lira (TRY) will be used as the default currency. **Supported Currencies:** - `TRY` - Turkish Lira (default) - `USD` - US Dollar - `EUR` - Euro - `GBP` - Great Britain Pound **Example with currency header:** ``` X-Currency: USD ``` ### Timezone Within the scope of the car rental service, the timezone information of the searched location is also transmitted. Therefore, the timezone of the searched location must be stored in your system, and the `/search/point` request should be sent based on this information. Otherwise, if the timezone information of the relevant location is not provided to us, the system defaults to UTC ( Coordinated Universal Time). This may cause discrepancies in the vehicle pick-up and drop-off times. ### Request Body | Field | Type | Required | Description | | --- | --- | --- | --- | | `checkInDateTime` | datetime | Yes | Pick-up date and time (RFC 3339 format with timezone support) | | `checkOutDateTime` | datetime | Yes | Drop-off date and time (RFC 3339 format with timezone support) | | `age` | string | Yes | Driver age category (18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30+) | | `country` | string | Yes | ISO country code (2 characters, e.g., "TR", "US") | | `paymentType` | string | Yes | Payment type: `creditCard` or `limit` | | `checkInLocation` | object | Yes | Pick-up location coordinates | | `checkInLocation.lat` | number | Yes | Latitude coordinate (-90 to 90) | | `checkInLocation.lon` | number | Yes | Longitude coordinate (-180 to 180) | | `checkOutLocation` | object | Yes | Drop-off location coordinates | | `checkOutLocation.lat` | number | Yes | Latitude coordinate (-90 to 90) | | `checkOutLocation.lon` | number | Yes | Longitude coordinate (-180 to 180) | | `commission` | object | No | Commission details for agencies | | `commission.type` | string | No | Commission type: `percentage` or `fixed` | | `commission.percentage` | number | No | Commission percentage (0-100, required if type is percentage) | | `commission.fixed` | object | No | Fixed commission amount (required if type is fixed) | | `campaignCode` | string | No | Optional campaign code for discounts | | `fullCredit` | boolean | No | Whether to use full credit payment | ### Example Request ```bash curl -X POST https://api.pro.yolcu360.com/api/v1/search/point \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "X-Currency: USD" \ -d '{ "checkInDateTime": "2024-08-01T10:00:00+03:00", "checkOutDateTime": "2024-08-08T10:00:00+03:00", "age": "25", "country": "TR", "paymentType": "creditCard", "checkInLocation": { "lat": 41.0082, "lon": 28.9784 }, "checkOutLocation": { "lat": 41.0082, "lon": 28.9784 }, "commission": { "type": "percentage", "percentage": 5.0 }, "fullCredit": false }' ``` ### Response **Success Response (200 OK):** ```json { "count": 15, "results": [ { "code": "ECAR123", "searchID": "search_1234567890", "applicableForFullCredit": true, "appointment": { "checkInDateTime": "2024-08-01T10:00:00+03:00", "checkInOffice": { "id": 1, "location": { "name": "Sabiha Gokcen Airport", "city": "Istanbul" } }, "checkOutDateTime": "2024-08-08T10:00:00+03:00", "checkOutOffice": { "id": 1, "location": { "name": "Sabiha Gokcen Airport", "city": "Istanbul" } } }, "brand": { "id": 1, "name": "Toyota" }, "model": { "id": 1, "name": "Corolla" }, "class": { "id": 1, "name": "Economy" c }, "customClassName": "economy", "fuel": { "id": 3, "name": "Petrol" }, "fuelPolicy": { "id": 1, "name": "F2F" }, "transmission": { "id": 1, "name": "Automatic" }, "isFindeksRequired": false, "integrationCode": "FNDX12345", "seatCount": 5, "rentalDurationInDays": 7, "images": [ { "url": "https://example.com/car-image.jpg", "alt": "Toyota Corolla" } ], "imageURL": "https://example.com/car-image.jpg", "pricing": { "net": { "amount": 50000, "currency": "TRY" }, "commission": { "amount": 5000, "currency": "TRY" }, "fee": { "amount": 55000, "currency": "TRY" }, "total": { "amount": 55000, "currency": "TRY" }, "paymentTotal": { "amount": 55000, "currency": "TRY" } }, "vendor": { "id": 1, "displayName": "Sixt", "name": "Sixt Rent a Car" }, "rules": [ { "name": "Minimum Driver Age", "type": "minDriverAge", "minDriverAge": 21 }, { "name": "Deposit", "type": "deposit", "deposit": { "amount": 150000, "currency": "TRY" } } ], "rentalConditions": { "productInformationPDF": "https://static.yolcu360.com/thumbnails", "termsConditionPDF": "https://static.yolcu360.com/thumbnails" } } ] } ``` ### Response Fields | Field | Type | Description | | --- | --- | --- | | `count` | integer | Total number of available vehicles | | `results` | array | Array of available vehicle objects | | `results[].code` | string | Unique vehicle product code | | `results[].searchID` | string | Search session identifier | | `results[].applicableForFullCredit` | boolean | Whether vehicle can be paid with full credit | | `results[].pricing` | object | Comprehensive pricing information | | `results[].pricing.total` | object | Total price including all fees | | `results[].pricing.net` | object | Net price after discounts | | `results[].pricing.commission` | object | Commission amount | | `results[].brand` | object | Vehicle brand information | | `results[].model` | object | Vehicle model information | | `results[].class` | object | Vehicle class (economy, compact, etc.) | | `results[].transmission` | object | Transmission type | | `results[].fuel` | object | Fuel type | | `results[].seatCount` | integer | Number of seats | | `results[].isFindeksRequired` | boolean | Whether Findeks credit check is required | | `results[].integrationCode` | string | Integration code associated with the car for credit checks | | `results[].vendor` | object | Car rental company information | | `results[].images` | array | ⚠️ **Deprecated**: Array of car images. Use `imageURL` instead. | | `results[].imageURL` | string | URL of the car image | ## Findeks Credit Check Integration Some vehicles in search results may require Findeks credit verification before booking. When the `isFindeksRequired` field is `true` in a vehicle result, you must complete the Findeks verification process before creating an order for that vehicle. ### When Findeks is Required - The `isFindeksRequired` field in the search response will be `true` - This indicates that the customer must pass a credit eligibility check - The verification must be completed before the booking can proceed ### Integration Steps When `isFindeksRequired: true`: 1. **Initiate Findeks Check**: Use the `/findeks/check` endpoint to verify initial credit eligibility 2. **Handle Unknown Status**: If status is "Unknown", proceed with phone verification and report generation 3. **Complete Verification**: Follow the complete Findeks workflow as needed 4. **Proceed with Booking**: Only create orders after successful Findeks verification ### Example Response with Findeks Required ```json { "count": 1, "results": [ { "code": "PREMIUM123", "searchID": "search_1234567890", "isFindeksRequired": true, "integrationCode": "FNDX67890", "brand": { "id": 1, "name": "BMW" }, "model": { "id": 5, "name": "3 Series" }, "class": { "id": 3, "name": "Premium" } // ... other fields } ] } ``` For complete details on implementing Findeks verification, see the [Findeks Credit Eligibility](/endpoints/findeks) documentation. ## Get Vehicle Extra Products Retrieve available extra products (insurance, GPS, child seats, etc.) for a specific vehicle from search results. ### Endpoint ``` GET /search/{searchID}/{code}/extra-products ``` ### Authentication This endpoint requires authentication. Include your JWT access token in the Authorization header. ### Path Parameters | Parameter | Type | Required | Description | | --- | --- | --- | --- | | `searchID` | string | Yes | Search ID from the vehicle search results | | `code` | string | Yes | Vehicle product code from search results | ### Example Request ```bash curl -X GET https://api.pro.yolcu360.com/api/v1/search/search_123456789/ECAR/extra-products \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ### Response **Success Response (200 OK):** ```json [ { "code": "GPS", "name": "GPS Navigation System", "type": "equipment", "searchID": "search_123456789", "min": 0, "max": 1, "campaign": { "id": "gps_discount", "name": "GPS Special Offer" }, "pricing": { "total": { "amount": 1500, "currency": "TRY" }, "net": { "amount": 1350, "currency": "TRY" }, "commission": { "amount": 75, "currency": "TRY" } } }, { "code": "CDW", "name": "Collision Damage Waiver", "type": "insurance", "searchID": "search_123456789", "min": 0, "max": 1, "pricing": { "total": { "amount": 3000, "currency": "TRY" }, "net": { "amount": 2700, "currency": "TRY" }, "commission": { "amount": 150, "currency": "TRY" } } }, { "code": "CHILD_SEAT", "name": "Child Safety Seat", "type": "equipment", "searchID": "search_123456789", "min": 0, "max": 3, "pricing": { "total": { "amount": 2000, "currency": "TRY" }, "net": { "amount": 1800, "currency": "TRY" }, "commission": { "amount": 100, "currency": "TRY" } } }, { "code": "EXTRA_KM", "name": "Extra Kilometers", "type": "range", "searchID": "search_123456789", "min": 0, "max": 5, "extraRange": { "amount": 100, "unit": "km" }, "pricing": { "total": { "amount": 500, "currency": "TRY" }, "net": { "amount": 450, "currency": "TRY" }, "commission": { "amount": 25, "currency": "TRY" } } }, { "code": "THEFT_PROTECTION", "name": "Theft Protection Insurance", "type": "insurance", "searchID": "search_123456789", "min": 0, "max": 1, "insurance": { "code": "TP", "name": "Theft Protection" }, "pricing": { "total": { "amount": 3500, "currency": "TRY" }, "net": { "amount": 3150, "currency": "TRY" }, "commission": { "amount": 175, "currency": "TRY" } } } ] ``` ### Extra Product Fields Extra products use a discriminated union based on the `type` field to provide type-specific information: #### Base Extra Product Fields (Common to all types) | Field | Type | Description | | --- | --- | --- | | `code` | string | Unique product code | | `name` | string | Product display name | | `type` | string | Product type discriminator | | `searchID` | string | Associated search session ID | | `min` | integer | Minimum quantity that can be selected | | `max` | integer | Maximum quantity that can be selected | | `pricing` | object | Product pricing information | | `campaign` | object | Associated campaign or discount | #### Range Extra Product (type: "range") Additional fields when `type` is `"range"`: | Field | Type | Description | | --- | --- | --- | | `extraRange` | object | Additional range information (amount and unit) | #### Insurance Extra Product (type: "insurance") Additional fields when `type` is `"insurance"`: | Field | Type | Description | | --- | --- | --- | | `insurance` | object | Insurance product details (code and name) | ## Search Best Practices ### Location Coordinates - **Accuracy**: Provide precise coordinates for better results - **Validation**: Ensure coordinates are within valid ranges - **Proximity**: Results are ordered by distance from provided coordinates ### Date and Time Selection - **Future Dates**: Pick-up time must be in the future - **Duration**: Minimum rental period is typically 1 day - **Time Zones**: Full timezone support available. You can use: - UTC format: `2024-12-25T10:00:00Z` - Timezone offset: `2024-12-25T13:00:00+03:00` (Istanbul time) - Local timezone: `2024-12-25T10:00:00-05:00` (New York time) - **Business Hours**: Consider rental location operating hours in local timezone ### Payment Types - **Credit Card**: Standard payment method, supports installments - **Credit Limit**: Available for agencies with approved credit limits - **Mixed Payments**: Some vehicles may support multiple payment methods ### Performance Optimization - **Caching**: Search results are cached for 15 minutes - **Pagination**: Use appropriate filters to limit result sets - **Parallel Requests**: Retrieve extra products in parallel with search ### Error Handling **Common Error Responses:** - `400 Bad Request`: Invalid search parameters - `401 Unauthorized`: Authentication required or token expired - `404 Not Found`: Search ID or product code not found - `500 Internal Server Error`: Service temporarily unavailable **Example Error Response:** ```json { "code": 1001, "description": "Invalid request parameters", "details": { "field": "checkInDateTime", "message": "Must be a future date" } } ``` ## Search Workflow ### Typical Integration Flow 1. **Location Search**: Use `/locations` to find pickup/dropoff locations 2. **Vehicle Search**: Call `/search/point` with location coordinates and dates 3. **Extra Products**: For each vehicle, optionally call `/search/{searchID}/{code}/extra-products` 4. **Order Creation**: Use search results to create an order via `/order` ### Code Example: Complete Search Flow ```javascript // Step 1: Search for vehicles const searchResponse = await fetch('/api/v1/search/point', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessToken}`, 'X-Currency': 'USD' }, body: JSON.stringify({ checkInDateTime: "2024-08-01T10:00:00+03:00", checkOutDateTime: "2024-08-08T10:00:00+03:00", age: '25', country: 'TR', paymentType: 'creditCard', checkInLocation: {lat: 41.0082, lon: 28.9784}, checkOutLocation: {lat: 41.0082, lon: 28.9784} }) }); const searchData = await searchResponse.json(); console.log(`Found ${searchData.count} vehicles`); // Step 2: Get extra products for the first vehicle if (searchData.results.length > 0) { const vehicle = searchData.results[0]; const extrasResponse = await fetch( `/api/v1/search/${vehicle.searchID}/${vehicle.code}`, { headers: { 'Authorization': `Bearer ${accessToken}` } } ); const extras = await extrasResponse.json(); console.log(`Found ${extras.length} extra products`); } ``` ## Rate Limiting Search endpoints are subject to rate limiting: - **Search endpoint**: Maximum 20 requests per minute per user - **Extra products**: Maximum 100 requests per minute per user Implement appropriate retry logic with exponential backoff for rate limit errors.