- Developers
- The booking flow: lifecycle of a booking
The booking flow: lifecycle of a booking
The booking flow is the central business process of partner integration, consisting of two primary stages: creating a booking to register passenger and seat details, and confirming ticket issuance to debit funds and reserve physical seats on the ferry operator’s booking engine. Ferry does not maintain an independent temporary hold on the operator engine; seats belong firmly to passengers only upon successful ticket confirmation.
Prerequisites before starting
Section titled “Prerequisites before starting”| Prerequisite | Business context | Reference |
|---|---|---|
| Valid API key | All booking creation and management operations require partner authentication | Authentication with an API key |
| Voyage and seat details | You need the voyage code, departure date, and selected seat identifiers | Voyage search and remaining seats |
| Knowledge of your partner NET rate | The exact amount debited upon confirming ticket issuance | Ticket pricing and multi-level markup |
| Available organization balance | Your account and all upstream ancestors must have sufficient balance or credit | Payments and balances |
| Webhook configuration (recommended) | Register callback endpoints to receive real-time ticket issuance events | Webhooks and events |
Integration steps
Section titled “Integration steps”The diagram below illustrates the interaction sequence when creating and confirming a booking:
sequenceDiagram participant A as "Your system" participant B as "Ferry API" participant M as "Financial ledger" participant O as "Operator system" A->>B: "Create new booking (POST /bookings)" B-->>A: "Booking ID, Requested status (2)" Note over A,B: "Order created, no funds debited yet, payment timer started" A->>B: "Confirm issuance (POST /bookings/confirmToIssue/{id})" B->>M: "Verify balance and credit limit along org chain" alt Insufficient funds M-->>B: "Insufficient balance" B-->>A: "Balance error, booking remains in status 2" else Sufficient funds M-->>B: "Hold funds based on partner NET rate" B->>O: "Submit ticket issuance request to operator" alt Operator issues tickets successfully O-->>B: "Operator electronic ticket codes" B-->>A: "Booking transitions to Issued (10)" else Operator rejects or encounters error O-->>B: "Issuance error response" B-->>A: "Booking transitions to Issue Error (6), funds refunded" end endThe table below summarizes the actions at each step:
| Step | Your system | Ferry API | Partner takeaway |
|---|---|---|---|
| 1 | Search voyage and inspect layout | Returns schedules and deck seat statuses | Re-check seat availability right before booking |
| 2 | Call booking creation endpoint | Creates booking record and attaches payment timer | Receives booking ID in Requested status (2) |
| 3 | Check balance and payment deadline | Monitors allocated payment deadline | Ensure available balance covers partner NET rate |
| 4 | Call ticket confirmation endpoint | Locks booking, holds funds, calls operator | Execution may take several minutes depending on operator |
| 5 | Poll booking status | Returns latest updated order state | Continue periodic polling until a terminal state is reached |
| 6 | Download tickets and deliver to user | Provides download URLs for issued e-tickets | Execute once the booking transitions to status 10 |
Booking status lifecycle
Section titled “Booking status lifecycle”The business status of a booking tracks order progression from initial submission to final completion or cancellation.
The diagram below illustrates the state transitions of a booking:
stateDiagram-v2 state "Draft (0)" as s0 state "Requested (2)" as s2 state "Issue Error (6)" as s6 state "Expired (8)" as s8 state "Issued (10)" as s10 state "Cancel Requested (12)" as s12 state "Cancelled (14)" as s14 state "Trip Cancelled (16)" as s16 [*] --> s0 s0 --> s2: Booking creation call s2 --> s10: Ticket issuance confirmed s2 --> s6: Operator reports error s2 --> s8: Every order in the booking is cancelled s2 --> s14: Cancelled before issuance s10 --> s12: Cancellation request submitted s12 --> s14: Cancellation approved s10 --> s16: Operator cancels departure s8 --> [*] s14 --> [*] s16 --> [*]Meaning of booking statuses:
| Code | Status | Meaning and next action |
|---|---|---|
| 0 | Draft | Internal draft, not exposed on the partner tier. |
| 2 | Requested | Order created, seats marked in Ferry; await confirmation before payment deadline. |
| 6 | Issue Error | Operator rejected issuance or connection timed out; funds refunded; retry possible. |
| 8 | Expired | Every order in the booking has been cancelled; seats are released. Create a new booking if the customer still needs one. |
| 10 | Issued | Tickets successfully issued on the operator system; deliver e-tickets to passenger. |
| 12 | Cancel Requested | Ticket cancellation request under review; see Cancellation and refund. |
| 14 | Cancelled | Order cancellation completed; refunded money credited back to agency account. |
| 16 | Trip Cancelled | Operator cancelled voyage due to weather or technical reasons; assist with refund or exchange. |
Booking payment statuses
Section titled “Booking payment statuses”Alongside the business status, each booking maintains an independent payment status axis:
The diagram below shows the payment states of a booking:
stateDiagram-v2 state "Unpaid (1)" as p1 state "Partially Paid (3)" as p3 state "Paid (4)" as p4 state "Paid with Debt (5)" as p5 state "Refunded (18)" as p18 state "Cancelled (30)" as p30 [*] --> p1 p1 --> p4: Issuance confirmed successfully p1 --> p3: Partial payment received p3 --> p4: Outstanding balance settled p1 --> p5: Upstream partner extends credit p5 --> p4: Debt fully repaid p4 --> p18: Funds refunded after cancellation p1 --> p30: Booking cancelled while unpaid p4 --> p30: Booking cancelled after payment- Unpaid (1): Default state upon booking creation.
- Partially Paid (3): A partial payment through the banking channel; ticket confirmation does not produce this status.
- Paid (4): Funds debited successfully during ticket confirmation or debt settled.
- Paid with Debt (5): Upstream parent organization authorized debt to issue tickets in advance. Once the debt is settled, Ferry automatically changes payment status from 5 to 4 without a partner call.
- Refunded (18): Money refunded to agency balance following cancellation approval.
- Cancelled (30): Payment transaction cancelled.
Integration invariants and rules
Section titled “Integration invariants and rules”Seat reservation scope
Section titled “Seat reservation scope”Ferry does not hold seats on the operator booking engine while a passenger enters their details:
- When a booking is created (status 2), Ferry marks the seats in its internal seat map to prevent other Ferry users from selecting them.
- The ferry operator and other direct agents of the operator can still sell those seats until your confirmation call successfully executes against the operator.
- Seats firmly belong to your passenger only when the booking transitions to Issued (10).
Payment deadlines
Section titled “Payment deadlines”The payment deadline (payment_expired_at) equals the creation time plus the smaller of your organization’s configured payment window, expressed in hours and converted to minutes, and the minutes remaining until the earliest departure among the booking’s legs. Without an organization setting, the deadline equals that departure time. You can filter bookings by payment_expired_at_from and payment_expired_at_to.
A scheduled task processes overdue unpaid bookings. Status 8 means every order in the booking has been cancelled; do not infer it from the deadline alone.
Background processing of overdue unpaid bookings does not send partners an advance notification. Read payment_expired_at and schedule customer reminders yourself.
Handling timeouts during booking creation (No Idempotency)
Section titled “Handling timeouts during booking creation (No Idempotency)”Ferry does not support idempotency keys on booking creation. Sending POST /bookings twice creates two separate bookings with two distinct booking codes.
Standard procedure on network timeout or disconnect:
- Never immediately issue a fresh creation call.
- Query the booking list API, filtering by passenger phone number, voyage code, and departure date.
- If a matching booking is found, use its booking ID and proceed directly to confirmation.
- Only create a new booking if you are certain the original call never reached the system.
Lock windows and confirmation cooldowns
Section titled “Lock windows and confirmation cooldowns”When calling ticket confirmation:
- Ferry acquires an internal execution lock for up to 600 seconds per booking to prevent duplicate processing. Retrying while issuance is running returns HTTP 422 (“processing”).
- A cooldown ceiling allows at most 5 confirmation attempts per 60 seconds per booking. Exceeding this temporarily rejects requests.
- For certain operators, issuance can take 5–8 minutes. Set your client timeout accordingly or rely on periodic polling of the booking status.
The payment lock lasts 180 seconds. A confirmation retried while work is in progress does not replay the first call’s result. The soft per-booking confirmation limit returns a business error rather than HTTP 429. Webhooks time out after 2 seconds and are not retried, so polling remains the final confirmation. Real-time push requires a logged-in user’s JWT and cannot replace polling for API-key integrations.
Automated reconciliation of pending bookings
Section titled “Automated reconciliation of pending bookings”If a booking has been debited but ticket response from the operator was interrupted, Ferry’s background reconciliation workers automatically verify the status with the operator and advance the booking to Issued (10) within several minutes. In this situation, avoid creating replacement orders or initiating cancellations prematurely.
Operators without automated ticketing
Section titled “Operators without automated ticketing”Four operators in the directory do not currently support automated electronic ticket issuance via API: Binh An Ha Tien, Thanh Thoi, Hang Chau Tourist, and Saigon WaterGo. Bookings for these operators can be created, but the confirmation call will return an error. See Ticket issuance.
- Orders are read-only for partners: Use
/ordersto list and inspect individual legs. Create and confirm tickets through/bookings, not through the order group. - Seat conflicts: SuperDong can return
UnavailableSeatswhen another operator-side agent takes a seat between booking creation and confirmation. - Partial issuance: Some legs can succeed while others fail. Ferry flags the partial result and refunds the failed legs; do not assume every leg has the same outcome.
- Booking list limits: Pages are silently capped at 50, only
_idsorting is supported, and an internal failure can return HTTP 200 with an empty list. Alert on unexpectedly empty results. - Dynamic filters: The booking list returns a deprecation warning. Dynamic filters can still apply to allowed fields, but there is no partner-tier replacement group; do not depend on these filters. See Conventions.
- Status number collision: Booking status 6 means issuance failed; order status 6 has a different meaning and is currently unused. Identify which resource owns a status before interpreting it.
Common errors and remedies
Section titled “Common errors and remedies”| Symptom | Probable cause | Recommended action | Retry safe |
|---|---|---|---|
| HTTP 422 on booking creation | Missing required fields or invalid passenger payload format | Inspect response error details, correct data, and re-send | Yes, after correcting payload |
| Network disconnect during creation | Network drop or slow upstream response | Query bookings by phone and voyage before creating anew | Do not re-create immediately |
| HTTP 422 reported as processing | Issuance lock currently held for this booking | Wait several minutes and poll booking status | Wait and poll status |
| Rate limit error on confirmation | Exceeded 5 confirmation attempts within 60 seconds | Back off and wait for the 60-second window to clear | Yes, after cooldown |
| Insufficient balance error on confirmation | Organization balance or credit limit insufficient | Top up agency balance or request credit increase upstream | Yes, after funds are available |
| Status Issue Error (code 6) | Operator rejected order or operator connection timed out | Inspect operator error message; correct data and re-confirm | Yes, if error allows retry |
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 |
|---|---|
| Create bookings, confirm issuance, view details, download tickets | Bookings |
| Manage passenger information attached to orders | Customers |
| Inspect details of individual leg orders in a booking | Orders |
For instructions on configuring your API key in Scalar, see API Reference.
Read next
Section titled “Read next”| Page | Related topic |
|---|---|
| Voyage search and remaining seats | Discovering voyages and inspecting seat layouts |
| Ticket pricing and multi-level markup | Organization markup rules and price components |
| Payments and balances | Balance deduction mechanics and credit limits |
| Ticket issuance | Detailed execution of electronic ticket issuance |
| Cancellation and refund | Submitting cancellation requests and refund policies |
| Webhooks and events | Real-time event notifications for booking status changes |