Hotel offers and priced offer detail over the Amadeus API. Agents shop rooms without an account or an API key — one paid HTTP call, answer in the response body. Pay in USDC on Base or Solana — your client picks the rail.
git clone https://github.com/nirholas/x402-hotel-search && cd x402-hotel-search && npm install && npm run dev| Route | Price | You get back |
|---|---|---|
GET /search | $0.005 | Hotel offers for a city and date range — hotel, room, board type, cancellation policy, total price |
GET /offer/:offerId | $0.003 | Priced offer detail with a per-night price breakdown |
GET /health | free | Service status and which data source is live |
GET /cities | free | City codes the fixture data models by name and location |
GET /.well-known/x402 | free | Machine-readable price sheet, both rails |
Shopping a city and drilling into one candidate is $0.008. /search already
returns complete offers, so only pay for /offer when you need the breakdown.
Every 402 lists both networks. A caller holding USDC on Base pays on Base; a caller holding USDC on Solana pays on Solana. Same route, same price, same artifact.
base-sepolia by default, base for mainnet. EIP-3009 transfer authorization.
0x40252CFDF8B20Ed757D61ff157719F33Ec332402
solana mainnet by default, solana-devnet for testing. SPL transfer.
WwwuGbqHrwF5RG89KhUbmRWEvjnRH9k5kVM5p7T3WwW
X-PAYMENT# 1. Run the service (works immediately — no keys needed)
cp .env.example .env
npm run dev # http://localhost:4023
# 2. See the dual-rail 402 quote (no wallet needed)
curl -s "http://localhost:4023/search?cityCode=NYC&checkInDate=2026-09-15&checkOutDate=2026-09-18" \
| jq '.accepts[] | {network, payTo, maxAmountRequired}'
# 3. Pay for real on Base Sepolia (free test USDC: faucet.circle.com)
export PRIVATE_KEY=0x…
npm run client # searches a city, then pulls detail on the cheapest room
Amadeus is a keyed API, so the service is env-gated: set
AMADEUS_CLIENT_ID and AMADEUS_CLIENT_SECRET
(free sandbox keys, no card) and every
route hits the real Hotel Search API. Without them you get deterministic fixtures
instead, so the demo always runs. Every response carries a source
field — "amadeus" or "fixture" — so a caller is never
guessing which it got. Never quote a fixture rate as a real price.