- Developers
- Getting started: from zero to the first booking
Getting started: from zero to the first booking
This page provides a step-by-step checklist for developers integrating with Ferry from initial setup to issuing the first ferry ticket. Following these steps sequentially ensures smooth integration and prevents service disruption.
10-step integration roadmap
Section titled “10-step integration roadmap”The diagram below illustrates the 10-step journey from preparation to your first ticket:
flowchart TB subgraph prep["Preparation Phase"] s1["1. Identify organization in hierarchy"] s2["2. Receive API key from admin"] s3["3. Store key securely and set header"] s4["4. Select environment and get base URL"] end subgraph query["Data Retrieval Phase"] s5["5. Test voyage search call"] s6["6. Fetch seat layout and availability"] s7["7. Verify pricing and vouchers"] end subgraph trans["Transaction Phase"] s8["8. Top up agency deposit balance"] s9["9. Create reservation booking"] s10["10. Confirm ticket issuance and track status"] end s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9 --> s10Step-by-step guide
Section titled “Step-by-step guide”Step 1 — Identify your organization’s position in the agency hierarchy
Section titled “Step 1 — Identify your organization’s position in the agency hierarchy”What to do: Contact your Ferry representative to verify your agency organization details in the system. Clearly identify your direct parent organization to understand pricing policies, markup tiers, and bank account details for balance top-ups.
Done when: You know your organization ID, your direct parent organization, and the net pricing terms applicable to your agency.
Step 2 — Obtain an API key from your agency administrator
Section titled “Step 2 — Obtain an API key from your agency administrator”What to do: Partners cannot create keys via API. An agency user with the admin role must sign in to the web Dashboard, navigate to Settings > API Keys, generate a new key, and securely transfer it to the technical team. For detailed instructions, see API Key Management on Dashboard.
Done when: You possess the complete API key string. This key is displayed only once upon creation and cannot be retrieved later.
Keys are issued only to organizations with a partnership contract. Keys do not expire automatically; revocation is an immediate, irreversible hard deletion.
Step 3 — Store the key securely and configure authentication headers
Section titled “Step 3 — Store the key securely and configure authentication headers”What to do: Store the API key in a secure server-side secrets store or environment variable. Configure your HTTP client to attach the Authorization: Bearer <API_KEY> header to every outbound call to Ferry.
Done when: Your backend service reads the key from environment variables. The key string must never be committed to source code repositories or exposed in client-facing applications.
Ferry reads the key only through Authorization; X-API-Key has no effect. Keep the key out of logs and variables embedded into client builds.
Step 4 — Choose your environment and confirm the base URL
Section titled “Step 4 — Choose your environment and confirm the base URL”What to do: Request the official UAT base URL in writing from the Ferry team. Note the vital caveat: the UAT environment connects to live operator ticketing engines and issues real tickets. Agree in advance on which specific voyage to test with Ferry to prevent unwanted ticketing charges.
Done when: You hold the confirmed test environment base URL and an approved test voyage list.
CangSaKy still places real bookings even when real-ticket issuance mode is disabled for the environment. Agree with Ferry on the operator, voyage, and party responsible for each test’s costs.
Step 5 — Make a test voyage search call
Section titled “Step 5 — Make a test voyage search call”What to do: Send a GET request to the Voyages group searching for ferry sailings by departure terminal, arrival terminal, and departure date.
Done when: You receive an HTTP 200 response with an active list of real voyages. If you receive an HTTP 401, verify the Authorization header name and the Bearer prefix.
HTTP 200 with an empty list can hide a system failure; it does not prove there are no voyages. Try a pier pair and date known to have data before concluding. Sorting by fields other than _id falls back to descending _id; see Conventions.
Step 6 — Fetch seat layouts and seat availability
Section titled “Step 6 — Fetch seat layouts and seat availability”What to do: Using the voyage ID obtained in the previous step, call the Boat Layout group to retrieve cabin seating charts and the Voyage Counts group to check remaining seat counts per cabin class.
Done when: You have detailed information about valid vacant seat codes ready to submit in an order.
Availability changes continuously. Query Ferry again immediately before creating the booking; do not rely on a long-cached layout or derive remaining capacity yourself.
Step 7 — Verify pricing and discounts
Section titled “Step 7 — Verify pricing and discounts”What to do: Call the Ticket Price Additions group to review applicable surcharges or markup rules, and the Vouchers group to validate discount codes (if applicable).
Done when: You know both the retail price charged to end customers and the agency NET amount payable to your direct parent organization.
Step 8 — Top up agency deposit balance
Section titled “Step 8 — Top up agency deposit balance”What to do: Inspect your current balance via the Transactions or Debt Ledgers groups. Transfer funds following your parent organization’s payment instructions so that your available balance meets or exceeds the total order value.
Done when: Your agency’s available balance is sufficient to cover the order cost. Balance deduction occurs upon ticket confirmation.
Step 9 — Create a reservation booking
Section titled “Step 9 — Create a reservation booking”What to do: Call the Bookings group with voyage details, selected seat positions, and passenger identity details to create a tentative booking.
Done when: You have saved the booking ID, Requested status (2), Unpaid payment status (1), and payment_expired_at. Seats are marked within Ferry only, not reserved on the operator system.
Step 10 — Confirm ticket issuance and track status
Section titled “Step 10 — Confirm ticket issuance and track status”What to do: Call POST /bookings/confirmToIssue/{id}, then poll GET /bookings/{id} to confirm the outcome. Webhooks are signals only: they have no signature, no retries, and a 2-second timeout. Do not replace polling with webhook delivery.
Done when: The booking reaches Issued status (10); then download the tickets for the customer.
Confirmation can take 5–8 minutes with some operators. A timeout does not prove failure, and an in-progress error is not a reason to cancel. A paid booking may automatically reach status 10 after several minutes through background reconciliation. Do not rush to cancel or create a replacement; consult Booking flow and Rate limits before retrying.
10-step summary table
Section titled “10-step summary table”| Step | Location | Relevant API group | Done when |
|---|---|---|---|
| 1 | Ferry liaison | None (offline) | Parent organization and pricing tier confirmed |
| 2 | Agency Dashboard | None (offline) | Valid API key received |
| 3 | Your server | None (offline) | Key stored in secret store with Bearer header set |
| 4 | Ferry liaison | None (offline) | UAT base URL and approved test voyage confirmed |
| 5 | Your server | Voyages | Real voyage list received (HTTP 200) |
| 6 | Your server | Boat Layout, Voyage Counts | Seat layout and valid vacant seats retrieved |
| 7 | Your server | Ticket Price Additions, Vouchers | Retail and wholesale pricing determined |
| 8 | Bank transfer | Transactions, Debt Ledgers | Available balance sufficient for order value |
| 9 | Your server | Bookings | Booking created with seat hold timestamp |
| 10 | Your server | Bookings | Ticket issuance confirmed and e-tickets received |
Common misconceptions
Section titled “Common misconceptions”| Misconception | Reality | Correct practice |
|---|---|---|
| Issuing test tickets freely in UAT | UAT connects to live operators and incurs real costs | Only test ticketing on voyages explicitly agreed with Ferry |
| Automatically retrying timed-out booking calls | Booking creation lacks automated deduplication | Check recent bookings before deciding to retry |
| Expecting balance deduction upon booking creation | Balance is only deducted upon ticket confirmation | Ensure balance is sufficient before triggering confirmation |
| Confusing retail prices with agency settlement prices | Different amounts depending on markup configurations | Always verify pricing via calculation APIs before checkout |
Where to look in Scalar
Section titled “Where to look in Scalar”The API groups required for these 10 steps are mapped on the Scalar UI — Ferry VN API:
| Workflow step | Scalar group |
|---|---|
| Step 5: Voyage search | Voyages |
| Step 6: Seat layout and counts | Boat Layout, Voyage Counts |
| Step 7: Price additions and vouchers | Ticket Price Additions, Vouchers |
| Step 8: Balances and debt ledgers | Transactions, Debt Ledgers |
| Steps 9 and 10: Booking and ticketing | Bookings, Orders |
Read next
Section titled “Read next”| Guide | Recommended next reading |
|---|---|
| Environments | Read operational differences and testing rules for UAT |
| Authentication with an API key | Key format, lifecycle, and safe rotation procedures |
| Voyage and seat lookup | Detailed guide on schedule search and seat layouts |
| Bookings: the life cycle of one booking | In-depth order handling workflow from creation to completion |