Fortrip

Changelog

What changed for callers of the API, the MCP tools, the CLI and the contract, release by release.

Fortrip's agent API is pre-release. Until general availability, breaking changes may happen. A breaking change ships only in a new major version of the contract, @fortrip/agent-contract, and is announced in the changelog with migration notes. After general availability, v1 will change only additively: new fields, endpoints, enum values and error codes.

The contract, @fortrip/agent-contract, and the CLI, fortrip, share one version number. Each entry lists breaking changes first, then what is new, then how to migrate. The values in an entry are the ones that release had.

4.3.0

Not released yet.

New

  • The contract exports more of the values these docs state, so a client can read them instead of copying them:
    • HTTP_ROUTES and ACCOUNT_ROUTES: each endpoint's method and path. routePath() builds a request path from an input.
    • RATE_LIMITS: the requests a token may make per scope and window.
    • ENABLED_REGIONS, from the new entry point @fortrip/agent-contract/regions: the regions a search can be scoped to.
    • PAY_WAYS and PAY_INPUT_WAYS: the ways an order is paid, and the way each field of the pay_order input pays by.
    • LIMITS gains tokenPaymentMaxUsd, payMinMinutesLeft (the time that must be left to pay for a token or wallet payment to be offered), payCutoffMinutes (the time left below which pay_order refuses), tokensPerOrder, wechatCodeMinutes and ordersPerStay (the orders one stay can have).
    • SUPPLIER_OUTCOME_STATUS: the HTTP status of supplier_unavailable for each details.outcome.
    • SEARCH_RULES, ORDER_HTTP, ME_SCOPES, MCP_SERVER_URL, SKILL_INSTALL_COMMAND, REPOSITORY_URL and DOCS_ORIGIN.
  • The API, the MCP tools and the CLI's commands are unchanged.

4.2.0

Released 2026-11-04.

New

  • Pay an order with Alipay or WeChat Pay. pay_order (POST /v1/orders/{orderId}/pay) takes method: "alipay_wechat_pay" with the order's total. The answer is the order, with a WeChat Pay code and an Alipay link in payment.wallets. The user pays once, by either. Both charge at once.
  • order.payment.wallets is always sent: { open, current, wechatPay, alipay }, or null when the order can't be paid this way and no wallet payment is open. wechatPay.qrData and wechatPay.qrImageUrl are null when there is no live code. A WeChat Pay code lasts 120 minutes.
  • The text of book_hotel, get_order and list_orders results has a consent paragraph for an order that offers the wallets. The contract exports it as WALLET_NEXT_STEP and walletNextStep.
  • CLI: fortrip orders pay <orderId> --wallet --total <total> prints both links, and draws the WeChat Pay code in a wide enough terminal.

Changed

  • limitPerHotel on get_hotel_offers (POST /v1/hotels/offers) defaults to 10 offers per hotel, up from 5. The maximum is still 20.
  • An order's payment.url is a Fortrip page, for paying and, after payment, for the order's status.

Migration

  • Nothing is required. To keep getting 5 offers per hotel, send limitPerHotel: 5.

4.1.0

Released 2026-11-04.

The schemas keep their shape. Most changes are to the text that agents and users read.

Changed

  • Paying by token: use a token only with a tool that can request one from the user's Link wallet; otherwise give payment.url and never ask for a token. Pay one way only. The charge is in USD.
  • payment_total_changed asks the agent to confirm the order's total, then retry with it and the same token.
  • Field descriptions are corrected or added:
    • payment.credentialLimits: the token must allow at least maxAmount and stay valid until at least expiresAt.
    • payment.handlers lists every reason it can be empty.
    • payment.url depends on requiresSignIn.
    • checkOut states the range: 1 to 15 nights, stay_unsupported (max_nights) beyond 15, invalid_request past 30. Validation is the same as in 4.0.0.
  • An order awaiting payment says it doesn't need cancelling: it expires unpaid.
  • API error messages no longer name MCP tools.
  • renderToolResult and renderError take an optional surface, "mcp" by default. With "cli", the text names CLI commands and flags instead of tools. The CLI's output uses it.

Migration

  • Nothing is required. A 4.0 or 4.1 CLI works with either server.

4.0.0

Released 2026-11-04.

A major release. It removes what was kept for older clients, and makes required what the server always sends.

Breaking changes

  • payment.handlers[].networkId is removed. schema, available_instruments and config { environment, business_profile } are required.
  • payment.handlers is always sent: [] when a token can't pay the order, with payment.credentialLimits null.
  • order.cancel is always sent.
  • A hotel's photos and a search hit's photo are always sent, null when there are none.
  • Each error code's details is required where the code defines it. search_too_broad's details.center is required and may be null. strictErrorEnvelope() is removed.
  • No token payment over $500, Link's cap per spend request. Such an order has empty payment.handlers, and pay_order answers payment_method_unavailable before anything is charged. Exactly $500 can still be paid by token.
  • The API takes only an OAuth bearer token as the caller's identity. OAuth authorization-server metadata is served on mcp.fortrip.ai only.
  • CLI:
    • With --json, a 429 without Fortrip's error envelope is reported as service_unavailable, retryable, instead of rate_limited. The exit code is still 4.
    • With --json, a local invalid_request always carries details.issues, empty for an error in the command line itself.
    • The 1.x and 2.x command names get no rename hints.

New

  • The hosted API and MCP server take the 3.5.0 additions: UCP's handler fields, and the token in payment.instruments.

