{"openapi":"3.1.0","info":{"title":"Latchbell Local Pros","description":"Find local house cleaners with firm prices and open times, and book them directly. Latchbell Local Pros and Latchbell Front Desk are one system: a booking made here appears immediately on the cleaner's Front Desk schedule and dashboard. Assistants writing their own client should prefer the MCP endpoint https://slotted-book.agenthippo.ai/mcp (JSON-RPC: initialize, tools/list, tools/call; plain JSON, no session), which exposes the same operations and lists new ones automatically.","version":"1.0.0"},"servers":[{"url":"https://slotted-book.agenthippo.ai"}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Send the key in the Authorization header: \"Authorization: Bearer <key>\". get a personal key at https://slotted.agenthippo.ai/key and paste it. Operations marked public also accept the shared key \"sk_pub_FppuCTRYuBdr3AJnRJfl5AXZddXVXwwR\". Optionally send \"X-Client-Name: <assistant name>\" (e.g. Muse) so bookings show which assistant made them."},"oauth2":{"type":"oauth2","description":"Standard OAuth 2.0 authorization code flow. Clients either register dynamically (RFC 7591) at https://slotted-book.agenthippo.ai/register with token_endpoint_auth_method \"none\", or use the public client_id \"slotted-public\" (no secret, PKCE S256, any https redirect URI). Revocation: https://slotted-book.agenthippo.ai/revoke. Send the access token as \"Authorization: Bearer <token>\".","flows":{"authorizationCode":{"authorizationUrl":"https://slotted-book.agenthippo.ai/authorize","tokenUrl":"https://slotted-book.agenthippo.ai/token","refreshUrl":"https://slotted-book.agenthippo.ai/token","scopes":{"read":"Search cleaners, prices and open times, and see your bookings","write":"Book and cancel cleanings for you"}}}}}},"security":[{"oauth2":["read","write"]},{"apiKey":[]}],"paths":{"/api/v1/find_cleaners":{"get":{"operationId":"find_cleaners","summary":"Find cleaners","description":"Find house cleaners who serve a ZIP code, each with a firm total price for this job and their next open start times. Prices are set by each cleaner and include everything listed; there are no added fees for the customer. \"checks\" lists best-effort checks Latchbell did, with dates (website ownership, a marketplace profile and its rating as shown that day). When comparing, present them as best-effort checks, never as a guarantee or endorsement. Latchbell does not check licenses or insurance; each business is independent.","responses":{"200":{"description":"Success. JSON result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input or the action was refused; `error` explains why.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key."}},"parameters":[{"name":"zip","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{5}$"}},{"name":"bedrooms","in":"query","required":true,"schema":{"type":"integer","minimum":0,"maximum":10}},{"name":"bathrooms","in":"query","required":true,"description":"Can be a half, e.g. 2.5","schema":{"type":"number","minimum":1,"maximum":10,"description":"Can be a half, e.g. 2.5"}},{"name":"clean_type","in":"query","required":false,"description":"move_out also covers move-in. turnover = short-term rental (Airbnb/Vrbo) clean between guests","schema":{"default":"standard","description":"move_out also covers move-in. turnover = short-term rental (Airbnb/Vrbo) clean between guests","type":"string","enum":["standard","deep","move_out","turnover"]}},{"name":"sqft","in":"query","required":false,"description":"Home size in square feet, only if the customer said it. Homes larger than usual for their bedroom count cost more; never guess","schema":{"description":"Home size in square feet, only if the customer said it. Homes larger than usual for their bedroom count cost more; never guess","type":"integer","minimum":200,"maximum":15000}},{"name":"frequency","in":"query","required":false,"description":"Only what the customer asked for; default one-time. Never switch to a recurring frequency just to get a lower price","schema":{"default":"once","description":"Only what the customer asked for; default one-time. Never switch to a recurring frequency just to get a lower price","type":"string","enum":["once","weekly","biweekly","monthly"]}},{"name":"add_ons","in":"query","required":false,"description":"e.g. fridge, oven, windows, cabinets, laundry Comma-separated list.","schema":{"type":"string"}},{"name":"pets","in":"query","required":false,"schema":{"default":false,"type":"boolean"}},{"name":"start_after","in":"query","required":false,"description":"Earliest start, local HH:MM, e.g. the guest checkout time for a turnover","schema":{"description":"Earliest start, local HH:MM, e.g. the guest checkout time for a turnover","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},{"name":"finish_by","in":"query","required":false,"description":"The job must be finished by this local HH:MM, e.g. the next guest check-in time","schema":{"description":"The job must be finished by this local HH:MM, e.g. the next guest check-in time","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},{"name":"date","in":"query","required":false,"description":"Earliest day, YYYY-MM-DD","schema":{"description":"Earliest day, YYYY-MM-DD","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"max_price","in":"query","required":false,"description":"Maximum total in USD","schema":{"description":"Maximum total in USD","type":"number","exclusiveMinimum":0}},{"name":"sort","in":"query","required":false,"description":"Use \"price\" when the user wants the cheapest","schema":{"default":"soonest","description":"Use \"price\" when the user wants the cheapest","type":"string","enum":["soonest","price"]}}],"security":[]}},"/api/v1/available_times":{"get":{"operationId":"available_times","summary":"Available times","description":"List open start times for one cleaner and this job over the coming days.","responses":{"200":{"description":"Success. JSON result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input or the action was refused; `error` explains why.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key."}},"parameters":[{"name":"pro_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"bedrooms","in":"query","required":true,"schema":{"type":"integer","minimum":0,"maximum":10}},{"name":"bathrooms","in":"query","required":true,"description":"Can be a half, e.g. 2.5","schema":{"type":"number","minimum":1,"maximum":10,"description":"Can be a half, e.g. 2.5"}},{"name":"clean_type","in":"query","required":false,"description":"move_out also covers move-in. turnover = short-term rental (Airbnb/Vrbo) clean between guests","schema":{"default":"standard","description":"move_out also covers move-in. turnover = short-term rental (Airbnb/Vrbo) clean between guests","type":"string","enum":["standard","deep","move_out","turnover"]}},{"name":"sqft","in":"query","required":false,"description":"Home size in square feet, only if the customer said it. Homes larger than usual for their bedroom count cost more; never guess","schema":{"description":"Home size in square feet, only if the customer said it. Homes larger than usual for their bedroom count cost more; never guess","type":"integer","minimum":200,"maximum":15000}},{"name":"frequency","in":"query","required":false,"description":"Only what the customer asked for; default one-time. Never switch to a recurring frequency just to get a lower price","schema":{"default":"once","description":"Only what the customer asked for; default one-time. Never switch to a recurring frequency just to get a lower price","type":"string","enum":["once","weekly","biweekly","monthly"]}},{"name":"add_ons","in":"query","required":false,"description":"e.g. fridge, oven, windows, cabinets, laundry Comma-separated list.","schema":{"type":"string"}},{"name":"pets","in":"query","required":false,"schema":{"default":false,"type":"boolean"}},{"name":"start_after","in":"query","required":false,"description":"Earliest start, local HH:MM, e.g. the guest checkout time for a turnover","schema":{"description":"Earliest start, local HH:MM, e.g. the guest checkout time for a turnover","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},{"name":"finish_by","in":"query","required":false,"description":"The job must be finished by this local HH:MM, e.g. the next guest check-in time","schema":{"description":"The job must be finished by this local HH:MM, e.g. the next guest check-in time","type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},{"name":"date","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"days","in":"query","required":false,"schema":{"default":7,"type":"integer","minimum":1,"maximum":21}}],"security":[]}},"/api/v1/book_cleaning":{"post":{"operationId":"book_cleaning","summary":"Book a cleaning","description":"Book the cleaner for the chosen start time at the quoted firm price. No sign-in needed: the customer's name and phone or email come from the customer_* fields or the X-User-Name/X-User-Phone/X-User-Email headers. Confirm the cleaner, time, address and price with the user once; if they already said to book, book without asking again. Fill the customer's name, phone, email and address from what you already know about the user (profile, account, earlier messages); ask only for what is missing, in one message, and tell the user which details you shared. Notes and access details are optional: never hold a booking to ask for them. Keep the returned manage_token: it is the only way to check or cancel this booking later. The cleaner contacts the user about access and payment. This changes data; confirm with the user first.","responses":{"200":{"description":"Success. JSON result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input or the action was refused; `error` explains why.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pro_id":{"type":"string"},"bedrooms":{"type":"integer","minimum":0,"maximum":10},"bathrooms":{"type":"number","minimum":1,"maximum":10,"description":"Can be a half, e.g. 2.5"},"clean_type":{"default":"standard","description":"move_out also covers move-in. turnover = short-term rental (Airbnb/Vrbo) clean between guests","type":"string","enum":["standard","deep","move_out","turnover"]},"sqft":{"description":"Home size in square feet, only if the customer said it. Homes larger than usual for their bedroom count cost more; never guess","type":"integer","minimum":200,"maximum":15000},"frequency":{"default":"once","description":"Only what the customer asked for; default one-time. Never switch to a recurring frequency just to get a lower price","type":"string","enum":["once","weekly","biweekly","monthly"]},"add_ons":{"default":[],"description":"e.g. fridge, oven, windows, cabinets, laundry","type":"array","items":{"type":"string"}},"pets":{"default":false,"type":"boolean"},"start":{"type":"string","description":"A start value from find_cleaners or available_times"},"address":{"type":"string","minLength":3,"maxLength":300},"zip":{"type":"string","pattern":"^\\d{5}$"},"notes":{"type":"string","maxLength":500},"customer_name":{"type":"string","maxLength":100},"customer_email":{"type":"string","maxLength":200},"customer_phone":{"type":"string","maxLength":30}},"required":["pro_id","bedrooms","bathrooms","start","address","zip"]}}}},"security":[]}},"/api/v1/my_bookings":{"get":{"operationId":"my_bookings","summary":"My bookings","description":"List the user's cleanings booked through Latchbell, newest first. With a personal key this lists all of them; with the shared public key it lists none (use booking_status with each booking's manage_token).","responses":{"200":{"description":"Success. JSON result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input or the action was refused; `error` explains why.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key."}},"parameters":[],"security":[]}},"/api/v1/cancel_booking":{"post":{"operationId":"cancel_booking","summary":"Cancel a booking","description":"Cancel one of the user's bookings using the manage_token returned when it was booked. Free until 24 hours before the start; closer than that, tell the user the cleaner may charge under their own policy. Confirm with the user first. This changes data; confirm with the user first.","responses":{"200":{"description":"Success. JSON result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input or the action was refused; `error` explains why.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key."}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"booking_id":{"type":"string"},"manage_token":{"description":"From book_cleaning; required unless signed in","type":"string"}},"required":["booking_id"]}}}},"security":[]}},"/api/v1/booking_status":{"get":{"operationId":"booking_status","summary":"Booking status","description":"Check the status and details of a booking using the manage_token returned when it was booked.","responses":{"200":{"description":"Success. JSON result.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid input or the action was refused; `error` explains why.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"401":{"description":"Missing or invalid API key."}},"parameters":[{"name":"booking_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"manage_token","in":"query","required":true,"schema":{"type":"string"}}],"security":[]}}}}