Skip to main content

Cities

Retrieve list of available cities for customer registration and shipping addresses.

Get All Cities

GET /api/ecom/ciudad

Get complete list of available cities
Retrieve all cities available in the system for use in customer registration, shipping addresses, and location-based features.
This endpoint does not require authentication and can be accessed publicly to populate city dropdowns and location selectors.

Response

cities
array
Array of city objects

Example Request

curl -X GET https://api.example.com/api/ecom/ciudad

Example Response

200 OK
[
  {
    "ct_codigo": "UIO",
    "ct_nombre": "Quito",
    "ct_provincia": "Pichincha",
    "ct_pais": "Ecuador",
    "ct_activo": true
  },
  {
    "ct_codigo": "GYE",
    "ct_nombre": "Guayaquil",
    "ct_provincia": "Guayas",
    "ct_pais": "Ecuador",
    "ct_activo": true
  },
  {
    "ct_codigo": "CUE",
    "ct_nombre": "Cuenca",
    "ct_provincia": "Azuay",
    "ct_pais": "Ecuador",
    "ct_activo": true
  },
  {
    "ct_codigo": "AMB",
    "ct_nombre": "Ambato",
    "ct_provincia": "Tungurahua",
    "ct_pais": "Ecuador",
    "ct_activo": true
  },
  {
    "ct_codigo": "MCH",
    "ct_nombre": "Machala",
    "ct_provincia": "El Oro",
    "ct_pais": "Ecuador",
    "ct_activo": true
  }
]
200 OK - Empty List
[]

Use Cases

Customer Registration

When registering a new customer, the city code is required as part of the customer details:
// 1. Fetch available cities
const citiesResponse = await fetch('https://api.example.com/api/ecom/ciudad');
const cities = await citiesResponse.json();

// 2. User selects city from dropdown
const selectedCityCode = 'UIO'; // User selection

// 3. Include in registration
const registerResponse = await fetch('https://api.example.com/api/ecom/auth/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: '[email protected]',
    password: 'securePassword123',
    cli_ruc_ced: '1234567890',
    cliente: {
      cli_nombre: 'Juan Pérez',
      cli_telefono: '0987654321',
      cli_celular: '987654321',
      cli_direccion: 'Av. Principal 123',
      ct_codigo: selectedCityCode  // City code from cities list
    }
  })
});

Address Forms

Populate city selectors in address forms:
async function loadCities() {
  try {
    const response = await fetch('https://api.example.com/api/ecom/ciudad');
    const cities = await response.json();
    
    const select = document.getElementById('city-select');
    
    // Clear existing options
    select.innerHTML = '<option value="">Seleccione una ciudad</option>';
    
    // Add cities grouped by province
    const provinces = {};
    cities.forEach(city => {
      if (!provinces[city.ct_provincia]) {
        provinces[city.ct_provincia] = [];
      }
      provinces[city.ct_provincia].push(city);
    });
    
    // Create optgroups
    Object.keys(provinces).sort().forEach(province => {
      const optgroup = document.createElement('optgroup');
      optgroup.label = province;
      
      provinces[province].forEach(city => {
        const option = document.createElement('option');
        option.value = city.ct_codigo;
        option.textContent = city.ct_nombre;
        optgroup.appendChild(option);
      });
      
      select.appendChild(optgroup);
    });
    
  } catch (error) {
    console.error('Failed to load cities:', error);
  }
}

// Load on page load
loadCities();
Implement city search and filtering:
async function searchCities(query) {
  const response = await fetch('https://api.example.com/api/ecom/ciudad');
  const cities = await response.json();
  
  const searchTerm = query.toLowerCase();
  
  return cities.filter(city => 
    city.ct_nombre.toLowerCase().includes(searchTerm) ||
    city.ct_provincia.toLowerCase().includes(searchTerm) ||
    city.ct_codigo.toLowerCase().includes(searchTerm)
  );
}

// Usage
const results = await searchCities('qui');
// Returns cities matching 'qui' (e.g., Quito)

Data Structure

City Code (ct_codigo)

The city code is typically a 3-letter abbreviation:
  • UIO: Quito
  • GYE: Guayaquil
  • CUE: Cuenca
  • AMB: Ambato
  • MCH: Machala
