Location endpoints provide comprehensive location search and geocoding services for car rental operations. These endpoints enable users to find pickup and drop-off locations with autocomplete functionality and detailed location information.
Search for car rental locations using text queries. This endpoint provides autocomplete functionality, returning location predictions that match the search query for an enhanced user experience.
GET /locations?query={query}This endpoint requires authentication. Include your JWT access token in the Authorization header:
Authorization: Bearer YOUR_ACCESS_TOKEN| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search query text (minimum 2 characters) |
curl -X GET "https://api.pro.yolcu360.com/api/v1/locations?query=istanbul" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Success Response (200 OK):
[
{
"placeId": "ChIJOwg_06VPwokRYv534QaPC8g",
"description": "Istanbul, Turkey",
"mainText": "Istanbul",
"secondaryText": "Turkey",
"types": [
"locality",
"political"
]
},
{
"placeId": "ChIJB3uraJq9yhQRvHRAVQ6KFT4",
"description": "Istanbul Airport (IST), Tayakadın, Arnavutköy/İstanbul, Turkey",
"mainText": "Istanbul Airport (IST)",
"secondaryText": "Tayakadın, Arnavutköy/İstanbul, Turkey",
"types": [
"airport",
"establishment",
"point_of_interest"
]
},
{
"placeId": "ChIJ8dYSQGq8yhQRy_TlKn0Qmgg",
"description": "Sabiha Gökçen International Airport (SAW), Pendik/İstanbul, Turkey",
"mainText": "Sabiha Gökçen International Airport (SAW)",
"secondaryText": "Pendik/İstanbul, Turkey",
"types": [
"airport",
"establishment",
"point_of_interest"
]
},
{
"placeId": "ChIJh8tEqiq9yhQR4Es7hO_KWw8",
"description": "Istanbul Atatürk Airport (ISL), Yeşilköy, Bakırköy/İstanbul, Turkey",
"mainText": "Istanbul Atatürk Airport (ISL)",
"secondaryText": "Yeşilköy, Bakırköy/İstanbul, Turkey",
"types": [
"airport",
"establishment",
"point_of_interest"
]
},
{
"placeId": "ChIJu46S-ZNjyhQROG9z8KiBUUs",
"description": "Sultanahmet, Fatih/İstanbul, Turkey",
"mainText": "Sultanahmet",
"secondaryText": "Fatih/İstanbul, Turkey",
"types": [
"neighborhood",
"political"
]
}
]| Field | Type | Description |
|---|---|---|
placeId | string | Unique identifier for the location |
description | string | Full description of the location |
mainText | string | Primary location text (typically the name) |
secondaryText | string | Secondary descriptive text (typically the address) |
types | array | Location types (e.g., airport, city, neighborhood) |
| Type | Description |
|---|---|
airport | Airport locations |
locality | Cities or towns |
neighborhood | Districts or neighborhoods |
establishment | Business establishments |
point_of_interest | Notable landmarks or points of interest |
political | Administrative boundaries |
Retrieve detailed information about a specific location using its place ID. This endpoint provides comprehensive location data including coordinates, timezone, and administrative information.
GET /locations/{placeId}This endpoint requires authentication. Include your JWT access token in the Authorization header.
| Parameter | Type | Required | Description |
|---|---|---|---|
placeId | string | Yes | Unique place identifier from location search |
curl -X GET https://api.pro.yolcu360.com/api/v1/locations/ChIJOwg_06VPwokRYv534QaPC8g \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"Success Response (200 OK):
{
"placeId": "ChIJOwg_06VPwokRYv534QaPC8g",
"name": "Istanbul",
"city": "Istanbul",
"countryCode": "TR",
"timezone": "Europe/Istanbul",
"point": {
"lat": 41.0082,
"lon": 28.9784
}
}| Field | Type | Description |
|---|---|---|
placeId | string | Unique place identifier |
name | string | Location name |
city | string | City name |
countryCode | string | ISO country code (2 characters) |
timezone | string | IANA timezone identifier |
point | object | Geographic coordinates |
point.lat | number | Latitude coordinate |
point.lon | number | Longitude coordinate |
- Minimum Length: Queries must be at least 2 characters long
- Language Support: The service supports multiple languages including Turkish and English
- Fuzzy Matching: The search supports partial and fuzzy matching for better user experience
- Special Characters: Handle special characters and diacritics appropriately
- Debouncing: Implement debouncing to avoid excessive API calls during typing
- Caching: Cache recent search results to improve performance
- Progressive Enhancement: Show results as the user types with progressive refinement
- Keyboard Navigation: Support keyboard navigation for accessibility
- Place ID Usage: Always use place IDs for location identification, not coordinates
- Validation: Validate selected locations before proceeding to vehicle search
- Fallback: Provide fallback options for locations that may not support car rentals
- Favorites: Consider implementing location favorites for frequent users
class LocationAutocomplete {
constructor(inputElement, apiToken) {
this.input = inputElement;
this.token = apiToken;
this.debounceTimer = null;
this.cache = new Map();
this.setupEventListeners();
}
setupEventListeners() {
this.input.addEventListener('input', (e) => {
this.handleInput(e.target.value);
});
}
handleInput(query) {
// Clear previous timer
clearTimeout(this.debounceTimer);
// Validate minimum length
if (query.length < 2) {
this.clearResults();
return;
}
// Debounce the search
this.debounceTimer = setTimeout(() => {
this.searchLocations(query);
}, 300);
}
async searchLocations(query) {
// Check cache first
if (this.cache.has(query)) {
this.displayResults(this.cache.get(query));
return;
}
try {
const response = await fetch(
`/api/v1/locations?query=${encodeURIComponent(query)}`,
{
headers: {
'Authorization': `Bearer ${this.token}`
}
}
);
if (!response.ok) {
throw new Error('Search failed');
}
const locations = await response.json();
// Cache the results
this.cache.set(query, locations);
// Display results
this.displayResults(locations);
} catch (error) {
console.error('Location search error:', error);
this.showError('Failed to search locations');
}
}
displayResults(locations) {
// Implementation for displaying search results
const resultsContainer = document.getElementById('location-results');
resultsContainer.innerHTML = '';
locations.forEach(location => {
const item = document.createElement('div');
item.className = 'location-item';
item.innerHTML = `
<div class="main-text">${location.mainText}</div>
<div class="secondary-text">${location.secondaryText}</div>
`;
item.addEventListener('click', () => {
this.selectLocation(location);
});
resultsContainer.appendChild(item);
});
}
async selectLocation(location) {
try {
// Get detailed location information
const response = await fetch(
`/api/v1/locations/${location.placeId}`,
{
headers: {
'Authorization': `Bearer ${this.token}`
}
}
);
if (!response.ok) {
throw new Error('Failed to get location details');
}
const locationDetails = await response.json();
// Update input and trigger selection event
this.input.value = location.description;
this.input.dispatchEvent(new CustomEvent('locationSelected', {
detail: locationDetails
}));
this.clearResults();
} catch (error) {
console.error('Location selection error:', error);
this.showError('Failed to select location');
}
}
clearResults() {
const resultsContainer = document.getElementById('location-results');
if (resultsContainer) {
resultsContainer.innerHTML = '';
}
}
showError(message) {
// Implementation for showing error messages
console.error(message);
}
}
// Usage
const pickupInput = document.getElementById('pickup-location');
const autocomplete = new LocationAutocomplete(pickupInput, accessToken);
pickupInput.addEventListener('locationSelected', (event) => {
const location = event.detail;
console.log('Selected location:', location);
// Store coordinates for vehicle search
window.pickupCoordinates = {
lat: location.point.lat,
lon: location.point.lon
};
});async function validateLocation(placeId) {
try {
const response = await fetch(`/api/v1/locations/${placeId}`, {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
if (!response.ok) {
if (response.status === 404) {
throw new Error('Location not found or not supported');
}
throw new Error('Location validation failed');
}
const location = await response.json();
// Validate that location has required fields
if (!location.point || !location.point.lat || !location.point.lon) {
throw new Error('Location does not have valid coordinates');
}
return location;
} catch (error) {
console.error('Location validation error:', error);
throw error;
}
}function calculateDistance(location1, location2) {
const R = 6371; // Earth's radius in kilometers
const dLat = (location2.lat - location1.lat) * Math.PI / 180;
const dLon = (location2.lon - location1.lon) * Math.PI / 180;
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(location1.lat * Math.PI / 180) * Math.cos(location2.lat * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c;
return distance; // Distance in kilometers
}
function validateLocationDistance(pickupLocation, dropoffLocation) {
const distance = calculateDistance(
pickupLocation.point,
dropoffLocation.point
);
// Warn if locations are very far apart (>500km)
if (distance > 500) {
return {
valid: true,
warning: `Pickup and drop-off locations are ${distance.toFixed(0)}km apart`
};
}
return {valid: true};
}400 Bad Request: Invalid query parameter or missing required fields401 Unauthorized: Authentication required or token expired404 Not Found: Place ID not found or location not supported429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Service temporarily unavailable
{
"code": 1001,
"description": "Invalid query parameter",
"details": {
"field": "query",
"message": "Query must be at least 2 characters long"
}
}- Graceful Degradation: Provide fallback options when location search fails
- User Feedback: Show clear error messages to users
- Retry Logic: Implement exponential backoff for temporary failures
- Validation: Validate user input before making API calls
- Search Results: Cache search results for identical queries
- Location Details: Cache detailed location information
- TTL: Use appropriate time-to-live values (suggested: 1 hour for search, 24 hours for details)
- Storage: Use browser localStorage or sessionStorage for client-side caching
Location endpoints are subject to rate limiting:
- Search endpoint: Maximum 60 requests per minute per user
- Details endpoint: Maximum 100 requests per minute per user
- Debouncing: Use 300ms debounce for search input
- Batch Requests: If possible, batch location detail requests
- Preloading: Preload popular locations for faster response
- CDN: Use CDN for static location data if available
- Keyboard Navigation: Support arrow keys for result navigation
- Screen Readers: Provide appropriate ARIA labels and descriptions
- Focus Management: Manage focus properly during location selection
- Voice Input: Support voice input for location search
- High Contrast: Ensure location results are visible in high contrast mode