Skip to content

Ticket issuance and order legs

6 min read

Confirming ticket issuance is the step that turns a tentative booking into valid electronic tickets on the ferry operator’s booking engine. Prior to this step, the operator has no record of the order and the passenger has no guaranteed seat; once completed, tickets are issued and passengers are clear to board.

PrerequisiteBusiness contextReference
Valid API keyAll ticket confirmation and file retrieval calls require partner authenticationAuthentication with an API key
Booking in Requested statusOrder must already be created and sitting in Requested status (2)The booking flow
Adequate available balanceAccount balance or credit limit across the org hierarchy must cover the NET ratePayments and balances
Verified operator capabilityVerify whether the target operator supports automated electronic ticketingSee operator capabilities list below
Webhook endpoint configuredRegister event URLs to receive immediate issuance notificationsWebhooks and events

UAT can still place real orders and incur real charges. One operator always books for real in both UAT and Production, even when booking is configured off. Review Environments before testing ticket confirmation.

The diagram below illustrates the sequence of actions that occur when confirming ticket issuance:

sequenceDiagram
autonumber
participant P as "Your system"
participant API as "Ferry API"
participant MONEY as "Balance check"
participant OP as "Operator"
participant WH as "Webhook"
P->>API: "Confirm issuance (POST /bookings/confirmToIssue/{id})"
API->>API: "Verify 5 req/60s ceiling and 600s lock"
API->>MONEY: "Check balance and credit limits"
alt Insufficient funds
MONEY-->>API: "Insufficient balance"
API-->>P: "HTTP 422 insufficient balance"
else Sufficient funds
MONEY-->>API: "Hold funds at partner NET rate"
API->>OP: "Submit ticket order to operator"
alt Operator issues tickets successfully
OP-->>API: "Return electronic ticket identifiers"
API->>WH: "Dispatch booking.issuedTicket"
API-->>P: "Booking transitions to Issued (10)"
else Operator rejects or encounters error
OP-->>API: "Report issuance error"
API->>MONEY: "Release held funds"
API->>WH: "Dispatch booking.issuedTicketError"
API-->>P: "Booking transitions to Issue Error (6)"
end
end

The table below summarizes the actions at each step:

StepYour systemFerry APIPartner takeaway
1Call confirm ticket issuanceEnforces rate limits (max 5 requests per 60 seconds)Avoid rapid-fire retries while previous call executes
2Await execution lockSecures a 600-second lock on the bookingConcurrent calls return HTTP 422 processing error
3Await balance check and holdTemporarily reserves funds based on partner NET rateInsufficient credit at any ancestor tier halts issuance
4Await operator communicationInvokes operator engine to reserve ticketsProcessing latency varies by operator engine
5Receive response or poll statusAdvances booking to status 10 upon completionUse periodic polling as your final verification checkpoint
6Download electronic ticketsProvides download URLs for operator ticket documentsDeliver finalized e-tickets to passengers

The per-booking lock prevents concurrent issuance processes, but it is not an idempotency key for the entire call. There is no advance notification of lock expiry. If balance checks fail, funds already held are released; after issuance failure, refund timing is not guaranteed. Background reconciliation skips bookings already at status 10, so finalizing that state is safe to repeat.

The flowchart below outlines how to verify issuance outcomes accurately:

flowchart TD
A["Call ticket confirmation endpoint"] --> B{"Response outcome"}
B -- "Success" --> C["Booking transitions to status 10"]
B -- "Error reported" --> D["Inspect error code to retry or abort"]
B -- "Timeout / Processing" --> E["Switch to periodic verification"]
E --> F["Receive ticket issued webhook event"]
E --> G["Poll booking details API"]
F --> G
G --> H{"Booking status"}
H -- "Status 10 (Issued)" --> C
H -- "Other status" --> I["Await background reconciliation or contact Ferry"]
C --> J["Download tickets and deliver to passenger"]

