- Developers
- The ferry CLI
The ferry CLI
ferry is Ferry’s official command-line tool for people who work with the partner API without writing code: search voyages and prices, view seat maps, build a booking from a passenger list in Excel, then issue tickets or send a cancellation request. The CLI lives in the open-source repository ferry-vn/ferry-sdk and shares its core with the SDK.
Install
Section titled “Install”The CLI is on npm and needs Node.js 22.12 or later:
npm install -g @ferryvn/cliTo run it once without installing, use npx @ferryvn/cli <command>. Verify with ferry --version: it prints the CLI version together with the bundled SDK version, for example 1.0.0 (sdk 1.0.0). Pier lookups such as ferry locations "phu quoc" work even before you log in, because the pier catalogue is public data.
Log in and profiles
Section titled “Log in and profiles”ferry login asks you to paste the API key (hidden on screen), verifies the key with Ferry, and stores it in a profile. An agency admin creates the key in the Dashboard; see Authentication with an API key.
ferry loginferry whoami --checkferry doctorferry whoami --check confirms the key still works; ferry doctor checks configuration, connectivity, and the key.
To work against UAT, create a second profile with a UAT key and pick the profile when you run a command:
ferry login --profile uat --env uatferry --profile uat voyages search --from "Rạch Giá" --to "Phú Quốc" --date tomorrowferry profiles use uatUAT is not a sandbox: issuing tickets there still books real tickets and spends real money; see Environments. When settings overlap, the order of priority is command-line flags, then environment variables (FERRY_PROFILE, FERRY_ENV, FERRY_API_KEY), then the profile, and finally production. Avoid --api-key because flags stay in your shell history.
Main workflow
Section titled “Main workflow”The usual flow goes from lookup to ticket issuance. The lookup commands only read data; creating a booking, issuing tickets, and cancelling write data:
ferry voyages search --from "Rạch Giá" --to "Phú Quốc" --date tomorrowferry calendar --from "Rạch Giá" --to "Phú Quốc" --days 14ferry prices --from "Rạch Giá" --to "Phú Quốc" --date 2026-11-01 --live 3ferry seats <voyageId>ferry customers --search 0901234567ferry booking draft --customer 1001 --orderer-name "Nguyễn Văn A" --email a@example.com \ --voyage <voyageId> --seats A1,A2 --passengers khach.csv --out booking.jsonferry booking create --file booking.jsonferry booking issue <id>- Look up voyages, calendar, and prices:
voyages searchfinds voyages;calendarshows how many voyages run each day;pricesshows selling prices per voyage, seat type, and ticket type (--live 3re-prices the first 3 voyages from their seat maps; otherwise prices can lag the operator). - Check seats and customers:
seatslists the free seats of a voyage;customers --searchfinds a customer from the text you type, for example a phone number, and gives the customer id (--customer) used when building the booking. - Build a draft booking:
booking drafttakes seat names and a passenger list, picks each ticket type from age using the operator’s rules, matches prices, checks seats and duplicate ID numbers, and writes the result tobooking.json. Nothing is sent. - Create the booking:
booking create --file booking.jsonsends the booking; alternatively add--createtobooking draftto do both steps at once. Add--dry-runto only validate. Creating a booking attaches the seats and passengers to it and charges nothing; the booking is Requested and unpaid, with a payment deadline (see Bookings). - Issue tickets:
booking issue <id>charges the balance and credit and then orders real tickets from the operator. The command asks for confirmation: the--yesflag, or typing the booking id back on an interactive terminal; before you confirm, the CLI prints the total and your reservable credit. With automated operators this step can take minutes. - Cancel tickets:
ferry cancel request --order <id> --positions 101,102 --reason "…"holds the cancellation fee immediately and marks the tickets cancelled; it asks for confirmation just like issuance.
The remaining commands are booking get, booking list, booking tickets, orders, cancel list, account, transactions, debts, vouchers, and disruptions. The ferry api command sends a raw request with your credentials and asks before sending a write. The full list of flags is in the CLI package README.
Passenger CSV file
Section titled “Passenger CSV file”booking draft reads a CSV exported from Excel or Google Sheets, or a JSON file. Example CSV:
name,date_of_birth,social_id,home_town,genderNguyễn Văn A,1990-05-01,079090000001,Cần Thơ,namNguyễn Văn B,2018-03-02,079090000001,Cần Thơ,nam| Column | Meaning |
|---|---|
name | Passenger’s full name (the headers ho_ten or Họ tên are accepted) |
date_of_birth | Date of birth as YYYY-MM-DD (ngay_sinh or Ngày sinh accepted) |
social_id | National ID or passport number (cccd or Số CCCD accepted) |
home_town | Home town (que_quan accepted) |
gender | male or female, nam or nữ, 1 or 0 (gioi_tinh accepted) |
national_id | Optional; defaults to Vietnam; list the values with ferry operators nationals |
ticket_type_id | Optional; by default chosen from age |
plate_number, passport_expired_at | Optional; vehicle plate and passport expiry date |
When you save from Excel, choose CSV UTF-8 so Vietnamese text is not corrupted; the CLI refuses files that are not UTF-8 and points you to this format. The separator is ,, or ; when the header row uses semicolons (Excel with a Vietnamese locale). ID numbers must differ between passengers, except on the child ticket types that the operator exempts.
Output formats
Section titled “Output formats”The --output flag (short -o) accepts table, json, ndjson, or csv; --json is a shorthand. CSV output carries a UTF-8 BOM so Excel opens Vietnamese text correctly, and cells that start like a formula are neutralised to prevent formula injection. Example exports of pending bookings and transactions for accounting:
ferry booking list --status Requested --output csv > don.csvferry transactions --output csv > giao-dich.csvUse --all to fetch every page instead of the first. Other shared flags are --timeout, --base-url, and --debug (writes the HTTP log to stderr with the key redacted).
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | API, server, or network error (also doctor with failed checks) |
| 2 | Usage error: bad flags, invalid input, or you did not confirm |
| 3 | Authentication or permission: 401, 403 |
| 4 | Not found: 404 |
| 5 | Rate limited: 429 |
Config location
Section titled “Config location”Profiles and keys live in a config.json file with mode 0600:
| Operating system | Directory |
|---|---|
| Linux | ~/.config/ferry/ (honours XDG_CONFIG_HOME when set) |
| macOS | ~/Library/Application Support/ferry/ |
| Windows | %APPDATA%\ferry\ |
Set the FERRY_CONFIG_DIR variable to use another directory.
Common mistakes
Section titled “Common mistakes”| Misconception | Reality | Correct practice |
|---|---|---|
| One profile can serve both UAT and production | The two environments need two keys | ferry login --profile uat --env uat, then pick it with --profile |
| UAT is as safe as a sandbox | Issuing on UAT places real orders and spends real money | Only issue on voyages agreed with Ferry |
booking draft already created the booking | By default it only writes a draft file | Add --create or run booking create once you have checked the draft |
| Saving the CSV from Excel in the default encoding | The CLI refuses files that are not UTF-8 | Choose CSV UTF-8 when saving |
Re-running booking create after a network error | The API has no idempotency key, a rerun can create a second order | Run ferry booking list --search … to check first |
Typing the key with --api-key | Shell history keeps the key | Use ferry login or the FERRY_API_KEY variable |
Where to look in Scalar
Section titled “Where to look in Scalar”The full list of commands and flags is in the CLI package README on GitHub; the repository also ships sample files examples/passengers.csv and examples/booking.json. The raw HTTP reference is on Scalar UI.
| What to look up | Where |
|---|---|
| Commands and flags | The CLI package README on GitHub |
| Sample CSV and JSON files | The examples folder of the ferry-sdk repository |
| HTTP routes and schemas behind each command | Scalar, groups Bookings, Voyages, Cancel Ticket Requests |
Read next
Section titled “Read next”| Page | When to read |
|---|---|
| TypeScript SDK | The same booking-building logic when you want to write code |
| The booking flow | Understand the booking states the commands produce |
| Ticket issuance | Understand what happens when you run booking issue |
| Cancellation and refunds | Understand the consequences of cancel request |