Guide for host platforms
This guide takes a host platform from nothing to Level 3. Each level is useful on its own; stop wherever it makes sense. It follows draft 0.2.
Before you start
- You need a domain you serve over HTTPS, and one calendar per home.
- Field tables in the specification and the JSON Schemas in the repository are normative; this guide is not.
- Clone the repository.
tools/mock_host.pyis a working Level 1 host platform in one file, andtools/conformance.pychecks yours.
Level 0: Listed
The goal: an assistant reading your site or your API can describe each home accurately and say why it fits a traveller. No Poppy sessions, no tokens.
- Write each home's facts with its host. Who it suits, who it does not, check-in and check-out times, what is and isn't included, parking, pets, children, noise, backup power, house rules, cancellation in one sentence, and what the host does when something breaks. See §6.2. Do not generate facts the host has not reviewed.
- Set the home's time zone (
Asia/Kolkata,Europe/Lisbon). Every date and local time about the home is in it. - Publish the home's public page with those facts as HTML and schema.org
Accommodationmarkup (§6.5). - Serve the same data as JSON at
GET {endpoint}/homesandGET {endpoint}/homes/{home_id}, with no token, echoing theLivStay-Revisionheader (§4.3). - Declare protection for every home (§6.4). A home without it is not published.
- Publish
poppy.jsonat/.well-known/poppy.json:
{
"protocol_version": "0.2",
"organization": { "name": "Example Stays", "domain": "stays.example" },
"web": {},
"extensions": {
"livstay.org/stays": {
"version": "0",
"revision": "0.2",
"endpoint": "https://stays.example/livstay/v0",
"level": 0
}
}
}
Check: python3 tools/conformance.py https://stays.example passes every L0 check, and the facts in your JSON and on your page match, field by field.
Level 1: Priced
Still no tokens. Quotes are public.
- List your API in
poppy.jsonapis(openapipointing at your copy ofopenapi/livstay-0.2.yaml). - Availability.
GET {endpoint}/homes/{home_id}/availabilityfrom your calendar (§7.1). - Signing key. Generate an ES256 (P-256) key pair in a key service, publish the public key as a JWK Set with
kid,use: "sig"andalg: "ES256", and list it inkeys(§13.4). - Quotes.
POST {endpoint}/homes/{home_id}/quotesreturns201and a signed Quote (§7.2): - price from the whole party: adults, children's ages, pets; - round each line to the currency's minor unit, then make sure lines, total, payment schedule and refunds reconcile (§2.1); - sign the canonical JSON of the Quote withoutsignature(§13.1).tools/livstay_jws.pydoes this in 40 lines. - Honour and keep quotes. A booking proposed from an unexpired Quote is charged its total or fails with
dates_unavailable. Serve kept Quotes atGET {endpoint}/quotes/{quote_id}.
Check: every L1 check passes, including signature and reconciliation. Then change a rate after issuing a Quote and book from it: the old price must hold.
Level 2: Reachable
- Poppy sessions. An OAuth server at
auth.issuerthat issues signed-out Session Tokens to agents (client assertions, DPoP). No sign-in yet. - Conversations. Implement Poppy conversations and list them in
agent.protocols. Accept enquiries in signed-out sessions with no scope, and route each to the host as a person (§8). Host replies havesender: "human". - Reply times. Tell agents when to expect an answer, from the host's real median reply time.
- Reports. Accept mismatch reports (§6.6) and Poppy feedback.
Check: send an enquiry without signing in, answer it from the host's phone, and confirm the agent sees responder: "human".
Level 3: Bookable
- Sign-in and scopes. Add Poppy Direct Sign-In, able to grant
poppy:read,livstay:book,livstay:share_contactandlivstay:share_trip_context, each described inauth.custom_scopes. - Operations. Implement the Poppy
operationsextension version"1": proposed, confirmed, tracked and cancelled operations, executed at most once, never changed after confirmation. - Bookings.
POST {endpoint}/bookingsturns a Quote into a proposed booking operation and holds the calendar for up to 15 minutes (§9). Report the tier outcome interms.livstay.tier; setuser_approval_required: truewhenever money moves; write asummarya traveller can decide from. - Completion. On confirmation, create the completion record with a fixed
complete_byand the payment and identity steps (§9.5). Succeed when every step is done; fail and release the dates whencomplete_bypasses. - Requests and counters, if any home is not instant-book (§10). Each counter carries its own new Quote, and can only be kinder than the published terms.
- Events. Serve each booking's event feed (§12.2), with a Receipt on every money movement, claim and host cancellation.
- Booking conversation. Accept the conversation the agent opens for a booking; hold host messages and announce them with
message_waitinguntil it does (§12.3). - Contact.
PUT,GETandDELETEon/bookings/{booking_id}/contact(§12.4). - Privacy and limits. Delete trip context within 24 hours of a failed or abandoned proposal. Cap open holds per traveller and per agent (§15.3).
Check: confirm the same operation twice and see one booking; let complete_by pass and see the dates released and nothing charged; verify every Receipt in the feed against your keys.
What hosts should see
Every action an agent takes appears on the booking as the host would describe it: who booked, through which agent, what was approved, what was paid, and the receipt. Hosts should never have to read JSON to know what happened.