AerTicket Integration
Interface to AerTicket API for flight search, verification, booking, ticket issuance, void, ancillaries, retrieval, and cancellation. Supports both UAT and Production environments with automatic authentication, retry logic, and comprehensive error handling.
Quick Start
Section titled “Quick Start”Installation
Section titled “Installation”Environment Variables (.env)
AERTICKET_UAT_CABINET_URL=https://uat-cabinet.aerticket.comAERTICKET_UAT_API_BASE_URL=https://uat-api.aerticket.comAERTICKET_UAT_USERNAME=your_uat_usernameAERTICKET_UAT_PASSWORD=your_uat_password
AERTICKET_DEFAULT_ENVIRONMENT=uatAERTICKET_TIMEOUT=30Test Connection
./vendor/bin/sail artisan aerticket:test-connectionBasic Flight Search
Section titled “Basic Flight Search”use App\Services\AerticketCabinetService;use App\Services\Flights\Aerticket\AerticketSearchService;
$cabinet = app(AerticketCabinetService::class);$search = new AerticketSearchService($cabinet);
$results = $search->search([ 'origin' => 'BCN', 'destination' => 'MAD', 'departure_date' => '2025-12-15', 'return_date' => '2025-12-20', 'adults' => 2, 'cabin_class' => 'economy',]);
foreach ($results->getFares() as $fare) { echo "Price: {$fare->getTotalPrice()} {$fare->getCurrency()}\n";}Multi-City Flight Search
Section titled “Multi-City Flight Search”use App\Services\Flights\Aerticket\AerticketSearchService;use App\Services\Flights\Aerticket\DTOs\Request\PassengerType;use App\Services\Flights\Aerticket\DTOs\Request\SearchOptions;use App\Services\Flights\Aerticket\DTOs\Request\SearchRequest;
// Define multi-city segments (2-6 segments allowed)$segments = [ ['departure' => 'BCN', 'destination' => 'BKK', 'date' => '2025-12-20'], ['departure' => 'BKK', 'destination' => 'CNX', 'date' => '2025-12-25'], ['departure' => 'CNX', 'destination' => 'BCN', 'date' => '2026-01-05'],];
// Build passenger types$passengers = [ PassengerType::adult(2), PassengerType::child(1),];
// Create multi-city search request$searchRequest = SearchRequest::multiCity( segments: $segments, passengerTypeList: $passengers, searchOptions: new SearchOptions(cabinClassList: ['ECONOMY']));
// Execute search$searchService = new AerticketSearchService();$response = $searchService->search($searchRequest);Service Components
Section titled “Service Components”| Service | Purpose |
|---|---|
AerticketCabinetService | HTTP client, authentication, environment switching |
AerticketSearchService | Flight search |
AerticketSearchUpsellService | Fare upgrade search |
AerticketVerifyService | Fare verification |
AerticketBookService | Booking creation |
AerticketTicketIssueService | Ticket issuance |
AerticketFastlaneTicketingService | Fast-track ticket issuance |
AerticketRePriceService | Booking re-pricing |
AerticketVoidService | Booking void |
AerticketAncillaryService | Ancillary services (baggage, meals) |
AerticketFareRulesService | Fare rules and restrictions |
AerticketRetrieveService | PNR retrieval |
AerticketCancelService | Booking cancellation |
Configuration
Section titled “Configuration”Environment Variables
Section titled “Environment Variables”# UAT (default)AERTICKET_UAT_CABINET_URL=https://uat-cabinet.aerticket.comAERTICKET_UAT_API_BASE_URL=https://uat-api.aerticket.comAERTICKET_UAT_USERNAME=your_usernameAERTICKET_UAT_PASSWORD=your_password
# ProductionAERTICKET_PRODUCTION_CABINET_URL=https://cabinet.aerticket.comAERTICKET_PRODUCTION_API_BASE_URL=https://api.aerticket.comAERTICKET_PRODUCTION_USERNAME=your_usernameAERTICKET_PRODUCTION_PASSWORD=your_password
# Environment SelectionAERTICKET_ENVIRONMENT=uat # Values: "uat" or "production"
# Timeouts and RetriesAERTICKET_TIMEOUT=30AERTICKET_RETRY_ATTEMPTS=3AERTICKET_FASTLANE_TIMEOUT=300Staging Environment Safeguards
Section titled “Staging Environment Safeguards”To prevent accidental low-cost carrier bookings in staging/UAT:
- Flydubai flights (airline code: FZ) are blocked
- Flights requiring instant purchase are blocked
Controlled by AERTICKET_ENVIRONMENT variable - active when set to "uat".
Key Operations
Section titled “Key Operations”Verify Fare
Section titled “Verify Fare”use App\Services\Flights\Aerticket\AerticketVerifyService;
$verify = new AerticketVerifyService($cabinet);
$response = $verify->verify([ 'fare_id' => $fare->getId(), 'session_id' => $searchResponse->getSessionId(),]);
if ($response->isAvailable()) { $updatedPrice = $response->getPrice();}Create Booking (Async)
Section titled “Create Booking (Async)”use App\Jobs\AerticketCreateBookingJob;
AerticketCreateBookingJob::dispatch( fareId: 'fare-123', instantTicketOrder: true, userId: auth()->id())->onQueue('aerticket-bookings');Issue Ticket
Section titled “Issue Ticket”use App\Jobs\AerticketIssueTicketJob;
AerticketIssueTicketJob::dispatch( bookingReference: 'ABC123', bookingId: $flightBooking->id, userId: auth()->id())->onQueue('aerticket-tickets');Fastlane Ticketing
Section titled “Fastlane Ticketing”Faster alternative to regular ticket issuance. Booking must be at least 5 minutes old.
use App\Jobs\AerticketFastlaneTicketingJob;
AerticketFastlaneTicketingJob::dispatch( bookingReference: 'ABC123', bookingId: $flightBooking->id, userId: auth()->id())->onQueue('aerticket-fastlane');Re-Price Booking
Section titled “Re-Price Booking”use App\Services\Flights\Aerticket\AerticketRePriceService;use App\Services\Flights\Aerticket\DTOs\Request\PriceRange;
$rePriceService = new AerticketRePriceService($cabinet);
// Re-pricing with price tolerance (±5 EUR)$priceRange = new PriceRange(min: 5.0, max: 5.0);$response = $rePriceService->rePrice('ABC123', $priceRange);
if ($response->hasNewFares()) { // Price outside tolerance - requires approval $subFareToken = $response->getSubFareToken();}View Ancillaries
Section titled “View Ancillaries”use App\Services\Flights\Aerticket\AerticketAncillaryService;
$ancillaryService = new AerticketAncillaryService($cabinet);
// For bookings (after booking)$response = $ancillaryService->availableBookingAncillaries( pnrLocator: 'ABC123', ancillaryTypes: ['BAGGAGE', 'MEAL']);
foreach ($response->getAncillariesByType() as $type => $ancillaries) { foreach ($ancillaries as $ancillary) { echo "{$ancillary->name}: {$ancillary->getFormattedPrice()}\n"; }}Cancel Booking
Section titled “Cancel Booking”use App\Services\Flights\Aerticket\AerticketCancelService;
$cancel = new AerticketCancelService($cabinet);
// Normal cancellation$result = $cancel->cancelBooking('ABC123');
// Force cancellation (even if tickets issued)$result = $cancel->cancelBooking('ABC123', forceCancellation: true);Passenger Validation
Section titled “Passenger Validation”Name Validation
Section titled “Name Validation”Per AerTicket API specification:
- No numbers in firstName or lastName
- No symbols (only letters and spaces)
- No ”+” character
- Combined length: 2-57 characters
- Valid titles: MR, MRS, MS, CHD, INF, DR MR, etc.
use App\Rules\PassengerValidationRules;
// In Form Requestspublic function rules(): array{ return [ 'passengerList.*.firstName' => PassengerValidationRules::firstName(), 'passengerList.*.lastName' => PassengerValidationRules::lastName(), 'passengerList.*.title' => PassengerValidationRules::title(), ];}Age Category Validation
Section titled “Age Category Validation”- Infant (INF): 0-23 months
- Child (CHD): 2-15 years
- Adult (ADT): 16+ years
use App\Enums\AgeCategory;
$ageCategory = AgeCategory::fromDateOfBirth($dateOfBirth);
if (!$ageCategory->isValidForDateOfBirth($dateOfBirth)) { $errorMessage = $ageCategory->getValidationErrorMessage($dateOfBirth);}Error Handling
Section titled “Error Handling”Exception Types
Section titled “Exception Types”| Exception | Description |
|---|---|
AerticketValidationException | Invalid input |
AerticketTimeoutException | Request timeout |
AerticketSearchException | Search error |
AerticketBookingException | Booking error |
AerticketTicketIssueException | Ticket issuance error |
AerticketRePricingException | Re-pricing error |
AerticketFareExpiredException | Fare expired (410) |
AerticketPriceChangeException | Price changed |
Example Error Handling
Section titled “Example Error Handling”try { $results = $search->search($data);} catch (AerticketValidationException $e) { return response()->json(['error' => $e->getMessage()], 422);} catch (AerticketTimeoutException $e) { return response()->json(['error' => 'Request timed out'], 504);} catch (AerticketSearchException $e) { Log::error('Search failed', ['error' => $e->getMessage()]); return response()->json(['error' => 'Search failed'], 500);}Testing
Section titled “Testing”# All AerTicket tests./vendor/bin/sail artisan test --filter=Aerticket
# Connection test./vendor/bin/sail artisan aerticket:test-connection
# Re-pricing tests./vendor/bin/sail artisan test --filter=RePrice
# Ancillary tests./vendor/bin/sail artisan test --filter=AncillaryTroubleshooting
Section titled “Troubleshooting”Authentication Failure (401)
Section titled “Authentication Failure (401)”php artisan tinker>>> config('aerticket.environments.uat.username')Connection Timeout
Section titled “Connection Timeout”Increase timeout in .env:
AERTICKET_TIMEOUT=60Missing apihubflowid
Section titled “Missing apihubflowid”Check logs:
./vendor/bin/sail artisan pail --filter="apihubflowid"The apihubflowid is required when contacting AerTicket support.
Related Documentation
Section titled “Related Documentation”- Async Booking Workflow - Queue-based booking
- Flight Search UI - FilamentPHP interface
- Airport Search - Airport lookup service
- Queue System - Queue infrastructure