# API Contract This document proposes the initial REST API for AzioneLab. Endpoint names are intentionally explicit and small-project friendly. All examples use JSON unless noted otherwise. ## Public Content ### List Shows ```http GET /api/shows/ ``` Returns published shows. Response `200 OK`: ```json { "results": [ { "id": 1, "title": "The Open Stage", "slug": "the-open-stage", "summary": "A contemporary theatre performance.", "poster_image": "https://example.org/media/shows/open-stage.jpg" } ] } ``` ### Show Detail ```http GET /api/shows/{slug}/ ``` Response `200 OK`: ```json { "id": 1, "title": "The Open Stage", "slug": "the-open-stage", "summary": "A contemporary theatre performance.", "description": "Full public show description.", "poster_image": "https://example.org/media/shows/open-stage.jpg", "performances": [ { "id": 10, "starts_at": "2026-05-15T20:30:00+02:00", "venue": { "name": "AzioneLab Theatre", "city": "Rome" }, "booking_enabled": true, "available_seats": 24 } ] } ``` Status codes: - `200 OK`: show found; - `404 Not Found`: show does not exist or is not published. ### List Performances ```http GET /api/performances/ ``` Optional filters: - `show`: show slug; - `from`: start date/time lower bound. Response `200 OK`: ```json { "results": [ { "id": 10, "show": { "title": "The Open Stage", "slug": "the-open-stage" }, "venue": { "name": "AzioneLab Theatre", "city": "Rome" }, "starts_at": "2026-05-15T20:30:00+02:00", "booking_enabled": true, "available_seats": 24 } ] } ``` ### Performance Detail ```http GET /api/performances/{id}/ ``` Response `200 OK`: ```json { "id": 10, "show": { "title": "The Open Stage", "slug": "the-open-stage", "summary": "A contemporary theatre performance." }, "venue": { "name": "AzioneLab Theatre", "address": "Via Example 10", "city": "Rome" }, "starts_at": "2026-05-15T20:30:00+02:00", "booking_enabled": true, "available_seats": 24 } ``` Status codes: - `200 OK`: performance found; - `404 Not Found`: performance does not exist or is not public. ## Booking ### Create Reservation ```http POST /api/performances/{id}/reservations/ ``` Creates a pending reservation and sends a confirmation email. Request: ```json { "name": "Maria Rossi", "email": "maria.rossi@example.org", "phone": "+390600000000", "party_size": 2, "notes": "We will arrive a few minutes early." } ``` Response `201 Created`: ```json { "id": 123, "status": "pending", "performance": 10, "party_size": 2, "message": "Reservation created. Please check your email to confirm it." } ``` Status codes: - `201 Created`: pending reservation created; - `400 Bad Request`: invalid input; - `404 Not Found`: performance does not exist or is not public; - `409 Conflict`: booking is closed or capacity is already unavailable. Validation rules: - `name` is required; - `email` must be a valid email address; - `party_size` must be a positive integer; - public clients must not set reservation status; - the backend must validate booking availability server-side. ### Confirm Reservation ```http POST /api/reservations/confirm/ ``` Confirms a pending reservation using the token from the email link. Request: ```json { "token": "opaque-confirmation-token" } ``` Response `200 OK`: ```json { "reservation_id": 123, "status": "confirmed", "party_size": 2, "qr_code_url": "https://example.org/api/reservations/123/qr-code/" } ``` Status codes: - `200 OK`: reservation confirmed; - `400 Bad Request`: token is missing or malformed; - `404 Not Found`: token is unknown; - `409 Conflict`: token already used, reservation already handled, or no capacity remains; - `410 Gone`: token expired. ### Retrieve QR Code ```http GET /api/reservations/{id}/qr-code/ ``` Returns the generated QR code for a confirmed reservation. Access must be protected by a valid QR token, signed URL, or equivalent control so that reservation IDs are not enough to retrieve QR codes. Response `200 OK`: ```json { "reservation_id": 123, "qr_code_image": "data:image/png;base64,...", "printable": true } ``` Status codes: - `200 OK`: QR code available; - `403 Forbidden`: caller is not allowed to access the QR code; - `404 Not Found`: reservation not found; - `409 Conflict`: reservation is not confirmed. ## Check-In ### Verify QR Code ```http POST /api/check-ins/verify/ ``` Validates a QR token and records check-in. This endpoint is for authenticated staff or an authenticated scanning interface. Request: ```json { "token": "opaque-check-in-token" } ``` Response `200 OK`: ```json { "status": "checked_in", "reservation_id": 123, "performance_id": 10, "party_size": 2, "checked_in_at": "2026-05-15T19:55:00+02:00" } ``` Status codes: - `200 OK`: reservation checked in; - `400 Bad Request`: token is missing or malformed; - `401 Unauthorized`: staff authentication is missing; - `403 Forbidden`: authenticated user cannot perform check-in; - `404 Not Found`: token is unknown; - `409 Conflict`: reservation is not confirmed or was already checked in; - `410 Gone`: token is expired. The response should include only the minimum information staff need to admit the party. ## Administration The initial administration API is Django admin. Admin paths: ```http GET /admin/ ``` Admin users can manage shows, venues, performances, reservations, reservation tokens, and check-ins according to staff permissions. Status codes: - `302 Found`: unauthenticated browser redirected to admin login; - `200 OK`: authenticated admin page; - `403 Forbidden`: authenticated user lacks the required permission. ## Error Format Use Django REST Framework's standard validation error format unless a project-specific envelope is introduced later. Example `400 Bad Request`: ```json { "email": ["Enter a valid email address."], "party_size": ["Ensure this value is greater than or equal to 1."] } ```