@agenzo/merchant-cli 0.8.13 → 0.8.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +343 -343
- package/dist/index.js +58 -15
- package/dist/index.js.map +1 -1
- package/package.json +28 -28
package/README.md
CHANGED
|
@@ -1,343 +1,343 @@
|
|
|
1
|
-
# @agenzo/merchant-cli
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/@agenzo/merchant-cli) [](../../LICENSE) 
|
|
4
|
-
|
|
5
|
-
> **Merchant-fulfillment CLI** for the Agenzo platform — binary `agenzo-merchant-cli`.
|
|
6
|
-
> Agents fulfill commerce services here. Each capability is a noun and the set grows over time — use `services` to discover what's available; today's capabilities are ride-hailing (`ride-elife`) and hotel booking (`hotel-redaug`).
|
|
7
|
-
|
|
8
|
-
**[Overview](#overview)** · **[Features](#features)** · **[Quick Start](#quick-start)** · **[Global flags](#global-flags)** · **[Errors](#output-and-error-contract)** · **[Idempotency-Key](#idempotency-key)**
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Overview
|
|
13
|
-
|
|
14
|
-
`agenzo-merchant-cli` is the command-line entry point for Agents to fulfill commerce services on the Agenzo platform. Each fulfillment capability is exposed as a **noun**, and the set grows over time:
|
|
15
|
-
|
|
16
|
-
- **`services`** (capability discovery): list what's currently available and how to call it — run this first to learn the current capability set.
|
|
17
|
-
- **`ride-elife`** (ride-hailing): the full loop of quote → book → query/poll → cancel → list-orders.
|
|
18
|
-
- **`hotel-redaug`** (hotel booking): search, find-destination, hotel-filters, list-cities, hotel-detail, quote, create-order, pay-order, get (status/poll), cancel, checkout, get-checkout, list-orders. Supports both **monthly_settlement** (on-account deduction) and **pay_per_call** (user pays via EVO using the order_id as the merchantTransID).
|
|
19
|
-
|
|
20
|
-
More fulfillment capabilities are added as new nouns over time; `services list` always reflects the current set.
|
|
21
|
-
|
|
22
|
-
## Features
|
|
23
|
-
|
|
24
|
-
| Noun | Verb | Type | HTTP | Description |
|
|
25
|
-
|---|---|---|---|---|
|
|
26
|
-
| `services` | `list` | Read | — (local) | List available merchant-fulfillment capabilities |
|
|
27
|
-
| `services` | `get <service-id>` | Read | — (local) | View the full metadata of a single capability (miss → `SERVICE_NOT_FOUND`) |
|
|
28
|
-
| `ride-elife` | `quote` | Read | `POST /ride/quote` | Point-to-point quote (`vehicle_classes[]` + meet-and-greet) |
|
|
29
|
-
| `ride-elife` | `book` | Write/Y | `POST /ride/book` | Book against a quote (monthly_settlement-aware, see below) |
|
|
30
|
-
| `ride-elife` | `get` | Read | `GET /ride/<id>/status` | Query order status; `--watch` emits an NDJSON polling stream |
|
|
31
|
-
| `ride-elife` | `cancel` | Write/Y | `POST /ride/<id>/cancel` | Cancel an order (no body, may incur a fee) |
|
|
32
|
-
| `ride-elife` | `list-orders` | Read | `GET /ride/orders` | List booked trips (pagination + filtering) |
|
|
33
|
-
| `hotel-redaug` | `search` | Read | `POST /hotel/search` | Search hotels by coordinates or destination-id + stay dates + filters |
|
|
34
|
-
| `hotel-redaug` | `find-destination` | Read | `POST /hotel/find-destination` | Resolve free-text to destinations (destination_id + coordinates) |
|
|
35
|
-
| `hotel-redaug` | `hotel-filters` | Read | `POST /hotel/filters` | Get available filter options for a location (codes → search flags) |
|
|
36
|
-
| `hotel-redaug` | `list-cities` | Read | `POST /hotel/cities` | List cities for a country (destination_id + coordinates) |
|
|
37
|
-
| `hotel-redaug` | `hotel-detail` | Read | `POST /hotel/detail` | Hotel detail with facilities/images AND `rooms[]` (area/floor/beds/photos) — call before quote |
|
|
38
|
-
| `hotel-redaug` | `quote` | Read | `POST /hotel/quote` | Real-time rooms/rates for one hotel (`product_token` + `price_items`) |
|
|
39
|
-
| `hotel-redaug` | `create-order` | Write/Y | `POST /hotel/create-order` | Create a hotel order without charging (locks rate + returns `order_id` + payable amount) |
|
|
40
|
-
| `hotel-redaug` | `pay-order` | Write/Y | `POST /hotel/{order_id}/pay` | Pay for a created order (takes only `--order-id`); billing path (`monthly_settlement` or `pay_per_call`) is chosen server-side |
|
|
41
|
-
| `hotel-redaug` | `get` | Read | `GET /hotel/<id>/status` | Query order status; `--watch` emits an NDJSON polling stream |
|
|
42
|
-
| `hotel-redaug` | `cancel` | Write/Y | `POST /hotel/<id>/cancel` | Cancel a whole order (acceptance ≠ proof; poll `get`) |
|
|
43
|
-
| `hotel-redaug` | `checkout` | Write/Y | `POST /hotel/<id>/checkout` | Partial check-out / out-of-policy cancellation (async) |
|
|
44
|
-
| `hotel-redaug` | `get-checkout` | Read | `GET /hotel/checkout/<task_order_code>` | Poll a check-out application; `--watch` emits an NDJSON stream |
|
|
45
|
-
| `hotel-redaug` | `list-orders` | Read | `GET /hotel/orders` | List hotel orders (pagination + status filter) |
|
|
46
|
-
|
|
47
|
-
> Write commands (`ride-elife book` / `cancel`; `hotel-redaug create-order` / `pay-order` / `cancel` / `checkout`) are subject to the idempotency-key rules (see [Idempotency-Key](#idempotency-key)).
|
|
48
|
-
> Read status verbs `get` / `get-checkout` support `--watch` for NDJSON status polling.
|
|
49
|
-
> `ride-elife track` is not available — use `get --watch` for order-status polling.
|
|
50
|
-
|
|
51
|
-
## Quick Start
|
|
52
|
-
|
|
53
|
-
### Requirements
|
|
54
|
-
|
|
55
|
-
- Node.js 22+
|
|
56
|
-
|
|
57
|
-
### Installation
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
npm install -g @agenzo/merchant-cli
|
|
61
|
-
agenzo-merchant-cli --version
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Upgrade later with `npm install -g @agenzo/merchant-cli@latest`.
|
|
65
|
-
|
|
66
|
-
### Authentication
|
|
67
|
-
|
|
68
|
-
A runtime-plane CLI that uses an **API Key** (`--api-key`, carried per command as the `X-Api-Key` header):
|
|
69
|
-
|
|
70
|
-
- The API Key is issued by `agenzo-admin-cli keys create --scope merchant` and must include the `merchant` scope.
|
|
71
|
-
- When `--api-key` is omitted, it is requested interactively (password input).
|
|
72
|
-
- No Bearer Token or local keystore — every command carries the API Key.
|
|
73
|
-
|
|
74
|
-
### Ride-hailing end-to-end example
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
# 1. Discover capabilities
|
|
78
|
-
agenzo-merchant-cli services list
|
|
79
|
-
agenzo-merchant-cli services get ride-elife
|
|
80
|
-
|
|
81
|
-
# 2. Quote (produces quote_id)
|
|
82
|
-
agenzo-merchant-cli ride-elife quote --api-key "$API_KEY" \
|
|
83
|
-
--pickup-lat 37.7937 --pickup-lng -122.3956 --pickup-name "1 Market St" \
|
|
84
|
-
--dropoff-lat 37.6213 --dropoff-lng -122.3790 --dropoff-name "SFO Airport" \
|
|
85
|
-
--pickup-time now
|
|
86
|
-
|
|
87
|
-
# 3. Book (write op: --yes auto-confirms + --idempotency-key must be provided)
|
|
88
|
-
agenzo-merchant-cli ride-elife book --api-key "$API_KEY" --yes \
|
|
89
|
-
--quote-id "$QUOTE_ID" --vehicle-class Sedan --price-amount 42.50 \
|
|
90
|
-
--passenger-name "Alice" --passenger-phone "+14155551234" \
|
|
91
|
-
--idempotency-key "book-$(date +%s)"
|
|
92
|
-
|
|
93
|
-
# 4. Query / poll (--watch emits line-by-line NDJSON)
|
|
94
|
-
agenzo-merchant-cli ride-elife get --api-key "$API_KEY" --order-id "$RIDE_ID"
|
|
95
|
-
agenzo-merchant-cli ride-elife get --api-key "$API_KEY" --order-id "$RIDE_ID" \
|
|
96
|
-
--watch --watch-interval 5 --watch-timeout 600
|
|
97
|
-
|
|
98
|
-
# 5. List orders / cancel
|
|
99
|
-
agenzo-merchant-cli ride-elife list-orders --api-key "$API_KEY" --status Pending --page 1 --page-size 20
|
|
100
|
-
agenzo-merchant-cli ride-elife cancel --api-key "$API_KEY" --yes \
|
|
101
|
-
--order-id "$RIDE_ID" --idempotency-key "cancel-$(date +%s)"
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Hotel booking end-to-end example
|
|
105
|
-
|
|
106
|
-
The core Agent loop is `search → quote → create-order → pay-order → get`. Amounts are decimal currency
|
|
107
|
-
units (e.g. `320.00` = 320.00 yuan). **`create-order` settles payment AND locks the room** — the funds
|
|
108
|
-
path is chosen server-side by the developer's `billing_mode`:
|
|
109
|
-
|
|
110
|
-
- **monthly_settlement**: the total is deducted from the developer's monthly-settlement account balance.
|
|
111
|
-
- **pay_per_call**: the total is authorized + captured on the developer's bound card via the platform's own EVO integration (server-side; no EVO parameters pass through this CLI).
|
|
112
|
-
|
|
113
|
-
`pay-order` takes only `--order-id` and triggers supplier confirmation / ticket issuance — funds were
|
|
114
|
-
already settled in `create-order`, so both billing modes use the same `pay-order` call.
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
# 1. Search hotels by coordinates + stay dates (or use --destination-id from find-destination).
|
|
118
|
-
# Pick a hotels[].hotel_id from the result for the quote step.
|
|
119
|
-
agenzo-merchant-cli hotel-redaug search --api-key "$API_KEY" \
|
|
120
|
-
--lat 31.2304 --lng 121.4737 --distance 20 \
|
|
121
|
-
--check-in 2026-02-10 --check-out 2026-02-12 \
|
|
122
|
-
--adults 2 --children 0 --room-num 1
|
|
123
|
-
|
|
124
|
-
# 2. Quote one hotel (produces rates[].product_token, total_price, price_items)
|
|
125
|
-
agenzo-merchant-cli hotel-redaug quote --api-key "$API_KEY" \
|
|
126
|
-
--hotel-id "$HOTEL_ID" \
|
|
127
|
-
--check-in 2026-02-10 --check-out 2026-02-12 \
|
|
128
|
-
--adults 2 --room-num 1 --nationality CN
|
|
129
|
-
|
|
130
|
-
# 3. Create Order (write op: settles payment + locks the room; returns order_id + fc_order_code).
|
|
131
|
-
agenzo-merchant-cli hotel-redaug create-order --api-key "$API_KEY" --yes \
|
|
132
|
-
--product-token "$PRODUCT_TOKEN" \
|
|
133
|
-
--total-amount 640.00 --currency CNY \
|
|
134
|
-
--price-items '[{"sale_date":"2026-02-10","sale_price":320.00,"breakfast_num":2},{"sale_date":"2026-02-11","sale_price":320.00,"breakfast_num":2}]' \
|
|
135
|
-
--check-in 2026-02-10 --check-out 2026-02-12 \
|
|
136
|
-
--guest-name "Zhang San" --contact-name "Zhang San" \
|
|
137
|
-
--contact-phone "13800138000" --contact-country-code 86 \
|
|
138
|
-
--idempotency-key "hotel-create-$(date +%s)"
|
|
139
|
-
|
|
140
|
-
# 4a. Pay Order — monthly_settlement path (on-account)
|
|
141
|
-
agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
|
|
142
|
-
--order-id "$ORDER_ID" \
|
|
143
|
-
--idempotency-key "hotel-pay-$(date +%s)"
|
|
144
|
-
|
|
145
|
-
# 4b. Pay Order — pay_per_call path (funds already captured on the bound card in
|
|
146
|
-
# create-order; pay-order just triggers supplier confirmation). Same command.
|
|
147
|
-
agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
|
|
148
|
-
--order-id "$ORDER_ID" \
|
|
149
|
-
--idempotency-key "hotel-pay-$(date +%s)"
|
|
150
|
-
|
|
151
|
-
# 4c. Pay Order — pay_per_call with --watch (polls until PAID or timeout)
|
|
152
|
-
agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
|
|
153
|
-
--order-id "$ORDER_ID" \
|
|
154
|
-
--idempotency-key "hotel-pay-$(date +%s)" \
|
|
155
|
-
--watch --watch-interval 5 --watch-timeout 120
|
|
156
|
-
|
|
157
|
-
# 5. Query / poll status. create-order returns order_status=AWAITING_PAYMENT;
|
|
158
|
-
# after pay-order succeeds, status becomes PAID; poll get until CONFIRMED.
|
|
159
|
-
agenzo-merchant-cli hotel-redaug get --api-key "$API_KEY" --order-id "$ORDER_ID"
|
|
160
|
-
agenzo-merchant-cli hotel-redaug get --api-key "$API_KEY" --order-id "$ORDER_ID" \
|
|
161
|
-
--watch --watch-interval 5 --watch-timeout 600
|
|
162
|
-
|
|
163
|
-
# 6. List orders (pagination + optional status filter)
|
|
164
|
-
agenzo-merchant-cli hotel-redaug list-orders --api-key "$API_KEY" \
|
|
165
|
-
--status CONFIRMED --page 1 --page-size 20
|
|
166
|
-
|
|
167
|
-
# 7. Cancel a whole order (write op). Acceptance is NOT proof — poll get until CANCELLED.
|
|
168
|
-
agenzo-merchant-cli hotel-redaug cancel --api-key "$API_KEY" --yes \
|
|
169
|
-
--order-id "$ORDER_ID" --fc-order-code "$FC_ORDER_CODE" \
|
|
170
|
-
--reason "Change of plans" \
|
|
171
|
-
--idempotency-key "hotel-cancel-$(date +%s)"
|
|
172
|
-
|
|
173
|
-
# 8. Partial check-out / out-of-policy cancellation (write op, async).
|
|
174
|
-
# Returns task_order_code; poll get-checkout for the refund outcome.
|
|
175
|
-
agenzo-merchant-cli hotel-redaug checkout --api-key "$API_KEY" --yes \
|
|
176
|
-
--order-id "$ORDER_ID" --fc-order-code "$FC_ORDER_CODE" \
|
|
177
|
-
--reason "Guest departing early" \
|
|
178
|
-
--checkout-rooms '[{"room_index":"1","guest_name":"Zhang San","cancel_check_in_date":"2026-02-11"}]' \
|
|
179
|
-
--refund-type 1 \
|
|
180
|
-
--idempotency-key "hotel-checkout-$(date +%s)"
|
|
181
|
-
|
|
182
|
-
# 9. Poll the check-out application until a terminal refund status
|
|
183
|
-
agenzo-merchant-cli hotel-redaug get-checkout --api-key "$API_KEY" \
|
|
184
|
-
--task-order-code "$TASK_ORDER_CODE"
|
|
185
|
-
agenzo-merchant-cli hotel-redaug get-checkout --api-key "$API_KEY" \
|
|
186
|
-
--task-order-code "$TASK_ORDER_CODE" --watch --watch-interval 10 --watch-timeout 600
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### Flight booking end-to-end example (flight-flink)
|
|
190
|
-
|
|
191
|
-
The flow is `find-airport → search → verify → create-order → pay-order → get-order (poll until TICKETED)`.
|
|
192
|
-
Amounts are decimal currency units (e.g. `1200.00` = 1200.00 yuan). `create-order` locks the fare without
|
|
193
|
-
charging; `pay-order` settles + triggers ticketing (asynchronous — poll `get-order` until status=TICKETED).
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
# 1. Resolve a city/airport keyword to IATA codes.
|
|
197
|
-
agenzo-merchant-cli flight-flink find-airport --api-key "$API_KEY" --keyword "beijing"
|
|
198
|
-
|
|
199
|
-
# 2. Search one-way flights (trip-type 1=OW, 2=RT, 3=multi-city).
|
|
200
|
-
# journeys always carries ALL legs; for multi-city, relay --journey-id from each result.
|
|
201
|
-
agenzo-merchant-cli flight-flink search --api-key "$API_KEY" \
|
|
202
|
-
--trip-type 1 \
|
|
203
|
-
--journeys '[{"date":"2026-08-01","origin":"PEK","originType":"2","destination":"SHA","destinationType":"2"}]'
|
|
204
|
-
|
|
205
|
-
# 3. Verify price (returns authoritative product_token; if price_changed, re-confirm with user).
|
|
206
|
-
agenzo-merchant-cli flight-flink verify --api-key "$API_KEY" \
|
|
207
|
-
--product-token "$PRODUCT_TOKEN"
|
|
208
|
-
|
|
209
|
-
# 4. Create Order (write op: locks fare, NO charge; status → AWAITING_PAYMENT).
|
|
210
|
-
agenzo-merchant-cli flight-flink create-order --api-key "$API_KEY" --yes \
|
|
211
|
-
--product-token "$VERIFIED_TOKEN" \
|
|
212
|
-
--total-amount 1200.00 --currency CNY \
|
|
213
|
-
--contact-name "ZHANG SAN" --contact-region 86 \
|
|
214
|
-
--contact-phone "13800138000" --contact-email "a@example.com" \
|
|
215
|
-
--passengers '[{"firstName":"SAN","lastName":"ZHANG","gender":"1","birthday":"1990-01-01","id_type":"1","id_number":"E12345678","nationality":"CN","type":"adult","expiration":"2032-01-01"}]' \
|
|
216
|
-
--idempotency-key "flight-create-$(date +%s)"
|
|
217
|
-
|
|
218
|
-
# 5. Pay Order (settles + triggers ticketing; status → PAID).
|
|
219
|
-
agenzo-merchant-cli flight-flink pay-order --api-key "$API_KEY" --yes \
|
|
220
|
-
--order-no "$ORDER_NO" \
|
|
221
|
-
--idempotency-key "flight-pay-$(date +%s)"
|
|
222
|
-
|
|
223
|
-
# 6. Poll status until TICKETED (ticket_infos populated). Single-pax ~100s, multi-pax ~150s+.
|
|
224
|
-
agenzo-merchant-cli flight-flink get-order --api-key "$API_KEY" --order-no "$ORDER_NO" \
|
|
225
|
-
--watch --watch-interval 10 --watch-timeout 300
|
|
226
|
-
|
|
227
|
-
# 7. List flight orders (local read, pagination + optional status filter).
|
|
228
|
-
agenzo-merchant-cli flight-flink list-orders --api-key "$API_KEY" --page 1 --page-size 20
|
|
229
|
-
|
|
230
|
-
# 8. Cancel an un-ticketed order (ticketed orders → use refund-apply instead).
|
|
231
|
-
agenzo-merchant-cli flight-flink cancel-order --api-key "$API_KEY" --yes \
|
|
232
|
-
--order-no "$ORDER_NO" \
|
|
233
|
-
--idempotency-key "flight-cancel-$(date +%s)"
|
|
234
|
-
|
|
235
|
-
# 9. Change (rebooking): search → apply → detail; confirm via pay-order or cancel via change-cancel.
|
|
236
|
-
agenzo-merchant-cli flight-flink change-search --api-key "$API_KEY" \
|
|
237
|
-
--order-no "$ORDER_NO" --date 2026-08-05 --passenger P1 --segment-id S1
|
|
238
|
-
agenzo-merchant-cli flight-flink change-apply --api-key "$API_KEY" --yes \
|
|
239
|
-
--order-no "$ORDER_NO" --passenger P1 --segment-id S1 \
|
|
240
|
-
--product-token "$CHANGE_TOKEN" \
|
|
241
|
-
--contact-name "ZHANG SAN" --contact-region 86 --contact-phone 138 --contact-email a@b.com \
|
|
242
|
-
--idempotency-key "flight-change-$(date +%s)"
|
|
243
|
-
|
|
244
|
-
# 10. Refund: apply → detail → confirm (--confirm 1 to proceed, 2 to cancel).
|
|
245
|
-
agenzo-merchant-cli flight-flink refund-apply --api-key "$API_KEY" --yes \
|
|
246
|
-
--order-no "$ORDER_NO" --passenger P1 --segment-id S1 \
|
|
247
|
-
--reason-type 1 \
|
|
248
|
-
--contact-name "ZHANG SAN" --contact-region 86 --contact-phone 138 --contact-email a@b.com \
|
|
249
|
-
--idempotency-key "flight-refund-$(date +%s)"
|
|
250
|
-
agenzo-merchant-cli flight-flink refund-confirm --api-key "$API_KEY" --yes \
|
|
251
|
-
--refund-order-no "$REFUND_ORDER_NO" --confirm 1 \
|
|
252
|
-
--idempotency-key "flight-refund-confirm-$(date +%s)"
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
## Global flags
|
|
256
|
-
|
|
257
|
-
| Flag | Default | Description |
|
|
258
|
-
|---|---|---|
|
|
259
|
-
| `--format <json\|table>` | **`json`** | Output format. Defaults to `json`; pass `table` for tabular output. Also reads the `AGENZO_FORMAT` environment variable |
|
|
260
|
-
| `--api-key <key>` | — (requested interactively) | API Key, carried per command as the `X-Api-Key` header |
|
|
261
|
-
| `--yes` | `false` | Skip interactive confirmation (non-interactive automation); for write commands, `--yes` with a missing idempotency key is a hard error |
|
|
262
|
-
| `--verbose` | `false` | Verbose logging (written to stderr) |
|
|
263
|
-
|
|
264
|
-
## Output and error contract
|
|
265
|
-
|
|
266
|
-
- **`--format json` (non-watch commands)**: stdout contains only a **single valid JSON** (business payload + `profile`/`endpoint` envelope, where endpoint is host-only without a path); all status/progress/spinner lines go to stderr and are silenced in json mode.
|
|
267
|
-
- **`--format table`**: business output goes to stdout, status lines/spinner go to stderr.
|
|
268
|
-
- **`get --watch`**: stdout is a line-by-line NDJSON stream, **not wrapped** in the profile/endpoint envelope; polling stops when it hits the terminal-status set (`At destination` / `Cancelled` / `Rejected` / `Customer no show` / `Driver no show`, case-sensitive) or times out; on timeout the final line is `{ "watch_status": "timeout", ... }`.
|
|
269
|
-
- **`hotel-redaug get --watch` / `hotel-redaug get-checkout --watch`**: same NDJSON line-stream contract (no envelope). `get` stops when `order_status_code ∈ {3, 4, 5}` (equivalently `order_status ∈ {CONFIRMED, CANCELLED, COMPLETED}`); `get-checkout` stops when `refund_status ∈ {approved, rejected, refunded}`; on timeout the final line is `{ "watch_status": "timeout", ... }`.
|
|
270
|
-
- **Error envelope**: `json` → `{ "error": { "code", "code_num", "message", "request_id"? } }`; `table` → `✗ [<code_num>] <message>`. When a request fails, retry with the same `--idempotency-key`; if it persists, contact support with the `request_id` from the error output.
|
|
271
|
-
|
|
272
|
-
Exit codes:
|
|
273
|
-
|
|
274
|
-
| Exit code | Meaning | Representative error codes |
|
|
275
|
-
|---|---|---|
|
|
276
|
-
| `0` | Success | — |
|
|
277
|
-
| `1` | Business / param | `PARAM_INVALID`(2101) · `PARAM_IDEMPOTENCY_KEY_REQUIRED`(2102) · `SERVICE_NOT_FOUND`(4101) · `VEHICLE_UNAVAILABLE`(4201) · `QUOTE_EXPIRED`(4202) · `BOOKING_FAILED`(4203) · `CANCELLATION_NOT_ALLOWED`(4204) · `NO_AVAILABILITY`(4301) · `PRICE_CHANGED`(4302) · `NAME_FORMAT_INVALID`(4303) · `HOTEL_ORDER_NOT_FOUND`(4304) · `ALREADY_CANCELLED`(4305) · `CHECKOUT_NOT_ALLOWED`(4306) · `CHECKOUT_TASK_NOT_FOUND`(4307) · `PAY_PER_CALL_NOT_AVAILABLE`(4308) · `BILLING_MODE_MISMATCH`(3001) · `ACCOUNT_*`(31xx) · `PAYMENT_ORDER_*`(32xx) |
|
|
278
|
-
| `2` | Upgrade required | `UPGRADE_REQUIRED`(9008) |
|
|
279
|
-
| `3` | Auth / invalid key | `KEY_INVALID`(1101) · `KEY_SCOPE_DENIED`(1102) |
|
|
280
|
-
| `4` | Network / 5xx | `RATE_LIMITED`(5001) · `UPSTREAM_ERROR`(5101) · `INTERNAL_ERROR`(5201) |
|
|
281
|
-
| `5` | User cancel | `CLIENT_ABORTED`(9007) · SIGINT |
|
|
282
|
-
|
|
283
|
-
> api-key auth mapping: HTTP 401 → `KEY_INVALID`, 403 → `KEY_SCOPE_DENIED`. A known string error code (e.g. `QUOTE_EXPIRED`) takes priority and is preserved; otherwise it falls back to the HTTP-status mapping.
|
|
284
|
-
|
|
285
|
-
## Idempotency-Key
|
|
286
|
-
|
|
287
|
-
The write commands `ride-elife book` / `cancel` and `hotel-redaug create-order` / `pay-order` / `cancel` / `checkout` accept `--idempotency-key`:
|
|
288
|
-
|
|
289
|
-
- Format: `[A-Za-z0-9_-]{1,128}`.
|
|
290
|
-
- **The CLI never auto-generates one**: `--yes` with a missing key → hard error `PARAM_IDEMPOTENCY_KEY_REQUIRED` (exit 1), and no request is sent; a missing key without `--yes` → requested interactively.
|
|
291
|
-
- Sent as the `Idempotency-Key` HTTP **header**, **never in the body**.
|
|
292
|
-
- Reuse the same key to retry the same logical request; use a new key for a new request.
|
|
293
|
-
|
|
294
|
-
## Billing model for book (monthly_settlement-aware)
|
|
295
|
-
|
|
296
|
-
`ride-elife book` **does not accept** `--payment-method-id` or any card information — the merchant domain holds no payment handle. Funding is decided according to the Developer's `billing_mode`:
|
|
297
|
-
|
|
298
|
-
- **monthly_settlement**: deducted from the monthly-settlement account, no payment handle; the response has `payment_status=ON_ACCOUNT` and includes `billing_entry_id`.
|
|
299
|
-
- **pay_per_call**: optionally pass through `--payment-order-id` (a PAID order number charged separately, out-of-band); the response echoes `payment_order_id`.
|
|
300
|
-
|
|
301
|
-
The request body contains at most an optional `payment_order_id`.
|
|
302
|
-
|
|
303
|
-
### hotel-redaug billing (create-order + pay-order, two billing modes)
|
|
304
|
-
|
|
305
|
-
`hotel-redaug` uses a **two-step flow**: `create-order` (locks rate, no charge) then `pay-order` (settles).
|
|
306
|
-
|
|
307
|
-
`pay-order` takes only `--order-id`; there is no merchant-transaction-id flag. The billing path is
|
|
308
|
-
chosen server-side by the developer's `billing_mode`:
|
|
309
|
-
|
|
310
|
-
- **monthly_settlement**: deducted from the monthly-settlement account. The response carries `payment_status=ON_ACCOUNT`.
|
|
311
|
-
- **pay_per_call**: the user pays via shared EVO parameters out-of-band using the create-order `order_id` as the EVO merchantTransID; the platform queries EVO for that same `order_id` to confirm payment before calling upstream `payOrder` (response `settlement_path` is `pay_per_call`). If EVO reports "not yet paid", the CLI receives `PAYMENT_NOT_COMPLETED` (exit 1) — use `--watch` to poll until confirmed.
|
|
312
|
-
|
|
313
|
-
If the order's `billing_mode` is neither of the two values above, `pay-order` returns `BILLING_MODE_MISMATCH` (exit 1).
|
|
314
|
-
|
|
315
|
-
## Amount units (decimal currency)
|
|
316
|
-
|
|
317
|
-
Both `ride-elife` and `hotel-redaug` express **every monetary amount in DECIMAL currency units** paired with an ISO 4217 `currency` code — `320.00` means 320.00 yuan, never `32000` minor units (cents/fen). This applies to inputs (`hotel-redaug create-order --total-amount`, each `--price-items[].sale_price`) and to every rendered amount (`quote` totals and `price_items`, `get` / `list-orders` prices, cancellation fees, and refunds). Amounts are forwarded and rendered **verbatim**, with no minor-unit conversion in either direction. This differs from `agenzo-token-cli` and `agenzo-payment-cli`, which use minor units.
|
|
318
|
-
|
|
319
|
-
## profile / host model
|
|
320
|
-
|
|
321
|
-
merchant-cli **has no host / config commands** and does not govern environments. It reuses the environment configured by `agenzo-admin-cli` (persisted under `~/.agenzo-admin-cli/`):
|
|
322
|
-
|
|
323
|
-
- Determines the API host that requests are sent to.
|
|
324
|
-
- Provides the environment name + host for the `profile` / `endpoint` envelope in json output.
|
|
325
|
-
|
|
326
|
-
**Setting the host / switching environments belongs to `agenzo-admin-cli`** (`agenzo-admin-cli config set-host`).
|
|
327
|
-
|
|
328
|
-
## Machine-readable verb schema
|
|
329
|
-
|
|
330
|
-
Every `ride-elife`, `hotel-redaug`, and `flight-flink` verb supports `--help --format json`, emitting that verb's machine-readable schema (`cli` / `noun` / `verb` / `description` / `flags` / `response` / `example`, some with `error_recovery` / `polling`):
|
|
331
|
-
|
|
332
|
-
```bash
|
|
333
|
-
agenzo-merchant-cli ride-elife quote --help --format json
|
|
334
|
-
agenzo-merchant-cli ride-elife book --help --format json
|
|
335
|
-
agenzo-merchant-cli hotel-redaug quote --help --format json
|
|
336
|
-
agenzo-merchant-cli hotel-redaug create-order --help --format json # write verb: error_recovery
|
|
337
|
-
agenzo-merchant-cli flight-flink search --help --format json
|
|
338
|
-
agenzo-merchant-cli flight-flink create-order --help --format json
|
|
339
|
-
agenzo-merchant-cli hotel-redaug pay-order --help --format json # write verb: error_recovery
|
|
340
|
-
agenzo-merchant-cli hotel-redaug get --help --format json # long-running: polling block
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
For `hotel-redaug`, `create-order` / `pay-order` / `cancel` / `checkout` are the write verbs that require `--idempotency-key`, and `get` / `get-checkout` are the long-running reads that support `--watch` NDJSON streaming (their schemas carry a `polling` block).
|
|
1
|
+
# @agenzo/merchant-cli
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@agenzo/merchant-cli) [](../../LICENSE) 
|
|
4
|
+
|
|
5
|
+
> **Merchant-fulfillment CLI** for the Agenzo platform — binary `agenzo-merchant-cli`.
|
|
6
|
+
> Agents fulfill commerce services here. Each capability is a noun and the set grows over time — use `services` to discover what's available; today's capabilities are ride-hailing (`ride-elife`) and hotel booking (`hotel-redaug`).
|
|
7
|
+
|
|
8
|
+
**[Overview](#overview)** · **[Features](#features)** · **[Quick Start](#quick-start)** · **[Global flags](#global-flags)** · **[Errors](#output-and-error-contract)** · **[Idempotency-Key](#idempotency-key)**
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
`agenzo-merchant-cli` is the command-line entry point for Agents to fulfill commerce services on the Agenzo platform. Each fulfillment capability is exposed as a **noun**, and the set grows over time:
|
|
15
|
+
|
|
16
|
+
- **`services`** (capability discovery): list what's currently available and how to call it — run this first to learn the current capability set.
|
|
17
|
+
- **`ride-elife`** (ride-hailing): the full loop of quote → book → query/poll → cancel → list-orders.
|
|
18
|
+
- **`hotel-redaug`** (hotel booking): search, find-destination, hotel-filters, list-cities, hotel-detail, quote, create-order, pay-order, get (status/poll), cancel, checkout, get-checkout, list-orders. Supports both **monthly_settlement** (on-account deduction) and **pay_per_call** (user pays via EVO using the order_id as the merchantTransID).
|
|
19
|
+
|
|
20
|
+
More fulfillment capabilities are added as new nouns over time; `services list` always reflects the current set.
|
|
21
|
+
|
|
22
|
+
## Features
|
|
23
|
+
|
|
24
|
+
| Noun | Verb | Type | HTTP | Description |
|
|
25
|
+
|---|---|---|---|---|
|
|
26
|
+
| `services` | `list` | Read | — (local) | List available merchant-fulfillment capabilities |
|
|
27
|
+
| `services` | `get <service-id>` | Read | — (local) | View the full metadata of a single capability (miss → `SERVICE_NOT_FOUND`) |
|
|
28
|
+
| `ride-elife` | `quote` | Read | `POST /ride/quote` | Point-to-point quote (`vehicle_classes[]` + meet-and-greet) |
|
|
29
|
+
| `ride-elife` | `book` | Write/Y | `POST /ride/book` | Book against a quote (monthly_settlement-aware, see below) |
|
|
30
|
+
| `ride-elife` | `get` | Read | `GET /ride/<id>/status` | Query order status; `--watch` emits an NDJSON polling stream |
|
|
31
|
+
| `ride-elife` | `cancel` | Write/Y | `POST /ride/<id>/cancel` | Cancel an order (no body, may incur a fee) |
|
|
32
|
+
| `ride-elife` | `list-orders` | Read | `GET /ride/orders` | List booked trips (pagination + filtering) |
|
|
33
|
+
| `hotel-redaug` | `search` | Read | `POST /hotel/search` | Search hotels by coordinates or destination-id + stay dates + filters |
|
|
34
|
+
| `hotel-redaug` | `find-destination` | Read | `POST /hotel/find-destination` | Resolve free-text to destinations (destination_id + coordinates) |
|
|
35
|
+
| `hotel-redaug` | `hotel-filters` | Read | `POST /hotel/filters` | Get available filter options for a location (codes → search flags) |
|
|
36
|
+
| `hotel-redaug` | `list-cities` | Read | `POST /hotel/cities` | List cities for a country (destination_id + coordinates) |
|
|
37
|
+
| `hotel-redaug` | `hotel-detail` | Read | `POST /hotel/detail` | Hotel detail with facilities/images AND `rooms[]` (area/floor/beds/photos) — call before quote |
|
|
38
|
+
| `hotel-redaug` | `quote` | Read | `POST /hotel/quote` | Real-time rooms/rates for one hotel (`product_token` + `price_items`) |
|
|
39
|
+
| `hotel-redaug` | `create-order` | Write/Y | `POST /hotel/create-order` | Create a hotel order without charging (locks rate + returns `order_id` + payable amount) |
|
|
40
|
+
| `hotel-redaug` | `pay-order` | Write/Y | `POST /hotel/{order_id}/pay` | Pay for a created order (takes only `--order-id`); billing path (`monthly_settlement` or `pay_per_call`) is chosen server-side |
|
|
41
|
+
| `hotel-redaug` | `get` | Read | `GET /hotel/<id>/status` | Query order status; `--watch` emits an NDJSON polling stream |
|
|
42
|
+
| `hotel-redaug` | `cancel` | Write/Y | `POST /hotel/<id>/cancel` | Cancel a whole order (acceptance ≠ proof; poll `get`) |
|
|
43
|
+
| `hotel-redaug` | `checkout` | Write/Y | `POST /hotel/<id>/checkout` | Partial check-out / out-of-policy cancellation (async) |
|
|
44
|
+
| `hotel-redaug` | `get-checkout` | Read | `GET /hotel/checkout/<task_order_code>` | Poll a check-out application; `--watch` emits an NDJSON stream |
|
|
45
|
+
| `hotel-redaug` | `list-orders` | Read | `GET /hotel/orders` | List hotel orders (pagination + status filter) |
|
|
46
|
+
|
|
47
|
+
> Write commands (`ride-elife book` / `cancel`; `hotel-redaug create-order` / `pay-order` / `cancel` / `checkout`) are subject to the idempotency-key rules (see [Idempotency-Key](#idempotency-key)).
|
|
48
|
+
> Read status verbs `get` / `get-checkout` support `--watch` for NDJSON status polling.
|
|
49
|
+
> `ride-elife track` is not available — use `get --watch` for order-status polling.
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
### Requirements
|
|
54
|
+
|
|
55
|
+
- Node.js 22+
|
|
56
|
+
|
|
57
|
+
### Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm install -g @agenzo/merchant-cli
|
|
61
|
+
agenzo-merchant-cli --version
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Upgrade later with `npm install -g @agenzo/merchant-cli@latest`.
|
|
65
|
+
|
|
66
|
+
### Authentication
|
|
67
|
+
|
|
68
|
+
A runtime-plane CLI that uses an **API Key** (`--api-key`, carried per command as the `X-Api-Key` header):
|
|
69
|
+
|
|
70
|
+
- The API Key is issued by `agenzo-admin-cli keys create --scope merchant` and must include the `merchant` scope.
|
|
71
|
+
- When `--api-key` is omitted, it is requested interactively (password input).
|
|
72
|
+
- No Bearer Token or local keystore — every command carries the API Key.
|
|
73
|
+
|
|
74
|
+
### Ride-hailing end-to-end example
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# 1. Discover capabilities
|
|
78
|
+
agenzo-merchant-cli services list
|
|
79
|
+
agenzo-merchant-cli services get ride-elife
|
|
80
|
+
|
|
81
|
+
# 2. Quote (produces quote_id)
|
|
82
|
+
agenzo-merchant-cli ride-elife quote --api-key "$API_KEY" \
|
|
83
|
+
--pickup-lat 37.7937 --pickup-lng -122.3956 --pickup-name "1 Market St" \
|
|
84
|
+
--dropoff-lat 37.6213 --dropoff-lng -122.3790 --dropoff-name "SFO Airport" \
|
|
85
|
+
--pickup-time now
|
|
86
|
+
|
|
87
|
+
# 3. Book (write op: --yes auto-confirms + --idempotency-key must be provided)
|
|
88
|
+
agenzo-merchant-cli ride-elife book --api-key "$API_KEY" --yes \
|
|
89
|
+
--quote-id "$QUOTE_ID" --vehicle-class Sedan --price-amount 42.50 \
|
|
90
|
+
--passenger-name "Alice" --passenger-phone "+14155551234" \
|
|
91
|
+
--idempotency-key "book-$(date +%s)"
|
|
92
|
+
|
|
93
|
+
# 4. Query / poll (--watch emits line-by-line NDJSON)
|
|
94
|
+
agenzo-merchant-cli ride-elife get --api-key "$API_KEY" --order-id "$RIDE_ID"
|
|
95
|
+
agenzo-merchant-cli ride-elife get --api-key "$API_KEY" --order-id "$RIDE_ID" \
|
|
96
|
+
--watch --watch-interval 5 --watch-timeout 600
|
|
97
|
+
|
|
98
|
+
# 5. List orders / cancel
|
|
99
|
+
agenzo-merchant-cli ride-elife list-orders --api-key "$API_KEY" --status Pending --page 1 --page-size 20
|
|
100
|
+
agenzo-merchant-cli ride-elife cancel --api-key "$API_KEY" --yes \
|
|
101
|
+
--order-id "$RIDE_ID" --idempotency-key "cancel-$(date +%s)"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Hotel booking end-to-end example
|
|
105
|
+
|
|
106
|
+
The core Agent loop is `search → quote → create-order → pay-order → get`. Amounts are decimal currency
|
|
107
|
+
units (e.g. `320.00` = 320.00 yuan). **`create-order` settles payment AND locks the room** — the funds
|
|
108
|
+
path is chosen server-side by the developer's `billing_mode`:
|
|
109
|
+
|
|
110
|
+
- **monthly_settlement**: the total is deducted from the developer's monthly-settlement account balance.
|
|
111
|
+
- **pay_per_call**: the total is authorized + captured on the developer's bound card via the platform's own EVO integration (server-side; no EVO parameters pass through this CLI).
|
|
112
|
+
|
|
113
|
+
`pay-order` takes only `--order-id` and triggers supplier confirmation / ticket issuance — funds were
|
|
114
|
+
already settled in `create-order`, so both billing modes use the same `pay-order` call.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# 1. Search hotels by coordinates + stay dates (or use --destination-id from find-destination).
|
|
118
|
+
# Pick a hotels[].hotel_id from the result for the quote step.
|
|
119
|
+
agenzo-merchant-cli hotel-redaug search --api-key "$API_KEY" \
|
|
120
|
+
--lat 31.2304 --lng 121.4737 --distance 20 \
|
|
121
|
+
--check-in 2026-02-10 --check-out 2026-02-12 \
|
|
122
|
+
--adults 2 --children 0 --room-num 1
|
|
123
|
+
|
|
124
|
+
# 2. Quote one hotel (produces rates[].product_token, total_price, price_items)
|
|
125
|
+
agenzo-merchant-cli hotel-redaug quote --api-key "$API_KEY" \
|
|
126
|
+
--hotel-id "$HOTEL_ID" \
|
|
127
|
+
--check-in 2026-02-10 --check-out 2026-02-12 \
|
|
128
|
+
--adults 2 --room-num 1 --nationality CN
|
|
129
|
+
|
|
130
|
+
# 3. Create Order (write op: settles payment + locks the room; returns order_id + fc_order_code).
|
|
131
|
+
agenzo-merchant-cli hotel-redaug create-order --api-key "$API_KEY" --yes \
|
|
132
|
+
--product-token "$PRODUCT_TOKEN" \
|
|
133
|
+
--total-amount 640.00 --currency CNY \
|
|
134
|
+
--price-items '[{"sale_date":"2026-02-10","sale_price":320.00,"breakfast_num":2},{"sale_date":"2026-02-11","sale_price":320.00,"breakfast_num":2}]' \
|
|
135
|
+
--check-in 2026-02-10 --check-out 2026-02-12 \
|
|
136
|
+
--guest-name "Zhang San" --contact-name "Zhang San" \
|
|
137
|
+
--contact-phone "13800138000" --contact-country-code 86 \
|
|
138
|
+
--idempotency-key "hotel-create-$(date +%s)"
|
|
139
|
+
|
|
140
|
+
# 4a. Pay Order — monthly_settlement path (on-account)
|
|
141
|
+
agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
|
|
142
|
+
--order-id "$ORDER_ID" \
|
|
143
|
+
--idempotency-key "hotel-pay-$(date +%s)"
|
|
144
|
+
|
|
145
|
+
# 4b. Pay Order — pay_per_call path (funds already captured on the bound card in
|
|
146
|
+
# create-order; pay-order just triggers supplier confirmation). Same command.
|
|
147
|
+
agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
|
|
148
|
+
--order-id "$ORDER_ID" \
|
|
149
|
+
--idempotency-key "hotel-pay-$(date +%s)"
|
|
150
|
+
|
|
151
|
+
# 4c. Pay Order — pay_per_call with --watch (polls until PAID or timeout)
|
|
152
|
+
agenzo-merchant-cli hotel-redaug pay-order --api-key "$API_KEY" --yes \
|
|
153
|
+
--order-id "$ORDER_ID" \
|
|
154
|
+
--idempotency-key "hotel-pay-$(date +%s)" \
|
|
155
|
+
--watch --watch-interval 5 --watch-timeout 120
|
|
156
|
+
|
|
157
|
+
# 5. Query / poll status. create-order returns order_status=AWAITING_PAYMENT;
|
|
158
|
+
# after pay-order succeeds, status becomes PAID; poll get until CONFIRMED.
|
|
159
|
+
agenzo-merchant-cli hotel-redaug get --api-key "$API_KEY" --order-id "$ORDER_ID"
|
|
160
|
+
agenzo-merchant-cli hotel-redaug get --api-key "$API_KEY" --order-id "$ORDER_ID" \
|
|
161
|
+
--watch --watch-interval 5 --watch-timeout 600
|
|
162
|
+
|
|
163
|
+
# 6. List orders (pagination + optional status filter)
|
|
164
|
+
agenzo-merchant-cli hotel-redaug list-orders --api-key "$API_KEY" \
|
|
165
|
+
--status CONFIRMED --page 1 --page-size 20
|
|
166
|
+
|
|
167
|
+
# 7. Cancel a whole order (write op). Acceptance is NOT proof — poll get until CANCELLED.
|
|
168
|
+
agenzo-merchant-cli hotel-redaug cancel --api-key "$API_KEY" --yes \
|
|
169
|
+
--order-id "$ORDER_ID" --fc-order-code "$FC_ORDER_CODE" \
|
|
170
|
+
--reason "Change of plans" \
|
|
171
|
+
--idempotency-key "hotel-cancel-$(date +%s)"
|
|
172
|
+
|
|
173
|
+
# 8. Partial check-out / out-of-policy cancellation (write op, async).
|
|
174
|
+
# Returns task_order_code; poll get-checkout for the refund outcome.
|
|
175
|
+
agenzo-merchant-cli hotel-redaug checkout --api-key "$API_KEY" --yes \
|
|
176
|
+
--order-id "$ORDER_ID" --fc-order-code "$FC_ORDER_CODE" \
|
|
177
|
+
--reason "Guest departing early" \
|
|
178
|
+
--checkout-rooms '[{"room_index":"1","guest_name":"Zhang San","cancel_check_in_date":"2026-02-11"}]' \
|
|
179
|
+
--refund-type 1 \
|
|
180
|
+
--idempotency-key "hotel-checkout-$(date +%s)"
|
|
181
|
+
|
|
182
|
+
# 9. Poll the check-out application until a terminal refund status
|
|
183
|
+
agenzo-merchant-cli hotel-redaug get-checkout --api-key "$API_KEY" \
|
|
184
|
+
--task-order-code "$TASK_ORDER_CODE"
|
|
185
|
+
agenzo-merchant-cli hotel-redaug get-checkout --api-key "$API_KEY" \
|
|
186
|
+
--task-order-code "$TASK_ORDER_CODE" --watch --watch-interval 10 --watch-timeout 600
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Flight booking end-to-end example (flight-flink)
|
|
190
|
+
|
|
191
|
+
The flow is `find-airport → search → verify → create-order → pay-order → get-order (poll until TICKETED)`.
|
|
192
|
+
Amounts are decimal currency units (e.g. `1200.00` = 1200.00 yuan). `create-order` locks the fare without
|
|
193
|
+
charging; `pay-order` settles + triggers ticketing (asynchronous — poll `get-order` until status=TICKETED).
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# 1. Resolve a city/airport keyword to IATA codes.
|
|
197
|
+
agenzo-merchant-cli flight-flink find-airport --api-key "$API_KEY" --keyword "beijing"
|
|
198
|
+
|
|
199
|
+
# 2. Search one-way flights (trip-type 1=OW, 2=RT, 3=multi-city).
|
|
200
|
+
# journeys always carries ALL legs; for multi-city, relay --journey-id from each result.
|
|
201
|
+
agenzo-merchant-cli flight-flink search --api-key "$API_KEY" \
|
|
202
|
+
--trip-type 1 \
|
|
203
|
+
--journeys '[{"date":"2026-08-01","origin":"PEK","originType":"2","destination":"SHA","destinationType":"2"}]'
|
|
204
|
+
|
|
205
|
+
# 3. Verify price (returns authoritative product_token; if price_changed, re-confirm with user).
|
|
206
|
+
agenzo-merchant-cli flight-flink verify --api-key "$API_KEY" \
|
|
207
|
+
--product-token "$PRODUCT_TOKEN"
|
|
208
|
+
|
|
209
|
+
# 4. Create Order (write op: locks fare, NO charge; status → AWAITING_PAYMENT).
|
|
210
|
+
agenzo-merchant-cli flight-flink create-order --api-key "$API_KEY" --yes \
|
|
211
|
+
--product-token "$VERIFIED_TOKEN" \
|
|
212
|
+
--total-amount 1200.00 --currency CNY \
|
|
213
|
+
--contact-name "ZHANG SAN" --contact-region 86 \
|
|
214
|
+
--contact-phone "13800138000" --contact-email "a@example.com" \
|
|
215
|
+
--passengers '[{"firstName":"SAN","lastName":"ZHANG","gender":"1","birthday":"1990-01-01","id_type":"1","id_number":"E12345678","nationality":"CN","type":"adult","expiration":"2032-01-01"}]' \
|
|
216
|
+
--idempotency-key "flight-create-$(date +%s)"
|
|
217
|
+
|
|
218
|
+
# 5. Pay Order (settles + triggers ticketing; status → PAID).
|
|
219
|
+
agenzo-merchant-cli flight-flink pay-order --api-key "$API_KEY" --yes \
|
|
220
|
+
--order-no "$ORDER_NO" \
|
|
221
|
+
--idempotency-key "flight-pay-$(date +%s)"
|
|
222
|
+
|
|
223
|
+
# 6. Poll status until TICKETED (ticket_infos populated). Single-pax ~100s, multi-pax ~150s+.
|
|
224
|
+
agenzo-merchant-cli flight-flink get-order --api-key "$API_KEY" --order-no "$ORDER_NO" \
|
|
225
|
+
--watch --watch-interval 10 --watch-timeout 300
|
|
226
|
+
|
|
227
|
+
# 7. List flight orders (local read, pagination + optional status filter).
|
|
228
|
+
agenzo-merchant-cli flight-flink list-orders --api-key "$API_KEY" --page 1 --page-size 20
|
|
229
|
+
|
|
230
|
+
# 8. Cancel an un-ticketed order (ticketed orders → use refund-apply instead).
|
|
231
|
+
agenzo-merchant-cli flight-flink cancel-order --api-key "$API_KEY" --yes \
|
|
232
|
+
--order-no "$ORDER_NO" \
|
|
233
|
+
--idempotency-key "flight-cancel-$(date +%s)"
|
|
234
|
+
|
|
235
|
+
# 9. Change (rebooking): search → apply → detail; confirm via pay-order or cancel via change-cancel.
|
|
236
|
+
agenzo-merchant-cli flight-flink change-search --api-key "$API_KEY" \
|
|
237
|
+
--order-no "$ORDER_NO" --date 2026-08-05 --passenger P1 --segment-id S1
|
|
238
|
+
agenzo-merchant-cli flight-flink change-apply --api-key "$API_KEY" --yes \
|
|
239
|
+
--order-no "$ORDER_NO" --passenger P1 --segment-id S1 \
|
|
240
|
+
--product-token "$CHANGE_TOKEN" \
|
|
241
|
+
--contact-name "ZHANG SAN" --contact-region 86 --contact-phone 138 --contact-email a@b.com \
|
|
242
|
+
--idempotency-key "flight-change-$(date +%s)"
|
|
243
|
+
|
|
244
|
+
# 10. Refund: apply → detail → confirm (--confirm 1 to proceed, 2 to cancel).
|
|
245
|
+
agenzo-merchant-cli flight-flink refund-apply --api-key "$API_KEY" --yes \
|
|
246
|
+
--order-no "$ORDER_NO" --passenger P1 --segment-id S1 \
|
|
247
|
+
--reason-type 1 \
|
|
248
|
+
--contact-name "ZHANG SAN" --contact-region 86 --contact-phone 138 --contact-email a@b.com \
|
|
249
|
+
--idempotency-key "flight-refund-$(date +%s)"
|
|
250
|
+
agenzo-merchant-cli flight-flink refund-confirm --api-key "$API_KEY" --yes \
|
|
251
|
+
--refund-order-no "$REFUND_ORDER_NO" --confirm 1 \
|
|
252
|
+
--idempotency-key "flight-refund-confirm-$(date +%s)"
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Global flags
|
|
256
|
+
|
|
257
|
+
| Flag | Default | Description |
|
|
258
|
+
|---|---|---|
|
|
259
|
+
| `--format <json\|table>` | **`json`** | Output format. Defaults to `json`; pass `table` for tabular output. Also reads the `AGENZO_FORMAT` environment variable |
|
|
260
|
+
| `--api-key <key>` | — (requested interactively) | API Key, carried per command as the `X-Api-Key` header |
|
|
261
|
+
| `--yes` | `false` | Skip interactive confirmation (non-interactive automation); for write commands, `--yes` with a missing idempotency key is a hard error |
|
|
262
|
+
| `--verbose` | `false` | Verbose logging (written to stderr) |
|
|
263
|
+
|
|
264
|
+
## Output and error contract
|
|
265
|
+
|
|
266
|
+
- **`--format json` (non-watch commands)**: stdout contains only a **single valid JSON** (business payload + `profile`/`endpoint` envelope, where endpoint is host-only without a path); all status/progress/spinner lines go to stderr and are silenced in json mode.
|
|
267
|
+
- **`--format table`**: business output goes to stdout, status lines/spinner go to stderr.
|
|
268
|
+
- **`get --watch`**: stdout is a line-by-line NDJSON stream, **not wrapped** in the profile/endpoint envelope; polling stops when it hits the terminal-status set (`At destination` / `Cancelled` / `Rejected` / `Customer no show` / `Driver no show`, case-sensitive) or times out; on timeout the final line is `{ "watch_status": "timeout", ... }`.
|
|
269
|
+
- **`hotel-redaug get --watch` / `hotel-redaug get-checkout --watch`**: same NDJSON line-stream contract (no envelope). `get` stops when `order_status_code ∈ {3, 4, 5}` (equivalently `order_status ∈ {CONFIRMED, CANCELLED, COMPLETED}`); `get-checkout` stops when `refund_status ∈ {approved, rejected, refunded}`; on timeout the final line is `{ "watch_status": "timeout", ... }`.
|
|
270
|
+
- **Error envelope**: `json` → `{ "error": { "code", "code_num", "message", "request_id"? } }`; `table` → `✗ [<code_num>] <message>`. When a request fails, retry with the same `--idempotency-key`; if it persists, contact support with the `request_id` from the error output.
|
|
271
|
+
|
|
272
|
+
Exit codes:
|
|
273
|
+
|
|
274
|
+
| Exit code | Meaning | Representative error codes |
|
|
275
|
+
|---|---|---|
|
|
276
|
+
| `0` | Success | — |
|
|
277
|
+
| `1` | Business / param | `PARAM_INVALID`(2101) · `PARAM_IDEMPOTENCY_KEY_REQUIRED`(2102) · `SERVICE_NOT_FOUND`(4101) · `VEHICLE_UNAVAILABLE`(4201) · `QUOTE_EXPIRED`(4202) · `BOOKING_FAILED`(4203) · `CANCELLATION_NOT_ALLOWED`(4204) · `NO_AVAILABILITY`(4301) · `PRICE_CHANGED`(4302) · `NAME_FORMAT_INVALID`(4303) · `HOTEL_ORDER_NOT_FOUND`(4304) · `ALREADY_CANCELLED`(4305) · `CHECKOUT_NOT_ALLOWED`(4306) · `CHECKOUT_TASK_NOT_FOUND`(4307) · `PAY_PER_CALL_NOT_AVAILABLE`(4308) · `BILLING_MODE_MISMATCH`(3001) · `ACCOUNT_*`(31xx) · `PAYMENT_ORDER_*`(32xx) |
|
|
278
|
+
| `2` | Upgrade required | `UPGRADE_REQUIRED`(9008) |
|
|
279
|
+
| `3` | Auth / invalid key | `KEY_INVALID`(1101) · `KEY_SCOPE_DENIED`(1102) |
|
|
280
|
+
| `4` | Network / 5xx | `RATE_LIMITED`(5001) · `UPSTREAM_ERROR`(5101) · `INTERNAL_ERROR`(5201) |
|
|
281
|
+
| `5` | User cancel | `CLIENT_ABORTED`(9007) · SIGINT |
|
|
282
|
+
|
|
283
|
+
> api-key auth mapping: HTTP 401 → `KEY_INVALID`, 403 → `KEY_SCOPE_DENIED`. A known string error code (e.g. `QUOTE_EXPIRED`) takes priority and is preserved; otherwise it falls back to the HTTP-status mapping.
|
|
284
|
+
|
|
285
|
+
## Idempotency-Key
|
|
286
|
+
|
|
287
|
+
The write commands `ride-elife book` / `cancel` and `hotel-redaug create-order` / `pay-order` / `cancel` / `checkout` accept `--idempotency-key`:
|
|
288
|
+
|
|
289
|
+
- Format: `[A-Za-z0-9_-]{1,128}`.
|
|
290
|
+
- **The CLI never auto-generates one**: `--yes` with a missing key → hard error `PARAM_IDEMPOTENCY_KEY_REQUIRED` (exit 1), and no request is sent; a missing key without `--yes` → requested interactively.
|
|
291
|
+
- Sent as the `Idempotency-Key` HTTP **header**, **never in the body**.
|
|
292
|
+
- Reuse the same key to retry the same logical request; use a new key for a new request.
|
|
293
|
+
|
|
294
|
+
## Billing model for book (monthly_settlement-aware)
|
|
295
|
+
|
|
296
|
+
`ride-elife book` **does not accept** `--payment-method-id` or any card information — the merchant domain holds no payment handle. Funding is decided according to the Developer's `billing_mode`:
|
|
297
|
+
|
|
298
|
+
- **monthly_settlement**: deducted from the monthly-settlement account, no payment handle; the response has `payment_status=ON_ACCOUNT` and includes `billing_entry_id`.
|
|
299
|
+
- **pay_per_call**: optionally pass through `--payment-order-id` (a PAID order number charged separately, out-of-band); the response echoes `payment_order_id`.
|
|
300
|
+
|
|
301
|
+
The request body contains at most an optional `payment_order_id`.
|
|
302
|
+
|
|
303
|
+
### hotel-redaug billing (create-order + pay-order, two billing modes)
|
|
304
|
+
|
|
305
|
+
`hotel-redaug` uses a **two-step flow**: `create-order` (locks rate, no charge) then `pay-order` (settles).
|
|
306
|
+
|
|
307
|
+
`pay-order` takes only `--order-id`; there is no merchant-transaction-id flag. The billing path is
|
|
308
|
+
chosen server-side by the developer's `billing_mode`:
|
|
309
|
+
|
|
310
|
+
- **monthly_settlement**: deducted from the monthly-settlement account. The response carries `payment_status=ON_ACCOUNT`.
|
|
311
|
+
- **pay_per_call**: the user pays via shared EVO parameters out-of-band using the create-order `order_id` as the EVO merchantTransID; the platform queries EVO for that same `order_id` to confirm payment before calling upstream `payOrder` (response `settlement_path` is `pay_per_call`). If EVO reports "not yet paid", the CLI receives `PAYMENT_NOT_COMPLETED` (exit 1) — use `--watch` to poll until confirmed.
|
|
312
|
+
|
|
313
|
+
If the order's `billing_mode` is neither of the two values above, `pay-order` returns `BILLING_MODE_MISMATCH` (exit 1).
|
|
314
|
+
|
|
315
|
+
## Amount units (decimal currency)
|
|
316
|
+
|
|
317
|
+
Both `ride-elife` and `hotel-redaug` express **every monetary amount in DECIMAL currency units** paired with an ISO 4217 `currency` code — `320.00` means 320.00 yuan, never `32000` minor units (cents/fen). This applies to inputs (`hotel-redaug create-order --total-amount`, each `--price-items[].sale_price`) and to every rendered amount (`quote` totals and `price_items`, `get` / `list-orders` prices, cancellation fees, and refunds). Amounts are forwarded and rendered **verbatim**, with no minor-unit conversion in either direction. This differs from `agenzo-token-cli` and `agenzo-payment-cli`, which use minor units.
|
|
318
|
+
|
|
319
|
+
## profile / host model
|
|
320
|
+
|
|
321
|
+
merchant-cli **has no host / config commands** and does not govern environments. It reuses the environment configured by `agenzo-admin-cli` (persisted under `~/.agenzo-admin-cli/`):
|
|
322
|
+
|
|
323
|
+
- Determines the API host that requests are sent to.
|
|
324
|
+
- Provides the environment name + host for the `profile` / `endpoint` envelope in json output.
|
|
325
|
+
|
|
326
|
+
**Setting the host / switching environments belongs to `agenzo-admin-cli`** (`agenzo-admin-cli config set-host`).
|
|
327
|
+
|
|
328
|
+
## Machine-readable verb schema
|
|
329
|
+
|
|
330
|
+
Every `ride-elife`, `hotel-redaug`, and `flight-flink` verb supports `--help --format json`, emitting that verb's machine-readable schema (`cli` / `noun` / `verb` / `description` / `flags` / `response` / `example`, some with `error_recovery` / `polling`):
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
agenzo-merchant-cli ride-elife quote --help --format json
|
|
334
|
+
agenzo-merchant-cli ride-elife book --help --format json
|
|
335
|
+
agenzo-merchant-cli hotel-redaug quote --help --format json
|
|
336
|
+
agenzo-merchant-cli hotel-redaug create-order --help --format json # write verb: error_recovery
|
|
337
|
+
agenzo-merchant-cli flight-flink search --help --format json
|
|
338
|
+
agenzo-merchant-cli flight-flink create-order --help --format json
|
|
339
|
+
agenzo-merchant-cli hotel-redaug pay-order --help --format json # write verb: error_recovery
|
|
340
|
+
agenzo-merchant-cli hotel-redaug get --help --format json # long-running: polling block
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
For `hotel-redaug`, `create-order` / `pay-order` / `cancel` / `checkout` are the write verbs that require `--idempotency-key`, and `get` / `get-checkout` are the long-running reads that support `--watch` NDJSON streaming (their schemas carry a `polling` block).
|