Migration

  • Request the token with config.business_profile in place of networkId.
  • Treat an empty payment.handlers as "no token payment", instead of checking whether the field is present.
  • Replace strictErrorEnvelope() with strictOutput(errorEnvelope).
  • Update the CLI to 4.0.0. A 3.x CLI can't read the orders this server sends.

3.5.0

Released 2026-11-04.

New

  • payment.handlers[] gains UCP's handler fields, in UCP's snake case: schema, available_instruments and config { environment, business_profile }.
  • pay_order also takes the token in UCP's Complete Checkout form, payment.instruments. The selected instrument must be a stripe_payments card with a stripe_payment_token credential. A card number anywhere in the instruments is refused.
  • sharedPaymentTokenOf(input) returns the token from either form.
  • Agents are told to request the token with config.business_profile.

Deprecated

  • networkId, equal to config.business_profile. It is removed in 4.0.0.

The hosted API and MCP server moved from 3.4.0 straight to 4.0.0, so they serve these additions from 4.0.0.

3.4.0

Released 2026-11-03.

New

  • Pay an order with a Stripe shared payment token from the user's Link wallet: pay_order, POST /v1/orders/{orderId}/pay, with sharedPaymentToken and the order's total. The answer is the order, confirming, with its payment authorized: the amount is held, and charged once the hotel confirms.
    • A token pays one order only. Calling again with the same token answers what the first call answered and never charges twice.
    • Once pay_order succeeds, payment.url stops working. A payment that fails leaves the link open.
  • payment.handlers and payment.credentialLimits (maxAmount in cents, currency, expiresAt) appear on an order a token can pay: awaiting payment by link, in USD, with at least 15 minutes left to pay. A handler is { id, type, version, spec, networkId }, and agents request the token with the handler's networkId.
  • New error codes: payment_total_changed, order_not_payable, payment_in_progress, payment_credential_invalid, payment_declined, payment_action_required and payment_method_unavailable. New rate-limit scope: orders_pay.
  • PAY_NEXT_STEP, the rule for paying by token. It is in pay_order's description, and in the text of results that hold an order a token can pay. It never goes in nextStep.
  • CLI: fortrip orders pay <orderId> --token <token> --total <total>.

3.3.1

Released 2026-11-03.

Changed

  • A stay can be ordered again once its order is confirmed, cancelled or refused by the hotel. A party with none of an open order's guests gets an order of its own. order_exists now answers only:
    • an open order that shares a guest with the request, names compared in any letter case;
    • an earlier order that failed at the hotel with its outcome unknown;
    • a stay that has had 20 orders.
  • Another order of a stay needs a new offer, since an offer is ordered once (offer_already_ordered). When the new order replaces an unpaid one, the user pays only the new link; the earlier one expires unpaid.
  • The contract's wording changes to match. No schema change.

3.3.0

Released 2026-10-27.

New

  • Cancel an order under its terms: cancel_order, POST /v1/orders/{orderId}/cancel, with maximumPenalty. The answer is the order: cancelling, then cancelled. If the hotel refuses, the order is confirmed again with cancel.reason refused.
  • order.cancel: { available, reason, penalty, refund }. penalty and refund are in the charge currency. reason is one of CANCEL_REASONS.
  • New error codes: cancellation_changed, when the penalty is now above maximumPenalty, and order_not_cancellable, with details.reason. New rate-limit scope: orders_cancel.
  • CANCEL_NEXT_STEP, the consent rule for cancelling. It is in cancel_order's description, and ends the text of get_order and list_orders results that hold a cancellable order. It never goes in nextStep.
  • CLI: fortrip orders cancel <orderId> --max-penalty <amount>. Without --max-penalty it cancels nothing: it prints the order's penalty and exits with code 2.

3.2.0

Released 2026-10-27.

Changed

  • get_hotel_offers returns a spread of choices instead of the cheapest few. Up to limitPerHotel offers are picked in this order: the cheapest, the cheapest that can be cancelled free, the cheapest with breakfast, the cheapest of each other room, then the rest by price. They are listed cheapest first.
  • Offers a caller couldn't tell apart collapse into one. omitted.dominated counts them too.
  • No schema change.

3.1.0

Released 2026-10-26.

New

  • Hotel photos, on Fortrip's own URLs. A search hit's photo is the hotel's cover. A hotel's photos lists up to 8, cover first, and is null when there are none.
  • The MCP results of search_hotels, get_hotel and get_hotel_offers end with a hint on how to present hotels, exported as PRESENTATION_HINT.
  • The text of a search shows each hotel's cover URL, and the text of a hotel its first 4 photo URLs.

3.0.0

Released 2026-10-25.

The first release of Fortrip API v1. This changelog starts here.

  • The HTTP API on https://api.fortrip.ai: search hotels, read a hotel, get live offers, order an offer, and read and list orders.
  • The MCP server on https://mcp.fortrip.ai, with the tools get_planning_guide, search_hotels, get_hotel, get_hotel_offers, book_hotel, get_order and list_orders.
  • The CLI, fortrip: hotel and order commands, sign-in, the guide, and fortrip mcp, a local bridge to the MCP server. Text output by default, --json for one line of JSON, and exit codes 0 to 4.
  • The contract, @fortrip/agent-contract: the input and output schemas, error codes, limits, the tool and command specs, and the text renderers renderToolResult, renderError and renderGuide.
  • Ids are opaque, with the prefixes htl_, off_ and ord_.

On this page