Coordinating Webhooks and Polling:

  • Webhooks as signals: Webhooks provide low-latency notifications as soon as tickets are issued, allowing prompt UI updates. However, webhooks can occasionally be lost due to network transit issues.
  • Polling as the source of truth: Calling the booking detail API (GET /bookings/{id}) is the authoritative verification. When the status is 10 (Issued), tickets are confirmed on the carrier system.
  • Automated background reconciliation: If communication drops while the operator is processing, Ferry’s background worker reconciles with the operator and updates the order status within a few minutes.

Partial issuance failures on multi-leg bookings

Section titled “Partial issuance failures on multi-leg bookings”

On round-trip or multi-leg bookings, one leg may issue successfully while a subsequent leg is rejected by the operator:

  • The booking does not transition to status 10; it retains an error state.
  • Your balance is partially debited for the leg that issued successfully, while the failed leg amount is refunded.
  • Resolution procedure: Inspect individual leg orders inside the booking (GET /bookings/{id}) to identify issued legs, then contact Ferry with the booking code. Do not create replacement bookings or retry confirmation to repair a partial failure: confirmation reruns the entire chain, not just the missing leg.

Ferry recalculates all fare components at the moment ticket confirmation is called rather than locking in search-time prices. If operator tariffs or addition rules have changed, the actual debited amount will reflect the latest recalculation. See Ticket pricing and multi-level markup.

On the partner integration tier, you cannot create or confirm orders directly via the Orders API group. The entire order lifecycle must be driven through the Bookings group. The Orders group is provided solely to inspect details of individual leg orders.

Partners also have no invoice read API, despite receiving events such as invoice.created, invoice.updated, invoice.published, and invoice.failed. Do not design an invoice event handler that depends on fetching invoice details through the partner API; see Webhooks.

Nine automated operators, four manual operators

Section titled “Nine automated operators, four manual operators”

Among the 13 ferry operators connected to Ferry:

  • 9 operators support automated issuance: Confirmation calls communicate with the operator engine and issue tickets when processing succeeds. Some operators can take 5–8 minutes; automated issuance does not mean an immediate response.
  • 4 operators lack automated connector APIs: Binh An Ha Tien, Thanh Thoi, Hang Chau Tourist, and Saigon WaterGo. Bookings for these operators can be created, but confirming ticket issuance returns an unimplemented error. Partners should filter out these carriers or arrange manual booking with Ferry operations.

When passengers lose their tickets or require re-delivery via email, call the ticket download endpoint (GET /bookings/{id}/tickets). This retrieves copies of previously issued ticket files without issuing new tickets or incurring charges.

SymptomProbable causeRecommended actionRetry safe
HTTP 422 reported as processing600-second lock currently held for this bookingWait several minutes and poll booking statusYes, after waiting
Cooldown error (exceeded 5 req/60s)Sent repeated confirmation attempts in rapid successionBack off and wait for the 60-second window to clearYes, after 60 seconds
Insufficient balance errorPartner account or an upstream parent lacks creditTop up balance or request credit increase from parentYes, after funding
Unimplemented connector errorVoyage belongs to one of the 4 manual operatorsCancel booking and arrange ticketing via Ferry operationsDo not retry via API
Request hangs without respondingOperator engine connection slow (takes 5–8 minutes)Do not abort; switch to periodic status pollingDo not issue new call
Booking failed but balance partially debitedPartial issuance failure on a multi-leg bookingInspect individual leg orders and contact Ferry supportDo not create duplicate

To inspect exact request schemas and test calls directly, open the Scalar UI under the relevant tags:

CapabilityScalar tag
Confirm ticket issuance and download ticketsBookings
Inspect list and details of individual leg ordersOrders
View passenger details linked to ticketsCustomers

For instructions on configuring your API key in Scalar, see API Reference.

PageRelated topic
The booking flowBooking lifecycle and payment timers
Payments and balancesBalance deduction mechanics and credit limits
Webhooks and eventsReal-time event notifications for ticket issuance
Cancellation and refundTicket cancellation procedures and refund terms
EnvironmentsTicketing behavior differences in the UAT sandbox