API: Cancel Individual Block/Booked

Request

Cancel a specific seat request while keeping other seats in the same issue with a DELETE request:

POST /seat-booked-blocked-cancel

Headers:


Content-Type: application/json
Authorization: Bearer {your_access_token}
                

Request Body:


{
  "seat_inventory_id": 456,
  "trip_id": 1
}
                

Success Response (200 OK):


{
  "status": "success",
  "code": 200,
  "message": "Seat request cancelled successfully",
  "data": {
    "cancelled_seat_request_id": 123,
    "seat_inventory_id": 456,
    "trip_id": 789,
    "seat_info": {
      "seat_id": 101,
      "seat_number": "A1",
      "row_position": 1,
      "col_position": 1,
      "seat_type": "window"
    },
    "seat_status": "available",
    "request_status": "cancelled",
    "blocked_until": null,
    "user_id": 25,
    "cancelled_at": "2025-08-28T10:30:15.000000Z",

  }
}
                

Request Parameters:

  • seat_inventory_id - Required, the specific seat inventory ID to cancel
  • trip id - Required, the trip ID to cancel

Response Fields:

  • cancelled_seat_request_id - ID of the cancelled seat request
  • seat_info - Details of the cancelled seat
  • seat_status - New status of the seat (available)
  • request_status - Status of the request (cancelled)

Key Features:

  • Selective Cancellation - Cancel only one seat from a multi-seat issue
  • Issue Preservation - Other seats in the issue remain active
  • Immediate Release - Cancelled seat becomes available instantly
  • Remaining Seats Info - Response shows what seats are still in the issue

Error Responses:

404 Not Found - Seat Request Not Found

{
  "status": "error",
  "code": 404,
  "message": "Seat request not found, already cancelled, or you do not have permission to remove it",
  "data": null
}
                
403 Forbidden - No Permission

{
  "status": "error",
  "code": 403,
  "message": "You do not have permission to remove this seat request",
  "data": null
}
                
422 Validation Error - Invalid Data

{
  "status": "error",
  "code": 422,
  "message": "The given data was invalid.",
  "data": {
    "seat_inventory_id": ["The seat inventory id field is required."],
    "issue_id": ["The issue id field is required."]
  }
}
                

JavaScript Example:


async function cancelIndividualSeat(seatInventoryId, issueId) {
  try {
    const response = await fetch('/api/seat-requests/cancel', {
      method: 'DELETE',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${localStorage.getItem('access_token')}`
      },
      body: JSON.stringify({
        seat_inventory_id: seatInventoryId,
        issue_id: issueId
      })
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(errorData.message);
    }

    const data = await response.json();

    console.log('Seat cancelled successfully:');
    console.log(`- Cancelled seat: ${data.data.seat_info.seat_number}`);
    console.log(`- Remaining seats in issue: ${data.data.remaining_seats_in_issue.total_remaining_seats}`);

    // Update UI to reflect cancellation
    updateSeatUI(data.data.seat_inventory_id, 'available');

    // Update issue summary
    updateIssueSummary(data.data.remaining_seats_in_issue);

    return data;
  } catch (error) {
    console.error('Error cancelling seat:', error);
    showErrorMessage(`Failed to cancel seat: ${error.message}`);
    throw error;
  }
}

// Usage example with confirmation
async function cancelSeatWithConfirmation(seatNumber, seatInventoryId, issueId) {
  const confirm = window.confirm(`Are you sure you want to cancel seat ${seatNumber}?`);

  if (confirm) {
    try {
      const result = await cancelIndividualSeat(seatInventoryId, issueId);

      showSuccessMessage(`Seat ${seatNumber} cancelled successfully`);

      // Check if this was the last seat in the issue
      if (result.data.remaining_seats_in_issue.total_remaining_seats === 0) {
        showInfoMessage('All seats have been cancelled from this issue');
        redirectToSeatSelection();
      }

      return result;
    } catch (error) {
      // Error handling is done in cancelIndividualSeat
    }
  } else {
    console.log('Seat cancellation aborted by user');
  }
}

// Helper functions
function updateSeatUI(seatInventoryId, status) {
  const seatElement = document.querySelector(`[data-seat-inventory-id="${seatInventoryId}"]`);
  if (seatElement) {
    seatElement.classList.remove('selected', 'blocked');
    seatElement.classList.add(status);
  }
}

function updateIssueSummary(remainingSeats) {
  const summaryElement = document.getElementById('issue-summary');
  if (summaryElement) {
    summaryElement.innerHTML = `
      
Issue: ${remainingSeats.issue_id}

Remaining seats: ${remainingSeats.total_remaining_seats}

`; } } function showSuccessMessage(message) { // Your success notification implementation console.log('[SUCCESS]', message); } function showErrorMessage(message) { // Your error notification implementation console.log('[ERROR]', message); } function showInfoMessage(message) { // Your info notification implementation console.log('[INFO]', message); } function redirectToSeatSelection() { // Redirect to seat selection page window.location.href = '/select-seats'; }

Use Cases:

  • Partial Cancellation - User wants to keep some seats but cancel others
  • Seat Adjustment - Cancel one seat to select a different one
  • Group Changes - Remove one person from a group booking
  • Error Correction - Cancel accidentally selected seats

Best Practices:

  • Confirmation - Always confirm with user before cancelling individual seats
  • UI Updates - Immediately update seat selection UI after cancellation
  • Issue Tracking - Keep track of remaining seats in the issue
  • Error Handling - Handle permission and validation errors gracefully
  • User Feedback - Provide clear feedback about the cancellation result

Notes:

  • Only the user who created the seat request can cancel it
  • Cancelled seats become immediately available for other users
  • If this is the last seat in an issue, the issue remains but becomes empty
  • The operation is atomic - either succeeds completely or fails without changes