The agent API

Search, book and track flights — and buy products on merchant websites — programmatically: x402-paid, wallet-identified, schema at /openapi.json.

API quickstart (agents)

Base URL: https://travel.brij.fi · full schema: /openapi.json · payments: x402 (USDC on Solana). Any x402-capable client works; without payment, endpoints reply 402 with the exact price and payment instructions.

# 1 — search (x402-paid; price is dynamic, quoted in the 402 challenge)
curl -X POST https://travel.brij.fi/air/search \
  -H "Content-Type: application/json" \
  -d '{"origin_iata":"MAD","destination_iata":"BCN","depart_date":"2026-12-15",
       "adults":1,"cabin_class":"economy","cheapest_per_itinerary":true,"limit":20}'
# → offers[], each with an offer_id. status "enriching" + search_id?
#   poll POST /air/search-updates {search_id} — free — until "complete".

# 2 — optional: drill into one offer (fare menu, baggage, current price)
curl -X POST https://travel.brij.fi/air/offer-details \
  -d '{"offer_id":"trip.com:…"}'
# browser-tier fare rows carry their own bookable offer_id ("…##2") and fare_index.

# 3 — create the intent (0.10 USDC)
curl -X POST https://travel.brij.fi/air/intents \
  -d '{"offer_id":"…","funding_wallet":"YOUR_WALLET"}'
# → intent.id, escrow_address, expected_escrow_amount, customer_support_code
#   ⚠ SAVE customer_support_code NOW — it is never returned again.

# 4 — fund the escrow: transfer expected_escrow_amount USDC to escrow_address.

# 5 — book (x402 pays the escrow amount if not already funded)
curl -X POST https://travel.brij.fi/air/book \
  -d '{"intent_id":"intent_…","passengers":[{"given_name":"…","family_name":"…",
       "born_on":"1990-01-01","title":"mr","gender":"m",
       "email":"…","phone_number":"+34…"}]}'

# 6 — track: GET /air/intents/{id} (free) until status "booked" / "refunded".
#     The PNR: GET /air/orders/{order_id} with X-Customer-Support-Code
#     (fastbooking), or the ticket email (browser tier).
Idempotency is built in: re-creating an intent for the same (wallet, offer) returns 409 with the existing intent_id; re-booking a booked intent returns 409. Refused calls are never charged — a 402 that is not settled costs nothing.

Buying a product (shop)

The same escrow, for a product on a merchant's own website: you name it by its URL, the marketplace reads the exact total at the merchant's checkout (shipping and sales tax included), you escrow that total plus the fee, and the merchant's own confirmation email releases the money. V1: one product line (quantity 1–10), US shipping addresses, USD, supported merchants only (a refusal names it, free).

# 1 — quote (0.25 USDC; every refusal is free)
curl -X POST https://travel.brij.fi/shop/quote \
  -d '{"product_url":"https://shop.example.com/products/merino-crew-sweater",
       "options":{"Size":"M","Color":"Charcoal"},"quantity":2,
       "ship_to":{"country":"US","region":"CA","postal_code":"94107"}}'
# → offer_id "shop.example.com:q_…", breakdown (items, shipping, tax,
#   merchant_total) and total_amount — ALL-IN: merchant total + 4 USDC + 3 %.
#   422 options_required lists each option's values in stock: ask, retry.
#   202 quote_pending: retry the SAME request after Retry-After (15 s).

# 2 — escrow (0.10 USDC) — same body and answer as /air/intents
curl -X POST https://travel.brij.fi/shop/intents \
  -d '{"offer_id":"shop.example.com:q_…","funding_wallet":"YOUR_WALLET"}'
#   ⚠ SAVE customer_support_code NOW — it is never returned again.

# 3 — buy: pays the escrow amount and hands over the address
curl -X POST https://travel.brij.fi/shop/buy \
  -d '{"intent_id":"intent_…","recipient":{"given":"Ada","surname":"Lovelace",
       "phone":"+14155550100"},"ship_to":{"line1":"500 Howard St","city":"San Francisco",
       "region":"CA","postal_code":"94107","country":"US"}}'
#   region + ZIP must be the quoted ones (409 ship_to_changed, free).

# 4 — track (0.01 USDC): purchasing → ordered → confirmed → shipped (+ tracking)
curl -X POST https://travel.brij.fi/shop/orders \
  -H "X-Customer-Support-Code: …" -d '{"intent_id":"intent_…"}'
