Skip to main content

Overview

The getZones endpoint retrieves all parking zones from Firestore, ordered by the order field. If no zones exist, it returns a default “General” zone.

Endpoint

GET /get-zones

Authentication

CORS-enabled endpoint with wildcard origin (*). No authentication required for read access.

Request

No parameters required. This is a simple GET request.

Response

zones
array
Array of zone objects sorted by order field (ascending)
zones[].id
string
Unique zone identifier (e.g., “zone_1764307623391”)
zones[].name
string
Display name of the zone (e.g., “Federico Froebel”)
zones[].order
integer
Display order for sorting (lower numbers appear first)
zones[].desc
string
Description of the zone
zones[].color
string
Color code for UI display (e.g., “blue”, “green”)
zones[].created_at
timestamp
Firestore timestamp of zone creation
zones[].updated_at
timestamp
Firestore timestamp of last update

Success Response

  • 200 OK - Returns array of zones
  • 204 No Content - OPTIONS preflight response

Error Response

  • 500 Internal Server Error - Database or server error

Default Zone Behavior

If no zones exist in the database, the endpoint returns a default zone:
[
  {
    "id": "General",
    "name": "General",
    "order": 1,
    "desc": "Zona general por defecto",
    "color": "blue",
    "created_at": "2026-03-05T10:00:00.000Z",
    "updated_at": "2026-03-05T10:00:00.000Z"
  }
]
This ensures the frontend always has at least one zone to work with.

Code Example

curl -X GET https://YOUR_REGION-YOUR_PROJECT.cloudfunctions.net/get-zones

Response Example

[
  {
    "id": "zone_1764307623391",
    "name": "Federico Froebel",
    "order": 1,
    "desc": "Outdoor parking area on Federico Froebel street with 20 spots (A-01 to A-20)",
    "color": "blue",
    "created_at": {
      "_seconds": 1764307623,
      "_nanoseconds": 391000000
    },
    "updated_at": {
      "_seconds": 1764307623,
      "_nanoseconds": 391000000
    }
  },
  {
    "id": "zone_1764306251630",
    "name": "Interior DUOC",
    "order": 2,
    "desc": "Indoor parking inside DUOC building with 16 spots (I-01 to I-16)",
    "color": "green",
    "created_at": {
      "_seconds": 1764306251,
      "_nanoseconds": 630000000
    },
    "updated_at": {
      "_seconds": 1764306251,
      "_nanoseconds": 630000000
    }
  }
]

Usage Patterns

Populate Zone Dropdown

const zones = await fetch('/get-zones').then(r => r.json());

const dropdown = document.getElementById('zone-select');
zones.forEach(zone => {
  const option = document.createElement('option');
  option.value = zone.id;
  option.textContent = zone.name;
  dropdown.appendChild(option);
});

Display Zone Statistics

const [zones, spots] = await Promise.all([
  fetch('/get-zones').then(r => r.json()),
  fetch('/get-parking-status').then(r => r.json())
]);

zones.forEach(zone => {
  const zoneSpots = spots.filter(s => s.zone_id === zone.id);
  const available = zoneSpots.filter(s => s.status === 1).length;
  
  console.log(`${zone.name}: ${available}/${zoneSpots.length} available`);
});

Color-Coded Map Markers

const zones = await fetch('/get-zones').then(r => r.json());
const zoneColors = Object.fromEntries(
  zones.map(z => [z.id, z.color])
);

const spots = await fetch('/get-parking-status').then(r => r.json());

spots.forEach(spot => {
  const color = zoneColors[spot.zone_id] || 'gray';
  addMapMarker(spot.lat, spot.lng, color);
});

Sorting Behavior

Zones are returned sorted by the order field in ascending order:
  • order: 1 appears first
  • order: 2 appears second
  • order: 999 appears last (default for new zones)
This allows administrators to control the display order in dropdowns and UI lists.

Firestore Query

The endpoint uses an indexed query:
firestore
  .collection('parking_zones')
  .orderBy('order', 'asc')
  .get()
Ensure you have a Firestore index on the order field for optimal performance:
Collection: parking_zones
Field: order
Type: Ascending

Caching Strategy

Zones change infrequently, making them ideal for caching:
let cachedZones = null;
let cacheTime = null;
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes

async function getZones() {
  const now = Date.now();
  
  if (cachedZones && (now - cacheTime) < CACHE_DURATION) {
    return cachedZones;
  }
  
  const zones = await fetch('/get-zones').then(r => r.json());
  cachedZones = zones;
  cacheTime = now;
  
  return zones;
}

Build docs developers (and LLMs) love