Skip to main content

Overview

The releaseParkingSpot endpoint cancels an active reservation on a parking spot, returning it to available status. It uses Firestore transactions to ensure safe concurrent operations.

Endpoint

POST /release-parking-spot

Authentication

CORS-enabled endpoint. Should be protected with user authentication in production to verify the user owns the reservation.

Request Body

spot_id
string
required
The unique identifier of the reserved parking spot to release (e.g., “A-01”, “I-16”)

Response

success
boolean
Indicates whether the release was successful
error
string
Error message (only present on failure)

Success Response

  • 200 OK - Reservation cancelled successfully

Error Responses

  • 400 Bad Request - Missing required parameter spot_id
  • 405 Method Not Allowed - Request method is not POST
  • 409 Conflict - Spot cannot be released due to:
    • Spot does not exist
    • Spot does not have an active reservation (status is not 2)

Transaction Logic

The function uses Firestore transactions to ensure atomic operations:
  1. Read: Fetch current spot data within transaction
  2. Validate: Check spot exists and status is 2 (Reserved)
  3. Write: Update spot to status 1 (Available) and delete reservation metadata
  4. Commit: Transaction commits only if no conflicts occurred
This prevents race conditions where a spot might be released multiple times or changed by another operation.

Code Example

curl -X POST https://YOUR_REGION-YOUR_PROJECT.cloudfunctions.net/release-parking-spot \
  -H "Content-Type: application/json" \
  -d '{
    "spot_id": "A-05"
  }'

Success Response Example

{
  "success": true
}

Error Response Examples

Missing Parameter

{
  "error": "Falta spot_id"
}

No Active Reservation

{
  "error": "El puesto no tiene una reserva activa para cancelar."
}

Spot Does Not Exist

{
  "error": "El puesto no existe"
}

Firestore Data Structure

After successful release, the spot document is updated:
{
  status: 1, // Changed from 2 to 1
  last_changed: FieldValue.serverTimestamp(),
  // reservation_data field is deleted using FieldValue.delete()
}

Use Cases

User Cancellation

User decides to cancel their reservation before arriving:
// User clicks "Cancel Reservation" button
await fetch('/release-parking-spot', {
  method: 'POST',
  body: JSON.stringify({ spot_id: userReservation.spot_id })
});

Administrative Release

Admin manually releases a stuck reservation:
// Admin dashboard force-release
await fetch('/release-parking-spot', {
  method: 'POST',
  body: JSON.stringify({ spot_id: 'A-05' })
});

Automatic Expiration

Note: Expired reservations are automatically cleared by the Get Parking Status endpoint, so manual release is not needed for expired reservations.

Status Transition Flow

Status 1 (Available)
    ↓ [reserve-parking-spot]
Status 2 (Reserved)
    ↓ [release-parking-spot]  ← YOU ARE HERE
Status 1 (Available)

Security Considerations

In a production environment, you should:
  1. Verify Ownership: Check that the requesting user owns the reservation
  2. Rate Limiting: Prevent abuse of reservation/release cycles
  3. Audit Logging: Log all release operations for accountability
  4. Authorization: Use Firebase Auth or similar to validate user identity
// Example with Firebase Auth token
const response = await fetch('/release-parking-spot', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${userIdToken}`
  },
  body: JSON.stringify({ spot_id: 'A-05' })
});

Build docs developers (and LLMs) love