Skip to content

Integration surface overview

6 min read

This page defines the integration boundary between partner systems and the Ferry platform. You will understand which business groups can be called using an API key, which internal areas are closed to external calls, and the core authorization principles across the platform.

The Ferry backend partitions its API surface into 4 distinct tiers according to the caller identity and authentication mechanism:

API TierCallerAuthentication methodPartner availability
publicWebsite visitors, mobile applications, partnersNo authentication requiredCommon catalogs: routes, locations, and operators
partnerB2B integration partnersAPI key in the Authorization headerPrimary partner tier with 86 business routes
internalAgency operations staff and Ferry employeesUser session JWTNot accessible via API key
adminFerry technical operations teamSystem administrator JWTNot accessible via API key

The diagram below illustrates the API tiers and external partner access boundaries:

flowchart LR
subgraph callers["Callers"]
partner["B2B Partner<br/>with API key"]
guest["Public User<br/>unauthenticated"]
dashboard["Operations Staff<br/>with JWT"]
end
subgraph reachable["Partner Reachable Area"]
tierpublic["Public Tier<br/>Shared catalogs"]
tierpartner["Partner Tier<br/>86 business routes"]
end
subgraph blocked["Closed Internal Area"]
tierinternal["Internal Tier<br/>Requires user JWT"]
tieradmin["Admin Tier<br/>Requires admin JWT"]
end
guest --> tierpublic
partner --> tierpublic
partner --> tierpartner
dashboard --> tierinternal

The partner tier declares 112 routes, but only 87 routes are configured with the API key authentication mechanism, with 1 route requiring higher internal administrative privileges. Therefore, exactly 86 routes form the actual callable surface for partners using an API key (the remaining routes serve internal Ferry maintenance tasks such as operator gate testing or forced synchronization).

The public tier consists of 9 routes requiring no authentication. Both tiers appear side-by-side on the public documentation interface at /docs. For shared catalogs such as routes, ferry terminals, and operators, the platform does not provide separate authenticated endpoints — partners must call the public routes directly without passing an API key.

The 86 partner business routes are organised into the following core functional groups:

Business groupCore capabilitiesDetailed guide
Schedule searchSearch voyages by route and date, inspect schedules, get voyage detailsVoyage and seat lookup
Seat layout and availabilityRetrieve cabin layouts, check real-time seat availability per voyageVoyage and seat lookup
Bookings and order managementCreate seat-holding bookings, confirm electronic ticket issuance, query and update bookingsBookings: the life cycle of one booking
Order inquiry (Orders)List and inspect order details (read-only); do not create orders or issue tickets through this groupTicket issuance and orders
CancellationsSubmit ticket cancellation requests and monitor approval status from operatorsCancellation and refunds
Customers and companiesCreate customer profiles, update contact information, and manage company recordsInspect on Scalar, Customers group
Pricing and promotionsVerify price addition rules, pricing policies, and voucher eligibilityFares and multi-level markup
Cash flow and creditCheck agency deposit balance, query the debt ledger, and view transaction historyMoney: balance, credit limit and debt
Sub-organization managementCreate, update, and manage sub-agencies with authority to delete child organizationsAuthentication with an API key
Notifications and eventsRegister webhook URLs for status change notifications, trigger booking emailsWebhooks

To protect system integrity and operational safety, the following areas are strictly blocked from API key calls:

Blocked areaTechnical reasonAlternative approach
Entire internal and admin tiersRequires user authentication via JWTPerform actions on the Dashboard interface
Real-time event stream (SSE)Requires an active user JWT sessionUse Webhooks or periodic polling
Electronic invoice managementPartner-tier endpoint is completely closedReceive webhook notifications, inspect details on Dashboard
Booking Zalo ZNS messagesAlways returns 403 Forbidden because permission schema lacks API key roleSend ZNS independently from partner’s system
Creating and issuing new API keysRestricted to agency administrators on DashboardAgency administrators create keys under API Keys
Global system searchRestricted to operations staff on the interfaceQuery specific entities directly (voyages, bookings, customers)

Additional note: The booking listing endpoint (GET /api/v1/bookings) returns a deprecation warning header when passing dynamic filters; no replacement route is currently offered in the partner tier.

A Ferry API key is bound to one specific agency organization. When invoking APIs with this key, all actions and generated data belong to that organization.

Important security implications:

  • Server-side secrecy: Never embed an API key into mobile app binaries, client-side browser JavaScript, or public repositories.
  • Child-organization deletion risk: Key permissions include deleting child organizations within your agency hierarchy. A compromised key can be exploited to delete child organizations or manipulate transactions and customer data.
  • Compromise response: If key exposure is suspected, immediately revoke the old key and create a new one on the Dashboard following the safe rotation workflow.
MisconceptionRealityCorrect practice
Assuming all routes in the docs can be called with an API keyThe public docs mix unauthenticated routes and administrative routesCross-reference with the 86 partner routes
Searching for authenticated endpoints for routes, locations, and operatorsShared catalogs exist only in the public tier without authenticationCall public routes directly without the Authorization header
Attempting to send Zalo ZNS via Ferry APIAlways returns 403 Forbidden due to missing permissions for API keysImplement independent ZNS delivery from your own system
Attempting to inspect invoice details via API after receiving webhooksPartner-tier invoice endpoint is completely closedInspect invoice data through the Dashboard interface
Issuing tickets through the Orders groupThe Orders group only supports reading order detailsPerform complete booking and ticket issuance through the Bookings group
Embedding an API key inside end-user mobile appsAnyone decompiling the mobile package can extract the key and delete child organizationsRoute all Ferry calls through your secure backend server
Searching for an API endpoint to generate API keys programmaticallyKey generation is restricted to the web DashboardAn agency administrator creates keys manually in the Dashboard
Attempting to connect to the SSE stream using an API keyThe SSE channel strictly requires a user JWTRegister a webhook endpoint to receive order status updates

This guide maps each functional group to the corresponding section on the Scalar UI — Ferry VN API interactive portal:

Business domainGroup name on Scalar
Voyages, seat layouts, and seat countsVoyages, Boat Layout, Voyage Counts
Bookings and order detailsBookings, Orders
Price additions and vouchersTicket Price Additions, Vouchers
Payment transactions and debt ledgersTransactions, Debt Ledgers
Customer, company, and organization profilesCustomers, Companies, Organizations
Public catalogs (routes, locations, operators)Routes, Locations, Operators
GuideRecommended next reading
Getting started: from zero to the first booking10 practical steps from key setup to issuing your first ticket
EnvironmentsLearn about the UAT and Production environments before calling endpoints
Authentication with an API keyHeader format rules, key structure, and safe rotation procedures
General conventionsGuidelines on cursor pagination, timestamp standards, and error handling