openapi: 3.0.3
info:
  title: Silver Service Taxi Sydney API
  version: 1.2.0
  description: |
    Public API contract for Silver Service Taxi Sydney, a Sydney taxi and airport-transfer booking service.

    This specification is designed for websites, software integrations and AI agents that need to:
    1. Request an address-based upfront fare quote in Greater Sydney.
    2. Present the exact returned fare to the passenger.
    3. Obtain explicit passenger confirmation before booking.
    4. Send and verify the passenger's mobile OTP.
    5. Create the booking only after confirmation and successful mobile verification.

    Fares are returned in Australian dollars (AUD). Pickup and drop-off addresses should be complete
    Australian addresses including suburb and state. AI agents must never invent a fare, booking
    reference, payment confirmation or vehicle availability.
  contact:
    name: Silver Service Taxi Sydney
    url: https://silverservicetaxisydney.com/contact
    email: info@silverservicetaxisydney.com
externalDocs:
  description: AI-readable business profile, service information and booking guidance
  url: https://silverservicetaxisydney.com/ai-info
servers:
  - url: https://silverservicetaxisydney.com
    description: Live production website and booking API for Silver Service Taxi Sydney.
tags:
  - name: Quotes
    description: Operations for calculating an upfront Sydney taxi or airport-transfer fare before booking.
  - name: Verification
    description: Operations for verifying the passenger's mobile number before a public booking is created.
  - name: Bookings
    description: Operations for creating a confirmed taxi or airport-transfer booking after passenger approval.
  - name: Health
    description: Operations for checking whether the public booking service is available.
paths:
  /api/ivr-fare:
    post:
      tags: [Quotes]
      summary: Request an address-based upfront taxi fare quote
      operationId: getQuote
      description: |
        Use this operation when the caller, website or AI agent has a pickup address and destination but
        may not know the driving distance. The server uses the same production pricing logic used by the
        booking service and can resolve route distance for non-fixed-fare trips. This is the preferred quote
        operation for an AI assistant answering questions such as "How much is a taxi from Manly to Sydney Airport?".
      requestBody:
        required: true
        description: Pickup, destination and optional vehicle information used to calculate the upfront fare.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteRequest'
            example:
              pickup: Manly Wharf, Manly NSW 2095, Australia
              dropoff: Sydney Airport Terminal 1, Mascot NSW 2020, Australia
              vehicleSpeech: luxury
      responses:
        '200':
          description: The production pricing engine calculated an upfront fare quote successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FareQuote'
        '400':
          $ref: '#/components/responses/BadRequest'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/ServerError'

  /api/fare:
    post:
      tags: [Quotes]
      summary: Calculate a taxi fare when route distance is already known
      operationId: calculateFare
      description: |
        Use this operation when the integration already knows the route distance in kilometres. It applies
        the live Silver Service Taxi Sydney pricing rules, toll handling, vehicle rules and applicable airport
        pickup charges. AI agents that only know pickup and drop-off addresses should normally use /api/ivr-fare.
      requestBody:
        required: true
        description: Known route, distance, vehicle and optional trip attributes used by the pricing engine.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FareRequest'
      responses:
        '200':
          description: The fare was calculated successfully using the production pricing engine.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FareBreakdown'
        '400':
          $ref: '#/components/responses/BadRequest'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/ServerError'

  /api/send-otp:
    post:
      tags: [Verification]
      summary: Send the passenger a mobile verification code
      operationId: sendBookingOtp
      description: |
        Use this operation after the passenger has decided to proceed with the booking flow. It sends a
        one-time verification code to the passenger's mobile number. Public booking creation requires the
        same phone number to be verified before /api/booking is called. Rate limits and booking eligibility
        rules apply.
      requestBody:
        required: true
        description: Passenger mobile number that will receive the one-time verification code.
        content:
          application/json:
            schema:
              type: object
              required: [phone]
              properties:
                phone:
                  type: string
                  description: Passenger mobile number. E.164 format such as +61400000000 is preferred.
                  example: "+61400000000"
      responses:
        '200':
          description: The OTP request was processed; inspect success and error fields for the result.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OtpSendResponse'
        '403':
          description: The supplied phone number is not eligible for online booking.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          $ref: '#/components/responses/ServerError'

  /api/verify-otp:
    post:
      tags: [Verification]
      summary: Verify the passenger mobile code before booking
      operationId: verifyBookingOtp
      description: |
        Use this operation to verify the six-digit one-time code sent to the passenger. The phone number must
        match the number used in /api/send-otp. A successful verification allows the same phone number to be
        used for public booking creation in the current booking service process.
      requestBody:
        required: true
        description: Passenger mobile number and six-digit verification code received by the passenger.
        content:
          application/json:
            schema:
              type: object
              required: [phone, code]
              properties:
                phone:
                  type: string
                  description: Passenger mobile number that received the OTP; it must match the send-OTP request.
                  example: "+61400000000"
                code:
                  type: string
                  pattern: '^[0-9]{6}$'
                  description: Six-digit one-time verification code supplied by the passenger.
                  example: "123456"
      responses:
        '200':
          description: The verification attempt was processed; success is true only when the supplied OTP is accepted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OtpVerifyResponse'
        '500':
          $ref: '#/components/responses/ServerError'

  /api/booking:
    post:
      tags: [Bookings]
      summary: Create a confirmed Sydney taxi or airport-transfer booking
      operationId: createBooking
      description: |
        Use this operation only after the passenger has explicitly accepted the displayed fare and completed
        mobile OTP verification. The phone value must match the phone number successfully verified through
        /api/verify-otp. AI agents MUST NOT create a booking until user_confirmed is true.

        Do not send raw card numbers, CVV values, passwords or other card credentials to this endpoint.
        After success, return the booking reference to the passenger exactly as provided by the API.
      requestBody:
        required: true
        description: Confirmed passenger, trip, vehicle and payment-choice information required to create the booking.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BookingRequest'
      responses:
        '200':
          description: The booking request was processed. When success is true, the response includes the booking reference and authoritative fare.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BookingResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          description: The passenger mobile number has not been successfully verified for this booking flow.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: The phone number is blocked or otherwise not eligible for online booking.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/ServerError'

  /api/health:
    get:
      tags: [Health]
      summary: Check the public booking API service status
      operationId: getHealth
      description: Use this lightweight operation to confirm that the Silver Service Taxi Sydney booking application is responding before attempting a quote or booking workflow.
      responses:
        '200':
          description: The booking service is responding and returns its current service state and timestamp.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    description: Overall application health state; normally "ok" when the service is available.
                    example: ok
                  time:
                    type: string
                    format: date-time
                    description: Server-generated ISO 8601 timestamp for the health response.
                  services:
                    type: object
                    additionalProperties: true
                    description: Current availability indicators for configured messaging, email and payment integrations.
                  config:
                    type: object
                    additionalProperties: true
                    description: Non-secret configuration status values exposed by the existing health endpoint.