City codes are used as foreign keys in customer records and should be validated against the cities list before submission.

Active Status (ct_activo)

Cities have an active flag to indicate if they’re available for selection:
  • true: City is active and can be selected
  • false: City is inactive (historical data only)
Inactive cities may still appear in the API response but should typically be filtered out in UI dropdowns. They’re kept for maintaining referential integrity with existing customer records.

Response Characteristics

Empty Response

If no cities are configured in the system, the endpoint returns an empty array:
[]
This is a valid response (200 OK) and should be handled gracefully in client applications.

Response Size

The cities list is typically small (dozens to hundreds of entries) and can be:
  • Cached client-side for performance
  • Loaded once on application startup
  • Refreshed periodically if cities change

No Pagination

Unlike other list endpoints, the cities endpoint returns all cities in a single response without pagination. This is intentional as:
  • The dataset is small
  • Cities are needed in full for dropdown population
  • Pagination would complicate UI implementation

Integration with Registration

The city code is used during customer registration:
POST /api/ecom/auth/register
{
  "email": "[email protected]",
  "password": "securePassword123",
  "cli_ruc_ced": "1234567890",
  "cliente": {
    "cli_nombre": "Juan Pérez",
    "cli_telefono": "0987654321",
    "cli_celular": "987654321",
    "cli_direccion": "Av. Principal 123",
    "ct_codigo": "UIO"  // <- City code from cities list
  }
}
Always validate that the ct_codigo provided during registration exists in the cities list returned by this endpoint. Using an invalid city code will cause registration to fail.

Best Practices

Client-Side Caching

Cache the cities list to reduce API calls:
class CityService {
  constructor() {
    this.cache = null;
    this.cacheTime = null;
    this.cacheDuration = 3600000; // 1 hour
  }
  
  async getCities() {
    const now = Date.now();
    
    // Return cached data if still valid
    if (this.cache && (now - this.cacheTime) < this.cacheDuration) {
      return this.cache;
    }
    
    // Fetch fresh data
    const response = await fetch('https://api.example.com/api/ecom/ciudad');
    this.cache = await response.json();
    this.cacheTime = now;
    
    return this.cache;
  }
  
  invalidateCache() {
    this.cache = null;
    this.cacheTime = null;
  }
}

const cityService = new CityService();
Group cities by province for better UX:
<select id="city-select">
  <option value="">Seleccione una ciudad</option>
  <optgroup label="Pichincha">
    <option value="UIO">Quito</option>
  </optgroup>
  <optgroup label="Guayas">
    <option value="GYE">Guayaquil</option>
  </optgroup>
  <optgroup label="Azuay">
    <option value="CUE">Cuenca</option>
  </optgroup>
</select>

Error Handling

Handle cases where cities cannot be loaded:
async function loadCitiesWithFallback() {
  try {
    const response = await fetch('https://api.example.com/api/ecom/ciudad');
    
    if (!response.ok) {
      throw new Error('Failed to fetch cities');
    }
    
    const cities = await response.json();
    
    if (cities.length === 0) {
      console.warn('No cities available');
      showMessage('No hay ciudades disponibles en este momento');
      return [];
    }
    
    return cities;
    
  } catch (error) {
    console.error('Error loading cities:', error);
    showMessage('Error al cargar las ciudades. Por favor, intente nuevamente.');
    return [];
  }
}

Error Responses

500 Internal Server Error
{
  "message": "Error message details"
}
The endpoint returns a 500 status code only in case of server errors. Empty city lists return 200 with an empty array.

Source Code Reference

Implementation details can be found in:
  • Routes: /src/routes/ecom.ciudad.routes.js:1-9
  • Controller: /src/controllers/ecom.ciudad.controller.js:6-25
  • Model: /src/models/ciudad.model.js
  • Database: E-Commerce database connection via /src/config/db_ecom.js

The cities data is used in conjunction with:
  • Customer Registration: POST /api/ecom/auth/register - requires ct_codigo in customer details
  • Customer Profile: GET /api/ecom/auth/me - returns customer’s city information
This endpoint provides reference data for location-based features across the e-commerce platform. The city codes are standardized and must match between registration, profile management, and shipping operations.

Build docs developers (and LLMs) love