- Developers
- Voyage search and remaining seats
Voyage search and remaining seats
The voyage search flow provides departure timetables between piers for specific dates, remaining seat counts, and detailed seat maps so that passengers can select their seats before booking. Ferry serves voyage data that is periodically synchronized from ferry operators; the data represents a recent snapshot rather than the instantaneous state of the operator’s booking engine.
Prerequisites before starting
Section titled “Prerequisites before starting”| Prerequisite | Business context | Reference |
|---|---|---|
| Valid API key | Searching voyages, seat maps, and counts requires partner authentication | Authentication with an API key |
| Departure and arrival pier codes | Voyage lookup uses standardized pier identifiers rather than free-form names | See public pier catalogue |
| Target environment | The UAT sandbox environment disables synchronization for specific operators | Environments |
| Pagination and date conventions | Responses are capped at 50 records per page; dates use YYYY-MM-DD | General conventions |
| Pricing rules | Prices in voyage search results include markups applied by upstream organizations | Ticket pricing and multi-level markup |
Integration steps
Section titled “Integration steps”The diagram below illustrates the sequence of interactions between your system and Ferry during the search flow:
sequenceDiagram autonumber participant P as "Your system" participant F as "Ferry API" participant S as "Boat layout"
P->>F: "Fetch pier catalogue (public)" F-->>P: "Pier list with pier codes"
P->>F: "Search voyages by pier pair and date"
alt "Returned list is empty" F-->>P: "Empty array with status 200" Note over P,F: "Empty list: no voyages or data service disruption" P->>P: "Check alert threshold" else "Voyages available" F-->>P: "Voyage list with base prices" P->>S: "Fetch boat layout by voyage ID" S-->>P: "Seat layout with individual seat statuses" P->>F: "Count remaining seats" F-->>P: "Number of available seats" endThe diagram below shows the relationship between catalogue discovery and voyage lookup:
flowchart LR A["Fetch pier and route catalogue<br/>(no API key needed)"] --> B["Search voyages by pier and date<br/>(API key required)"] B --> C["Fetch boat layout for voyage<br/>(API key required)"] C --> D["Count remaining seats<br/>(API key required)"] D --> E["Proceed to booking flow"] A -.->|"Client-side cache"| A B -.->|"Repeat on date or pier change"| BThe table below summarizes the actions at each step:
| Step | Your system | Ferry API | Partner takeaway |
|---|---|---|---|
| 1 | Fetch route and pier catalogue once | Returns shared catalogue (no key required) | Cache locally; do not re-fetch on every user search |
| 2 | Query voyages by pier pair and date | Returns voyages from synchronized cache | Inspect the array; do not immediately assume sold-out on empty |
| 3 | Fetch boat layout for selected voyage | Returns deck structure and seat statuses | Vacant seats represent the latest sync snapshot |
| 4 | Count remaining seats before selection | Returns total available seat count | Confirm availability against the party size |
| 5 | Pass voyage and seat data to booking | Prepare voyage, seat, and passenger payloads | See next: The booking flow |
- Voyage lookup supports a date range for month-calendar views, not only a single day; still fetch all result pages.
- A
YYYY-MM-DDdate uses the operator’s local time, with no accompanying timezone field. If your server runs elsewhere, convert to Vietnam time before building the date string. - Route and pier catalogues are shared across organizations and remain subject to IP rate limits despite requiring no key. Refresh catalogue caches daily; no change-frequency commitment is defined.
Sync cadence and data freshness
Section titled “Sync cadence and data freshness”Ferry synchronizes voyage schedules from operators according to designated date brackets:
| Date bracket | Time window | Sync cadence |
|---|---|---|
| Near-term | Today to 7 days ahead | Every 30 minutes |
| Medium-term | 8 to 14 days ahead | Every 2 hours |
| Long-term | 15 to 45 days ahead | Every 4 hours |
| Far-term | 46 to 90 days ahead | 3 times daily |
| Sold-out voyages | All dates | Re-scanned every 40 minutes |
| Operator-disabled voyages | All dates | Re-scanned every 4 hours |
Three factors influence effective data freshness:
- Jittered worker scheduling: Sync executions are staggered across a 5-minute window to avoid thundering herds against operator servers.
- Skipping unchanged far dates: For long-term schedules, if the cached copy remains valid, queries against the operator engine are skipped.
- Fallback during operator outages: Ferry can return the last known valid snapshot for up to 4 hours instead of an error. The response has no indicator identifying fallback data; report unusually unchanged figures to Ferry.
Partner design recommendation: Cache voyage search results on your side for no longer than 5 minutes for near dates, and always refresh the boat layout and available count right before prompting the passenger to finalize their seat.
Integration pitfalls to avoid
Section titled “Integration pitfalls to avoid”- Empty list with status 200: Voyage queries return an empty array if no trips are scheduled or if an internal query disruption occurs. Set up anomaly detection on key commercial routes.
- Sort parameters are ignored: Sorting by departure time or price is silently replaced with sorting by record identifier. Fetch all pages, then sort the results in your application.
- Record limit ceilings: Standard voyage searches are silently capped at 50 records per page. The HTML voyage table for embedding in websites or emails has a separate cap of 100. Follow pagination cursors to retrieve all data.
- Absence of temporary hold: Viewing the seat map or creating a booking does not hold seats on the operator system. A new booking is only a Ferry record; seats and tickets are confirmed after ticket issuance succeeds.
- Operators without automated ticketing: Voyage searches return schedules across 13 operators, but 4 of them do not currently support automated electronic ticket issuance via API. See Ticket issuance.
Common errors and remedies
Section titled “Common errors and remedies”| Symptom | Probable cause | Recommended action | Retry safe |
|---|---|---|---|
| Empty voyage list on an active route | Booking window not yet opened or temporary operator connection issue | Verify public timetable; notify Ferry if issue persists | Retry after a backoff window |
| Max 50 items returned despite higher limit requested | System pagination ceiling clamped at 50 records | Paginate through subsequent pages using cursor | Yes, request next cursor |
| Results not ordered by departure time | Sorting parameters handled by internal identifiers | Re-sort the result list in your client application | No, handle on client side |
| Seat shown as available but booking fails | Seat taken by another channel prior to order creation | Refresh seat layout and prompt user to pick another seat | Yes, after layout refresh |
| HTTP 403 returned on voyage search | Not a missing permission: voyage search, seat layouts, and counts require a valid key but no separate permissions | Retry once; if the error persists or is widespread, report it to Ferry operations | Yes, once |
Where to look on Scalar
Section titled “Where to look on Scalar”To inspect exact request schemas and test calls directly, open the Scalar UI under the relevant tags:
| Capability | Scalar tag |
|---|---|
| Search voyages by pier and date, timetables | Voyages |
| Seat map layout and seat status | Boat Layout |
| Remaining seat counts | Voyage Counts |
| Route catalogue (public) | Routes |
| Pier locations catalogue (public) | Locations |
| Ferry operators catalogue (public) | Operators |
For instructions on configuring your API key in Scalar, see API Reference.
Read next
Section titled “Read next”| Page | Related topic |
|---|---|
| Ticket pricing and multi-level markup | Understanding price calculations and additions |
| The booking flow | Creating bookings and managing order lifecycles |
| General conventions | Date formats, currency conventions, and pagination rules |
| Environments | Data and connectivity differences between UAT and production |
| Ticket issuance | Complete ticket confirmation flow and issued ticket retrieval |