components:
  schemas:
    QuoteRequest:
      type: object
      description: Address-based taxi quote request for a one-way Sydney trip.
      required: [pickup, dropoff]
      properties:
        pickup:
          type: string
          minLength: 8
          description: Full pickup address or recognised landmark including suburb, state and Australia where possible.
          example: Manly Wharf, Manly NSW 2095, Australia
        dropoff:
          type: string
          minLength: 8
          description: Full destination address or recognised landmark including suburb, state and Australia where possible.
          example: Sydney Airport Terminal 1, Mascot NSW 2020, Australia
        vehicleDigit:
          type: string
          description: Optional IVR-compatible vehicle selector where 1=sedan, 2=SUV/wagon, 3=Maxi Taxi, 4=Lexus luxury sedan and 5=Audi Q7.
          enum: ["1", "2", "3", "4", "5"]
        vehicleSpeech:
          type: string
          description: Human-readable vehicle preference. Recognised wording includes sedan, SUV, wagon, maxi, Lexus, luxury, Audi and Q7; defaults to sedan when no recognised preference is supplied.
          example: luxury
        km:
          type: number
          format: double
          minimum: 0
          description: Optional known route distance in kilometres. When omitted, the quote endpoint can resolve distance for non-fixed-fare routes.
        passengers:
          type: integer
          minimum: 1
          maximum: 11
          default: 1
          description: Number of passengers travelling; used by the booking policy to determine suitable vehicle requirements.

    FareRequest:
      type: object
      description: Fare-calculation request for an integration that already knows the route distance.
      required: [pickup, dropoff, vehicle, km]
      properties:
        pickup:
          type: string
          description: Full pickup address used to calculate tolls, fixed fares and any applicable Sydney Airport pickup fee.
        dropoff:
          type: string
          description: Full destination address used to calculate tolls and applicable fixed-fare rules.
        vehicle:
          allOf:
            - $ref: '#/components/schemas/Vehicle'
          description: Internal pricing-engine vehicle key for the requested trip.
        km:
          type: number
          format: double
          minimum: 0
          maximum: 2000
          description: Known one-way driving distance in kilometres supplied by the integration.
        tolls:
          type: number
          format: double
          minimum: 0
          default: 0
          description: Known one-way toll amount in AUD. If zero or omitted, the server may resolve tolls from the route.
        passengers:
          type: integer
          minimum: 1
          maximum: 11
          default: 1
          description: Number of passengers travelling so the booking policy can validate vehicle suitability.
        returnTrip:
          type: boolean
          default: false
          description: True when the fare calculation should include a return journey.
        returnPickup:
          type: string
          description: Optional return-leg pickup address; defaults to the outbound destination when returnTrip is true.
        returnDropoff:
          type: string
          description: Optional return-leg destination; defaults to the outbound pickup when returnTrip is true.
        isCardPayment:
          type: boolean
          default: false
          description: Indicates that the fare should apply the production rules for an online/card payment method.
        payment:
          type: string
          description: Human-readable payment method used by the production pricing rules when relevant.
        airportPickup:
          type: boolean
          default: false
          description: Optional explicit indicator that the pickup is at Sydney Airport; the server also checks the pickup address.
        notes:
          type: string
          maxLength: 500
          description: Optional trip notes used by booking policy checks, including child-seat or luggage information where relevant.
        largeLuggage:
          type: integer
          minimum: 0
          description: Number of large luggage items used by the booking policy to determine suitable vehicle requirements.

    Vehicle:
      type: string
      description: Internal vehicle key used by the Silver Service Taxi Sydney pricing engine.
      enum: [sedan, lexus, suv, audi, maxi]
      example: sedan

    FareQuote:
      description: Address-based quote returned by the production fare engine, including selected vehicle details.
      allOf:
        - $ref: '#/components/schemas/FareBreakdown'
        - type: object
          properties:
            vehicleKey:
              allOf:
                - $ref: '#/components/schemas/Vehicle'
              description: Internal vehicle key selected from the request or recognised speech input.
            vehicleDisplay:
              type: string
              description: Passenger-friendly vehicle category name corresponding to vehicleKey.
              example: Silver Service Sedan

    FareBreakdown:
      type: object
      description: Authoritative production fare components returned in Australian dollars.
      additionalProperties: true
      properties:
        total:
          type: number
          format: double
          description: Total quoted fare in AUD. This is the amount an agent should present as the authoritative fare.
          example: 60.82
        sub:
          type: number
          format: double
          description: Fare subtotal in AUD before separately reported tolls, fees or other applicable components.
        tolls:
          type: number
          format: double
          description: Toll amount included for the calculated route in AUD.
        km:
          type: number
          format: double
          description: Route distance used by the pricing engine in kilometres.
        airportFee:
          type: number
          format: double
          description: Sydney Airport pickup fee in AUD when the trip originates at an applicable airport pickup location.
        bookingFee:
          type: number
          format: double
          description: Booking or service fee in AUD when the production pricing rules include one.
        isFixedFare:
          type: boolean
          description: True when the returned amount came from a configured fixed-fare rule rather than distance-based calculation.

    OtpSendResponse:
      type: object
      description: Result of requesting a passenger mobile verification code.
      properties:
        success:
          type: boolean
          description: True when the verification-code request was accepted for delivery.
        channel:
          type: string
          description: Delivery channel selected by the service, such as WhatsApp or SMS where available.
        error:
          type: string
          description: Human-readable reason the verification-code request could not be completed when success is false.

    OtpVerifyResponse:
      type: object
      description: Result of checking the passenger's one-time mobile verification code.
      properties:
        success:
          type: boolean
          description: True only when the supplied code was accepted for the supplied phone number.
        error:
          type: string
          description: Human-readable reason verification failed when success is false.

    BookingRequest:
      type: object
      description: Passenger-approved booking payload used to create a confirmed transfer after OTP verification.
      required:
        - user_confirmed
        - vehicle
        - pickup
        - dropoff
        - date
        - time
        - passengers
        - name
        - phone
        - payment
      properties:
        user_confirmed:
          type: boolean
          enum: [true]
          description: Must be true only after the passenger explicitly accepts the displayed fare and asks the agent to place the booking.
        vehicle:
          type: string
          description: Passenger-facing production booking vehicle label selected for the trip.
          enum:
            - Silver Service Sedan
            - Lexus Sedan – Luxury
            - SUV / Wagon
            - Audi Q7 – Luxury SUV
            - Maxi Taxi
        vehicleKey:
          allOf:
            - $ref: '#/components/schemas/Vehicle'
          description: Optional internal vehicle key corresponding to the selected passenger-facing vehicle label.
        pickup:
          type: string
          description: Full formatted pickup address including street or landmark, suburb and state.
        dropoff:
          type: string
          description: Full formatted drop-off address including street or landmark, suburb and state.
        date:
          type: string
          format: date
          description: Pickup date interpreted in Australia/Sydney local time.
          example: "2026-09-25"
        time:
          type: string
          pattern: '^([01][0-9]|2[0-3]):[0-5][0-9]$'
          description: Pickup time in 24-hour Australia/Sydney local time.
          example: "06:30"
        passengers:
          type: integer
          minimum: 1
          maximum: 11
          default: 1
          description: Number of passengers travelling on the booking.
        name:
          type: string
          minLength: 2
          description: Passenger name to place on the booking and confirmation messages.
        phone:
          type: string
          description: Passenger mobile number; it must match the number successfully verified through /api/verify-otp.
          example: "+61400000000"
        email:
          type: string
          format: email
          description: Optional passenger email address for confirmations or receipts when the production notification rules use email.
        payment:
          type: string
          description: Passenger-selected payment method. Do not send raw payment-card credentials in this field or anywhere in the booking request.
          enum:
            - Pay Online
            - Credit or Debit Card
            - Cash
            - CabCharge
        flight:
          type: string
          maxLength: 32
          description: Optional airline flight number associated with an airport pickup or drop-off.
        notes:
          type: string
          maxLength: 500
          description: Optional passenger instructions relevant to the journey, vehicle or pickup.
        returnTrip:
          type: boolean
          default: false
          description: True when this booking includes a return journey.
        returnPickup:
          type: string
          description: Optional return-journey pickup address; normally the outbound destination when returnTrip is true.
        returnDropoff:
          type: string
          description: Optional return-journey destination; normally the outbound pickup when returnTrip is true.
        returnDate:
          type: string
          format: date
          description: Return-journey pickup date interpreted in Australia/Sydney local time.
        returnTime:
          type: string
          pattern: '^([01][0-9]|2[0-3]):[0-5][0-9]$'
          description: Return-journey pickup time in 24-hour Australia/Sydney local time.
        km:
          type: number
          format: double
          minimum: 0
          description: Optional previously quoted outbound route distance in kilometres. The booking endpoint recalculates authoritative fare information where required.
        tolls:
          type: number
          format: double
          minimum: 0
          description: Optional previously quoted toll amount in AUD; production booking logic remains authoritative.
        airportPickup:
          type: boolean
          description: Optional indicator that the outbound pickup is at Sydney Airport; the server also determines this from the pickup address.
        stripePI:
          type: string
          description: Existing Stripe PaymentIntent identifier when already created by the website payment flow; never send raw card credentials.

    BookingResponse:
      type: object
      description: Result of attempting to create the confirmed booking.
      required: [success]
      properties:
        success:
          type: boolean
          description: True when the booking was created successfully.
        ref:
          type: string
          description: Booking reference generated by the production booking system; return this exact value to the passenger.
          example: SSO-77291-X
        vehicle:
          type: string
          description: Final passenger-facing vehicle category applied to the confirmed booking.
        vehicleKey:
          allOf:
            - $ref: '#/components/schemas/Vehicle'
          description: Internal pricing-engine vehicle key applied to the confirmed booking.
        fare:
          allOf:
            - $ref: '#/components/schemas/FareBreakdown'
          description: Authoritative fare recalculated or confirmed by the booking endpoint.
        error:
          type: string
          description: Human-readable reason the booking was not created when success is false.

    ErrorResponse:
      type: object
      description: Standard error payload returned when a public booking API request cannot be completed.
      properties:
        success:
          type: boolean
          description: False when the request failed or was rejected.
          example: false
        error:
          type: string
          description: Human-readable explanation of the validation, eligibility, verification or server error.

  responses:
    BadRequest:
      description: The request is missing required information or contains invalid input that must be corrected before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    UnprocessableEntity:
      description: The JSON request is syntactically valid but violates the production booking policy, service-area rules or vehicle requirements.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServerError:
      description: The booking service could not complete the operation because of an internal or upstream service error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