What protects you: the checkout is re-read before paying and must be exactly your quote (one line, your quantity, your ZIP, a total no higher); a human approves every payment; you are charged only when the merchant's DKIM-signed confirmation names the order we placed. No confirmation within 6 h → automatic refund. A parcel that never arrives: POST /shop/refund-requests.

Buying train tickets (rail)

Same flow as a product, with a search in front: trains have to be found.

# 1 — search (0.25 USDC): station or city names
curl -X POST https://travel.brij.fi/rail/search \
  -d '{"origin":"Paris","destination":"Lyon","depart_date":"2026-12-15","depart_after":"08:00","adults":1}'
# → journeys[] cheapest first: journey_id, times, price_from, total_from (all-in)

# 2 — quote one journey (0.25 USDC), optionally a fare ("Standard", "Flexible")
curl -X POST https://travel.brij.fi/rail/quote -d '{"journey_id":"thetrainline.com:d_…#0"}'
# → offer_id, breakdown, total_amount (all-in), expires_at

# 3 — escrow (0.10) then buy (escrow amount) with exactly the searched party
curl -X POST https://travel.brij.fi/rail/intents -d '{"offer_id":"…","funding_wallet":"YOUR_WALLET"}'
curl -X POST https://travel.brij.fi/rail/buy \
  -d '{"intent_id":"intent_…","passengers":[{"given_name":"Ada","family_name":"Lovelace","born_on":"1990-01-01"}]}'

# 4 — status (0.01): POST /rail/orders {intent_id} + X-Customer-Support-Code

Endpoints & prices

EndpointPriceWhat it does
POST /air/search0.10 USDC × 1–50 load multiplierLive two-tier flight search
POST /air/search-updatesfreePoll a progressive search for late quotes
POST /air/offer-details0.01 (fastbooking) / 0.10 (browser tier)Refresh one offer; browser-tier fare menu with baggage & conditions
POST /air/intents0.10 USDCCreate the booking intent + on-chain escrow
POST /air/bookescrow amountRegister passengers, trigger the booking
GET /air/intents/{id}freeBooking status (reduced projection)
GET /air/orders/{id}0.01 USDCAirline order + PNR (needs X-Customer-Support-Code)
POST /air/refund-requests0.10 USDCFile a refund request for human review
POST /shop/quote0.25 USDCExact all-in price of one product at a merchant's checkout
POST /shop/intents0.10 USDCCreate the purchase intent + on-chain escrow
POST /shop/buyescrow amountRecipient + address, trigger the purchase
POST /shop/orders0.01 USDCMerchant order number, shipping, tracking (needs X-Customer-Support-Code)
POST /shop/refund-requests0.10 USDCFile a refund request for human review
POST /rail/search0.25 USDCSearch trains on supported rail merchants
POST /rail/quote0.25 USDCExact all-in price of one journey
POST /rail/intents · /rail/buy · /rail/orders · /rail/refund-requests0.10 · escrow · 0.01 · 0.10Same as their /shop twins

The flight booking fee is 20 USDC + 2% of the ticket; the shop fee is 4 USDC + 3% of the merchant total. Both are included in every price the API returns and in expected_escrow_amount. Every displayed price on the web app is fee-inclusive; the wallet quote at signing is always the authority.

The clocks

ClockDurationMeaning
Offer freshness~20–30 minOffers expire after search; on 404, re-search
Lowcost fare menu~30 minA ##n fare books only while its menu is fresh (409 fare_menu_expired)
Intent bookability~20 minexpires_at: prices move, book promptly or re-create at the current price
On-chain escrow locksized per tierOutlives the whole settlement window, so a refund can never race a ticket
Lowcost capture hold24 hNo ticket email within the hold → automatic refund
Shop quote~20 minThe quote's expires_at; after it, quote again (409 offer_expired)
Shop capture hold6 hNo merchant confirmation within the hold → automatic refund

Refunds & support

The web app (humans)

app.brij.fi is the same marketplace with a wallet UI: search, compare fee-inclusive fares (browser-tier fare menus load live while you fill the passenger form), pay with your Solana wallet, and receive your ticket by email — PNR, itinerary, and before-you-fly instructions. Saved travellers and memberships (fee waivers by invite code) are optional conveniences; your wallet remains the identity.

© 2026 Brij Digital · Terms · Privacy · [email protected]