Getting started

Three calls to a
real reservation.

1Stay is hotel booking infrastructure for AI agents. Your agent is the interface; 1Stay is the booking engine. Connect the MCP server, then search, inspect, and hand the guest a checkout link.

Step zero

Connect the server

1Stay is a remote MCP server. Point any MCP client at it and eight tools load on connect.

Any MCP client — Claude, Cursor, Windsurf
{
  "mcpServers": {
    "1stay": {
      "url": "https://mcp.stayker.com/mcp"
    }
  }
}
Claude Code
$ claude mcp add 1stay --transport http https://mcp.stayker.com/mcp
stdio clients
$ npx 1stay-mcp

For direct HTTP calls, authenticate with a bearer token: Authorization: Bearer sk_live_…. Sandbox keys begin sk_test_; production keys begin sk_live_.

The canonical flow

Search → details → book

Every booking, in every client, follows the same three calls.

1

Search for hotels

Call search_hotels with dates plus either a location or both latitude and longitude. Note the parameter is guests_per_room, not guests.

// Tool: search_hotels
{
  "location": "Austin, TX",
  "check_in": "2027-01-15",
  "check_out": "2027-01-18",
  "guests_per_room": 2,
  "max_results": 10
}

// Returns: search_id, results[] with hotel_id, avg_nightly_rate, total_stay

Defaults worth knowing: max_results is 4 (max 15), radius is 25 miles (max 100), currency is USD. Check-in must fall within 340 days of today. Page through results with search_id + cursor.

2

Get hotel details

Call get_hotel_details with the hotel_id and the dates — rates cannot be priced without them. Returns room types, rate plans, cancellation policies, amenities, and the rate_code values book_hotel needs.

// Tool: get_hotel_details
{
  "hotel_id": "htl_x9y8z7",
  "check_in": "2027-01-15",
  "check_out": "2027-01-18",
  "guests": 2
}

// Returns: rates[] with rate_code, room types, cancellation policies

Pass accessible: true for ADA room types; the response always reports accessible_rooms_available either way.

3

Start checkout

Call book_hotel with the selected rate_code. It accepts no guest identity and no payment fields — those are collected on the checkout page, not in the conversation.

// Tool: book_hotel
{
  "hotel_id": "htl_x9y8z7",
  "rate_code": "RAC-STK-F8E2",
  "check_in": "2027-01-15",
  "check_out": "2027-01-18",
  "guests": 2
}

// Returns: checkout_url, total

All five of those fields are required. Pass external_reference_id to make the call idempotent and to retrieve the booking by your own reference later.

The reservation does not exist yet. book_hotel returns a checkout link. The hotel confirmation number is created only after the guest completes checkout — so an agent must never announce a booking on the strength of a checkout_url.

Know before you build

Four things that will bite you

  • 01 One room per booking. Each search, checkout, and reservation covers exactly one room. rooms accepts only 1. Multi-room is not in the first release.
  • 02 Rates expire. A quoted rate generally holds for about 15 minutes. Re-fetch rather than replaying a stale rate_code, and never silently substitute a changed price.
  • 03 Lookups key off the hotel's confirmation number — and a guest who lost it is never stuck. get_booking takes the hotel confirmation number only, and internal Stayker booking IDs are never accepted or disclosed. When the guest does not have it, resend_confirmation with their full name and email sends the confirmation to the address already on the booking; that email carries the number they then use to look up or cancel.
  • 04 Cancellation leaves the conversation. cancel_booking returns the hotel's policy and a first-party 1Stay URL where the guest confirms. It never cancels in-conversation and never estimates a refund, credit, or penalty.
Access

Sandbox first, then production

Sandbox keys (sk_test_) exercise the full API surface — same tools, same response shapes, same error codes — against a test inventory rather than the production catalogue. It holds fewer properties, and it does not cover every destination. Build and test against it; do not demo on it, and do not read catalogue coverage from it. Confirmations are simulated: no hotel is contacted, no guest is charged, and no reservation is created, enforced server-side. Sandbox access is free for 30 days, returns 5 hotels per search and 2 rate plans per hotel, and allows 100 searches a day.

Production (sk_live_) is $99/mo: live reservations, 15 hotels per search, all rate plans, and 50,000 searches included, then $0.002 per search.

An empty sandbox search is not an error. The test inventory does not cover every destination, so search_hotels can legitimately return no results for a city with plenty of hotels in production. Most major cities do populate — so if you are getting nothing, try a major metro before you start debugging your call. Secondary markets and smaller towns may have no sandbox coverage at all. Production coverage is not limited this way.

Same code, different key. Tool interfaces, response formats, and error codes are identical across tiers. Swapping sk_test_ for sk_live_ is the whole migration.