1Stay API
Reference

1Stay gives AI agents and applications access to real hotel inventory — 300,000+ properties across 140+ countries — through a simple MCP server. Reservations use the hotel's own confirmation number. Loyalty points are eligible. You're never the merchant of record.

The MCP server name is 1stay at endpoint mcp.stayker.com. There are 8 tools covering the complete booking lifecycle.

Early Access. 1Stay is onboarding developers by application. Sandbox access is free for 30 days — production requires approval and a Stripe account. Apply for access →

MCP Server Details

MCP Configuration
// Claude Desktop / claude_desktop_config.json
{
  "mcpServers": {
    "1stay": {
      "url": "https://mcp.stayker.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
Authentication
Authorization: Bearer YOUR_API_KEY

What Makes This Different

Most hotel APIs are OTA-style: you buy inventory, mark it up, you're the merchant. 1Stay is infrastructure: your agent connects guests to hotels directly. The hotel charges the guest. You build the experience, your users pay for your product — 1Stay is the booking layer that makes it possible. No inventory risk, no float, no chargebacks.

Three things that matter to your users: Loyalty points are eligible (guest books direct-equivalent). The hotel's own confirmation number appears in the guest email. And if the guest has a problem, they call the hotel — not you.

Muse
Integration

Release in Muse is pending. The 1Stay integration for Muse is in review and is not yet available to Muse users. This section describes how it works at launch, and we will update it if anything changes before release.

1Stay for Muse runs on its own endpoint and supports the full booking lifecycle with the same 8 tools as every other 1Stay connection. What differs is how bookings and cancellations are completed: in Muse, the guest approves the final booking, and any cancellation, in the conversation. The general developer flow in the rest of these docs is unchanged.

Muse Endpoint

  • Connector name: 1Stay
  • Muse MCP endpoint: https://mcp.stayker.com/mcp/muse
  • Authentication: none. The Muse endpoint accepts connections without an API key and does not use OAuth.
  • This endpoint is separate from the general developer endpoint at https://mcp.stayker.com/mcp.

Tools in Muse

  • search_hotels — search by location and dates, one room per search in the first release
  • get_hotel_details — room types, live rates, cancellation policies, amenities
  • book_hotel — prepare, check, and confirm a booking, as described below
  • get_booking / lookup_booking — find and retrieve a reservation. Verification always requires the guest's full name, plus either the hotel confirmation number or the booking email together with the last four digits of the card
  • resend_confirmation — resend the confirmation to the email on file
  • cancel_booking — prepare, check, and confirm a cancellation, as described below
  • search_tools — discover tools at runtime

Booking in Muse

The user must accept or deny every booking. Booking is a sensitive write. Every book_hotel call requires the user to choose Allow once or Deny, and it cannot be set to Always allow. Nothing is booked or charged unless the user accepts the exact booking summary.
1

Prepare

book_hotel with action: "prepare" holds the selected quote and returns a link to a secure 1Stay form. The guest enters their name and contact details there, never in the conversation. The card fields on that form are Basis Theory Elements, so card data goes directly to Basis Theory's vault and never reaches Stayker's servers or Muse. Submitting the form does not book or charge anything.

2

Review

action: "status" returns READY_FOR_APPROVAL with an approval summary and quote hash once the form is complete. Muse shows the summary to the user before they approve.

3

Confirm

action: "confirm", sent with the exact approval summary and quote hash, creates the reservation and returns CONFIRMED with the hotel confirmation number. It does not return a checkout link.

The approval summary shows:

  • The hotel (the seller), with 1Stay by Stayker as the service provider
  • Room type, rate plan, dates, guest count, and one room
  • Room subtotal, taxes, any hotel fees, and the total, in the stated currency
  • The 1Stay service fee, shown as its own line when the booking has one (some bookings have no service fee)
  • The rate's cancellation policy and guarantee or deposit policy
  • When each charge happens, and that there are no recurring charges

Who Charges What

  • The stay: the hotel is the merchant of record and charges the room rate, taxes, and any hotel fees directly, under the rate's guarantee or deposit and cancellation policy.
  • The 1Stay service fee: some bookings have no service fee. When there is one, it is charged by Stayker and processed through Stripe, as a separate charge. It is authorized before booking and charged only after the hotel confirms the reservation. It is non-refundable once the booking is confirmed, except where required by law.

The approval summary shows the stay and any service fee as separate lines, and together they match what the guest is charged.

Card data never touches Stayker or Muse. Card details are never typed in the conversation and are never sent as MCP tool parameters. They go from the Basis Theory card fields straight to Basis Theory's vault. Stayker receives only a token, plus the card brand and last four digits, never the full card number or security code. The last four digits may be used later to verify a reservation. Inside the vault, the card number is passed to the hotel to guarantee the reservation (never the security code), and, when there is a service fee, a Stripe payment token is created for it.

Price Changes and Failures

  • If the rate, taxes, fees, or policy change before confirmation, 1Stay does not book at the new price. It returns the change and requires a new review and approval.
  • If the approved details change in any way, the quote hash no longer matches and the booking is refused until the user approves again.
  • 1Stay never creates a duplicate booking or charge. A FAILED or EXPIRED attempt needs a new quote and fresh approval.

Cancellation in Muse

The user must accept or deny every cancellation. Cancellation is a sensitive write. Every cancel_booking call requires the user to choose Allow once or Deny, and it cannot be set to Always allow. Nothing is cancelled unless the user accepts the exact cancellation summary.
1

Verify

lookup_booking verifies the guest and returns a verification_token scoped to that one booking. Knowing a confirmation number alone is not enough to cancel.

2

Prepare

cancel_booking with action: "prepare", the guest's name, the confirmation number, and the verification token returns READY_FOR_APPROVAL with an approval summary, an approval hash, and a cancellation_session_id. Preparing does not cancel anything or send email. Muse shows the summary to the user before they approve.

3

Confirm

The user accepts or denies the cancellation in Muse. If they deny it, nothing is cancelled. After the user chooses Allow once, action: "confirm", sent with the exact approval summary, approval hash, and session ID, cancels the reservation and returns CANCELLED with a receipt. One cancellation confirmation is sent to the booking email shown in the summary. It does not return a cancellation page.

The cancellation summary shows:

  • The hotel, the hotel confirmation number, dates, and room
  • The cancellation policy and any cancellation deadline recorded with the reservation
  • The guarantee policy and any financial terms on file
  • The email address that will receive the cancellation confirmation
  • 1Stay does not estimate a refund, credit, penalty, or hotel charge. Cancellation terms are set by the hotel.
  • 1Stay returns CANCELLED only when the hotel's system confirms the reservation is cancelled. If the reservation is already cancelled, the tool says so instead of cancelling again.
  • If the summary changes or expires before confirmation, the cancellation is refused until the user reviews and approves a new summary.

Status and Support

After booking, Muse can check booking status, resend confirmations, and cancel using the hotel confirmation number and the verification above. Guests can get help at stayker.com/service or service@stayker.com. Data handling for Muse is covered in the Muse addendum to the MCP Data Processing Terms.

Quick
Start

From zero to a hotel checkout link in three tool calls. The canonical flow for any AI agent.

1

Search for hotels

Call search_hotels with location (or lat/lng coordinates), dates, and guest count. Returns a list of available properties with rates. Note the parameter is guests_per_room, not guests.

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

// Returns: list of hotels with hotel_id, rates, rate_code per rate
2

Get hotel details

Call get_hotel_details with the hotel_id and the dates — both are required, since rates cannot be priced without them. Returns room types, rates, cancellation policies, amenities, and everything your agent needs.

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

// Returns: rates[], room types, cancellation policies, amenities
3

Book it

Call book_hotel with the selected rate_code. It accepts no guest identity or payment fields and returns secure checkout, where the guest supplies them.

Example
// 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 — guest pays at checkout URL

API Keys &
Auth

The MCP endpoint accepts connections without a key and does not use OAuth. For developer-scoped access and attribution, send your API key as a Bearer token in the Authorization header. API keys are issued per application and scoped to either sandbox or production mode.

Request Header
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Sandbox keys begin with sk_test_. Production keys begin with sk_live_. When you apply, we email you a one-time link to reveal your sandbox key.

Never expose your API key in client-side code. All 1Stay API calls should be made from your server. API keys can make real bookings that incur real charges.

Key Scopes

Production plans include 50,000 searches per month with overage billed at $0.002/search. Sandbox keys use test properties and never charge guests. Production keys access live inventory and create real reservations.

search_hotels

Search for exactly one room by location and dates. Returns a representative selection of properties across brands (not a ranking) with rates and a search_id valid for 15 minutes. The first 1Stay release supports one room per search and reservation.

🔍
search_hotels
Find available hotels with live rates for a given location and date range
▲ collapse
Parameters
ParameterTypeRequiredDescription
locationstringoptionalCity, address, venue, or landmark. e.g. "Nashville, TN" or "Times Square, NYC". Required unless latitude and longitude are both provided.
check_instringrequiredCheck-in date. ISO 8601 format: YYYY-MM-DD. Must be today or later.
check_outstringrequiredCheck-out date. ISO 8601 format: YYYY-MM-DD. Must be after check_in.
guests_per_roomintegeroptionalGuests per room. Default: 2.
roomsintegeroptionalMust be 1. Omit this field or set it to 1; multi-room searches are not supported in the first release.
latitudenumberoptionalLatitude — must be provided together with longitude.
longitudenumberoptionalLongitude — must be provided together with latitude.
radiusintegeroptionalSearch radius in miles. Default: 25. Max: 100.
currencystringoptionalISO 4217 currency code for rates. Default: USD.
max_resultsintegeroptionalMax hotels to return. Default: 6. Max: 6. Use the returned cursor to load more pages.
search_idstringoptionalSearch ID from previous results — pass with cursor to fetch the next page.
cursorstringoptionalPagination cursor from a previous search response.
Example Request
{
  "location": "Nashville, TN",
  "check_in": "2026-06-12",
  "check_out": "2026-06-15",
  "guests_per_room": 2
}
200 OK Success Response
{
  "search_id": "srch_a1b2c3d4e5f6",
  "total_results": 4,
  "cursor": "next-page-token",
  "has_more": true,
  "results": [
    {
      "hotel_id": "htl_x9y8z7w6",
      "name": "The Hermitage Hotel",
      "star_rating": 5,
      "total_stay": 654.37,
      "avg_nightly_rate": 189.00,
      "booking_fee": 7.00,
      "currency": "USD",
      "reward_points_eligible": true
    }
  ]
}

get_hotel_details

Get room types, live rates, amenities, and cancellation policies for a specific hotel. This is the tool your agent calls before booking — it returns rate_code values needed by book_hotel. Rate codes expire in ~15 minutes.

🏨
get_hotel_details
Room types, live rates, cancellation policies, and amenities. Returns rate_codes for booking.
▼ expand
Parameters
ParameterTypeRequiredDescription
hotel_idstringrequiredHotel ID from a search_hotels response
check_instringrequiredCheck-in date (YYYY-MM-DD)
check_outstringrequiredCheck-out date (YYYY-MM-DD)
guestsintegeroptionalNumber of guests (default 2)
roomsintegeroptionalMust be 1. Hotel details price exactly one room in the first release.
accessiblebooleanoptionalReturn accessible (ADA) room types instead of standard ones. Omitted by default because hotels list many near-identical accessible variants. The response always reports accessible_rooms_available, so call again with accessible: true when a guest needs one.
Example Request
{
  "hotel_id": "TP-MC-DALCC",
  "check_in": "2026-06-12",
  "check_out": "2026-06-15",
  "guests": 2
}
200 OK
{
  "hotel": {
    "hotel_id": "TP-MC-DALCC",
    "name": "Dallas Marriott City Center",
    "chain": "Marriott",
    "check_in_time": "15:00",
    "check_out_time": "12:00"
  },
  "rooms": [
    {
      "room_id": "rm_01",
      "name": "King Guest Room",
      "description": "One king bed, city view",
      "bed_type": "King",
      "max_occupancy": 2,
      "rate_plans": [
        {
          "rate_code": "RAC-STK-A1B2",
          "name": "Best Available Rate",
          "avg_nightly_rate": 189.00,
          "subtotal": 572.00,
          "taxes": 82.37,
          "total_with_taxes": 654.37,
          "currency": "USD",
          "nightly_breakdown": [
            { "date": "2026-06-12", "amount": 189.00 },
            { "date": "2026-06-13", "amount": 189.00 },
            { "date": "2026-06-14", "amount": 189.00 }
          ],
          "refundable": true,
          "cancellation_policy": "Free cancellation until 48hrs before arrival",
          "reward_points_eligible": true,
          "booking_type": "Direct hotel confirmation"
        }
      ]
    }
  ],
  "rate_quote_expires_at": "2026-06-10T14:45:00Z",
  "rate_quote_ttl_seconds": 900
}
Rate codes expire in ~15 minutes. If you need to book, call book_hotel with the rate_code before it expires. If expired, call get_hotel_details again for fresh rates.

book_hotel

Start secure checkout for exactly one room using a rate_code from get_hotel_details. The tool accepts no guest identity or payment fields. A reservation is created only after the guest completes checkout.

✅
book_hotel
Create a secure checkout handoff for exactly one room.
▼ expand
Parameters
ParameterTypeRequiredDescription
hotel_idstringrequiredHotel ID from a search_hotels or get_hotel_details response
rate_codestringrequiredRate code from get_hotel_details response
check_instringrequiredCheck-in date. ISO 8601 format: YYYY-MM-DD
check_outstringrequiredCheck-out date. ISO 8601 format: YYYY-MM-DD
guestsintegerrequiredNumber of adult guests
external_reference_idstringoptionalYour own reference ID for this booking. Stored for your records.
Payment happens outside the conversation. The checkout_url returned by this tool is where the guest supplies identity and payment details. The reservation is not confirmed until checkout completes. Checkout and its live rate expire in approximately 15 minutes.
Example Request
{
  "hotel_id": "htl_x9y8z7w6",
  "rate_code": "RAC-STK-F8E2",
  "check_in": "2026-06-12",
  "check_out": "2026-06-15",
  "guests": 2
}
200 OK
{
  "status": "ACTION_REQUIRED",
  "message": "Complete the reservation on the secure checkout page.",
  "checkout_url": "https://book.1stay.ai/checkout/…",
  "total_with_taxes": 567.00,
  "booking_fee": 7.00,
  "currency": "USD",
  "expires_in_minutes": 15
}

get_booking

Retrieve an existing reservation exclusively by the hotel's confirmation number. Anonymous callers also pass the booking-scoped verification token returned by lookup_booking. Internal Stayker booking IDs are never accepted or disclosed through MCP.

📋
get_booking
Reservation details by hotel confirmation number only.
▼ expand
Parameters
ParameterTypeRequiredDescription
confirmation_numberstringrequiredHotel confirmation number shown in the guest's confirmation email
verification_tokenstringoptionalNot needed when authenticated with your own API key — your access is already scoped to your own bookings. The parameter exists for authless guest-facing callers, which must obtain a token from lookup_booking first; it does not apply to your integration.
200 OK
{
  "status": "confirmed",
  "confirmation_number": "HLC-98234",
  "hotel": "The Hermitage Hotel",
  "check_in": "2026-06-12",
  "check_out": "2026-06-15",
  "guest_name": "Jane Smith",
  "total": 567.00,
  "created_at": "2026-06-10T14:52:33Z"
}

lookup_booking

Look up a reservation with identity verification. The guest must provide their name plus at least one verification factor. Returns a booking summary with status, dates, and hotel information.

🔎
lookup_booking
Look up a reservation with identity verification.
▼ expand
Parameters
ParameterTypeRequiredDescription
first_namestringrequiredGuest first name on the reservation
last_namestringrequiredGuest last name on the reservation
confirmation_numberstringoptional*Hotel confirmation number — provide this, or use email together with last_four_card
emailstringoptionalEmail address used when booking — required with last_four_card; never sufficient on its own
last_four_cardstringoptional*Exactly the last 4 digits of the card used to book (requires email); never the full card number
check_in_datestringoptionalOptional check-in date (YYYY-MM-DD) to narrow repeat stays
Identity verification required. Provide first_name + last_name plus either confirmation_number, or email together with last_four_card. An email address on its own is not enough. check_in_date is optional and only narrows the match.
200 OK
{
  "status": "confirmed",
  "confirmation_number": "HLC-98234",
  "hotel": "The Hermitage Hotel",
  "check_in": "2026-06-12",
  "check_out": "2026-06-15",
  "guest_name": "Jane Smith"
}

resend_confirmation

Resend a confirmation using either the hotel confirmation number, or blind full-name + email recovery when the guest does not know it. Recovery never reveals whether a reservation matched and sends only to the email already on file. The email contains the hotel confirmation number needed for lookup or cancellation.

📧
resend_confirmation
Resend confirmation email to guest.
▼ expand
Parameters
ParameterTypeRequiredDescription
confirmation_numberstringoptional*Hotel confirmation number; alternatively provide first_name, last_name, and email
first_namestringoptional*Required with last_name and email for blind recovery
last_namestringoptional*Required with first_name and email for blind recovery
emailstringoptional*Used to find a match; mail is sent only to the stored address
200 OK
{
  "status": "sent",
  "message": "Confirmation email has been resent to the email address on file."
}

cancel_booking

Create a secure cancellation handoff. The guest's name and hotel confirmation number must match. The tool returns the hotel's cancellation policy and a first-party 1Stay URL; it never cancels the reservation in the conversation.

❌
cancel_booking
Return the hotel policy and a secure 1Stay cancellation page. Never cancels in conversation.
▼ expand
Parameters
ParameterTypeRequiredDescription
first_namestringrequiredGuest's first name. Must match the booking record.
last_namestringrequiredGuest's last name. Must match the booking record.
confirmation_numberstringrequiredHotel confirmation number from the booking
Cancellation leaves the conversation. This tool returns the hotel cancellation policy on file and a secure 1Stay page. The guest must open that page, review the policy, and explicitly confirm there. 1Stay does not estimate a refund, credit, penalty, or amount the hotel may charge. Do not state that the reservation is cancelled unless the secure page reports success. In Muse, cancellation is approved and completed in the conversation instead; see Muse Integration.
200 OK
{
  "status": "ACTION_REQUIRED",
  "message": "Review and confirm on the secure cancellation page.",
  "confirmation_number": "HLC-98234",
  "cancellation_url": "https://book.1stay.ai/cancel/…",
  "cancellation_url_expires_at": "2026-06-11T09:24:22Z",
  "cancellation": { "policy_summary": "Hotel policy on file" }
}

search_tools

Discover available MCP tools and their capabilities at runtime. Useful for agents that want to dynamically understand what operations are supported without relying on static documentation.

🛠
search_tools
List and describe available MCP tools at runtime. No parameters required.
▼ expand

No parameters required. Returns the complete list of tools with descriptions and parameter schemas. Accepts an optional keyword string (e.g. search, book, cancel, details) to filter the list.

200 OK
{
  "server": "1stay",
  "version": "1.0.0",
  "tools": [
    {
      "name": "search_hotels",
      "description": "Search available hotels by location and dates",
      "parameters": { /* schema */ }
    }
    // ... all 8 tools
  ]
}

Error
Codes

All errors return a JSON body with an error field (machine-readable code) and a message field (human-readable). Design your agent to handle these gracefully.

HTTPError CodeWhen / What to Do
200—Idempotency hit — same key, booking already created. Returns original booking.
201—Booking created successfully.
400invalid_requestMissing or invalid fields. Check guest data and required params.
400cache_id_invalidrate_code doesn't exist. Did you use a code from a different search?
401unauthorizedAPI key missing, invalid, or revoked.
409rate_changedRate changed between search and booking. See Rate Change Handling.
410rate_unavailableRoom/rate no longer available. Search again.
410cache_expiredRate quote expired (~15 min). Call get_hotel_details again.
429budget_exceededDaily search or booking budget exhausted. Resets midnight UTC.
500booking_failedUpstream error. No booking was created. Safe to retry with same idempotency key.

Rate Change
Handling

Hotel rates are live inventory. Any price difference between when you called get_hotel_details and when you call book_hotel may trigger a 409 rate_changed response — even a difference of $0.01. No exceptions. No silent overrides. The guest always sees every change.

Zero tolerance policy. Rate changes up, down, or sideways all require guest confirmation. This protects your users and keeps you off the hook.
409 rate_changed Response
{
  "error": "rate_changed",
  "original_rate": { "nightly": 189.00, "total": 567.00 },
  "new_rate": { "nightly": 209.00, "total": 627.00 },
  "difference": { "nightly": 20.00, "total": 60.00, "direction": "increase" }
}

If you receive a rate_changed response, surface the new rate to the guest and let them decide. To proceed at the new rate, start a fresh book_hotel call. If the guest declines, call search_hotels again to find alternatives.

What your agent should say

ScenarioSuggested Agent Response
Rate increased"The hotel just updated this room from $189 to $209/night — that's $60 more for your stay. Want to book at the new rate or look at other options?"
Rate decreased"Good news — the rate dropped from $209 to $189/night, saving you $60. Want me to lock it in?"
Small change"The rate changed slightly from $189.00 to $189.47/night — likely a tax adjustment. That's $1.41 more total. Shall I proceed?"

Access
Tiers

API capabilities and limits vary by access tier. All tiers use the same endpoints, response formats, and error codes — only the data volume and booking behavior differ.

Capability Sandbox Production Enterprise
Key prefix sk_test_ sk_live_ sk_live_
Hotels per search 5 15 Custom
Rate plans per hotel 2 All available All available
Bookings Simulated only Live reservations Live reservations
Searches / month 100 / day 50,000 included Custom
Search overage — $0.002 / search Custom
Monthly fee Free (30 days) $99 / mo Custom
Platform fee — Small fee / booking Custom
Booking service fee — Set your own via Stripe Connect Custom structure
Cancellations Simulated Live Live
Duration 30 days Ongoing Contract term
Same code, different key. Your integration code is identical between sandbox and production. Swap sk_test_ for sk_live_ and you're live. Response formats, error codes, and tool interfaces don't change.

Sandbox
Mode

Sandbox keys (sk_test_...) run against a test inventory rather than the production catalogue, and make no real reservations. The API surface is identical — same tools, same response shapes, same error codes — but it holds fewer properties and does not cover every destination. Most major cities populate; secondary markets and smaller towns may return nothing at all. An empty sandbox search is expected behaviour rather than an integration fault, and production coverage is not limited this way — if a search comes back empty, retry a major metro before debugging the call. Use sandbox for development and integration testing. Do not demo on it, and do not judge catalogue coverage from it.

Sandbox keys cannot create real bookings. Any call to book_hotel with a sk_test_ key returns a simulated confirmation. No hotel is contacted, no guest is charged, no reservation is created. This is enforced server-side and cannot be bypassed.
30-day trial. Sandbox access is valid for 30 days from approval. A reminder goes out at day 25. If you need more time, a self-serve extension is available once from your dashboard. After that, the path forward is production — or a conversation.
Sandbox is production-identical. Same response format, same error codes, same rate change handling — just with test properties and no real bookings. Your integration code doesn't change between sandbox and production.

Switch from sandbox to production by swapping your key from sk_test_ to sk_live_. No other code changes required.

Questions? Email hello@1stay.ai.