{"openapi":"3.1.0","info":{"title":"Linesteward API","description":"The Linesteward REST API: your calls, messages and bookings, your businesses' details and facts, and\nyour webhooks. Every request needs an API key (`Authorization: Bearer ls_live_...`), made by an owner or admin in the\napp (Settings, Developers). A key reads and changes only its own account's data, within its scopes.\n\nErrors are always `{\"error\": {\"code\": \"...\", \"message\": \"...\"}}`. Lists are newest first with cursor pagination\n(`next_cursor`). Each key may make 60 requests a minute and 10,000 a day. Send an `Idempotency-Key`\nheader with a POST to make a retry safe.\n\nNo endpoint starts a phone call or sends a text. Guides: https://linesteward.com/developers","version":"1.0.0","contact":{"url":"https://linesteward.com/developers"}},"servers":[{"url":"https://linesteward.com","description":"Production"}],"paths":{"/v1/businesses":{"get":{"summary":"List businesses","description":"Every business in the key's account, oldest first.","operationId":"list_businesses_businesses_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessList"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKey":[]}],"x-required-scope":"businesses:read"},"post":{"summary":"Add a business","description":"Add a business (a location with its own receptionist line) to the key's account. It shares the account's plan and minutes, so it needs a plan with room for another location (Enterprise). Sign-ups for a new account happen in the app.","operationId":"create_business_businesses_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Business"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKey":[]}],"x-required-scope":"businesses:write","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (a UUID). A retry with the same key and body gets the first answer for 24 hours instead of doing it twice."}]}},"/v1/businesses/{business_id}":{"get":{"summary":"Get a business","description":"One business: details, opening hours, the owner's texts, and the receptionist's name and greeting.","operationId":"get_business_businesses__business_id__get","security":[{"ApiKey":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Business"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"businesses:read"},"patch":{"summary":"Update a business","description":"Change only the fields you send. The receptionist uses the change from its next call.","operationId":"update_business_businesses__business_id__patch","security":[{"ApiKey":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Business"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"businesses:write"}},"/v1/businesses/{business_id}/knowledge":{"put":{"summary":"Replace the facts","description":"Replace one set of facts (services, prices, answers) the receptionist uses on calls. `manual` is the set typed in the app; `website` the set read from the website. The other set stays.","operationId":"replace_knowledge_businesses__business_id__knowledge_put","security":[{"ApiKey":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeReplace"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Saved"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"knowledge:write"}},"/v1/businesses/{business_id}/documents":{"post":{"summary":"Upload a document","description":"A PDF, Word (.docx), text, Markdown or CSV file the receptionist answers callers from. Send the file as the body and its name as ?name=. It is read in the background (status `processing`, then `ready` or `failed`; see it in the app). Only its text is kept; the file is deleted once read. The same limits as the app apply.","operationId":"upload_document_businesses__business_id__documents_post","security":[{"ApiKey":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","title":"Business Id"}},{"name":"name","in":"query","required":false,"schema":{"type":"string","description":"The file's name, like price-list.pdf.","default":"","title":"Name"},"description":"The file's name, like price-list.pdf."},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (a UUID). A retry with the same key and body gets the first answer for 24 hours instead of doing it twice."}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"knowledge:write","requestBody":{"required":true,"description":"The file itself, as the body (not a form).","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}}}},"/v1/calls":{"get":{"summary":"List calls","description":"Calls, newest first: time, length, outcome, summary and the caller's number (callers' personal data). The transcript is on GET /v1/calls/{call_id}.","operationId":"list_calls_calls_get","security":[{"ApiKey":[]}],"parameters":[{"name":"business_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only this business (its id).","title":"Business Id"},"description":"Only this business (its id)."},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only from this time on (ISO 8601).","title":"Since"},"description":"Only from this time on (ISO 8601)."},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only before this time (ISO 8601).","title":"Until"},"description":"Only before this time (ISO 8601)."},{"name":"outcome","in":"query","required":false,"schema":{"anyOf":[{"enum":["booked","changed","cancelled","message","info","transferred","abandoned","failed"],"type":"string"},{"type":"null"}],"title":"Outcome"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"next_cursor from the page before.","title":"Cursor"},"description":"next_cursor from the page before."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Up to 100; 25 if not given.","default":25,"title":"Limit"},"description":"Up to 100; 25 if not given."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallPage"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"calls:read"}},"/v1/calls/{call_id}":{"get":{"summary":"Get a call","description":"One call. Add ?include=transcript for what was said: it holds callers' personal data, so ask for it only when you need it and keep it no longer than your own retention time.","operationId":"get_call_calls__call_id__get","security":[{"ApiKey":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","title":"Call Id"}},{"name":"include","in":"query","required":false,"schema":{"anyOf":[{"const":"transcript","type":"string"},{"type":"null"}],"title":"Include"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDetail"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"calls:read"}},"/v1/messages":{"get":{"summary":"List messages","description":"Messages the receptionist took, newest first.","operationId":"list_messages_messages_get","security":[{"ApiKey":[]}],"parameters":[{"name":"business_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only this business (its id).","title":"Business Id"},"description":"Only this business (its id)."},{"name":"status","in":"query","required":false,"schema":{"enum":["open","done","all"],"type":"string","default":"all","title":"Status"}},{"name":"urgent","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Only urgent ones.","title":"Urgent"},"description":"Only urgent ones."},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only from this time on (ISO 8601).","title":"Since"},"description":"Only from this time on (ISO 8601)."},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only before this time (ISO 8601).","title":"Until"},"description":"Only before this time (ISO 8601)."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"next_cursor from the page before.","title":"Cursor"},"description":"next_cursor from the page before."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Up to 100; 25 if not given.","default":25,"title":"Limit"},"description":"Up to 100; 25 if not given."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagePage"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"messages:read"}},"/v1/bookings":{"get":{"summary":"List bookings","description":"Bookings, newest made first. Filter by when they start with starts_after / starts_before.","operationId":"list_bookings_bookings_get","security":[{"ApiKey":[]}],"parameters":[{"name":"business_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Only this business (its id).","title":"Business Id"},"description":"Only this business (its id)."},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["confirmed","cancelled","completed","no_show"],"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"starts_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Starts After"}},{"name":"starts_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Starts Before"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"next_cursor from the page before.","title":"Cursor"},"description":"next_cursor from the page before."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Up to 100; 25 if not given.","default":25,"title":"Limit"},"description":"Up to 100; 25 if not given."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingPage"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"bookings:read"},"post":{"summary":"Make a booking","description":"Book a time with the same rules the receptionist uses on calls: the skill must be on, the time must be open, on the booking grid, after the notice and within the days ahead, the service must be one the business lists, and there must be room. No text is sent to the customer. Not for businesses that book into a connected booking system, or trades job visits.","operationId":"create_booking_bookings_post","security":[{"ApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"bookings:write","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (a UUID). A retry with the same key and body gets the first answer for 24 hours instead of doing it twice."}]}},"/v1/bookings/{booking_id}":{"get":{"summary":"Get a booking","description":"One booking.","operationId":"get_booking_bookings__booking_id__get","security":[{"ApiKey":[]}],"parameters":[{"name":"booking_id","in":"path","required":true,"schema":{"type":"string","title":"Booking Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"bookings:read"},"delete":{"summary":"Cancel a booking","description":"Cancel a confirmed booking that hasn't started, with at least the business's cancellation notice. No text is sent to the customer. Cancelling twice is fine.","operationId":"cancel_booking_bookings__booking_id__delete","security":[{"ApiKey":[]}],"parameters":[{"name":"booking_id","in":"path","required":true,"schema":{"type":"string","title":"Booking Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Booking"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"bookings:write"}},"/v1/webhooks":{"get":{"summary":"List webhooks","description":"Each business has at most one webhook address: the same one Settings, \"Send to other apps\" sets in the app. The signing secret is never shown again.","operationId":"list_webhooks_webhooks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookList"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKey":[]}],"x-required-scope":"webhooks:write"},"post":{"summary":"Set a webhook","description":"Set the business's webhook address and events. It replaces the one set before (in the app too), and makes a new signing secret, shown once in the answer.","operationId":"set_webhook_webhooks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKey":[]}],"x-required-scope":"webhooks:write","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255},"description":"Any unique string (a UUID). A retry with the same key and body gets the first answer for 24 hours instead of doing it twice."}]}},"/v1/webhooks/{webhook_id}":{"delete":{"summary":"Delete a webhook","description":"Stop sending events to it. Events not sent yet are dropped.","operationId":"delete_webhook_webhooks__webhook_id__delete","security":[{"ApiKey":[]}],"parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deleted"}}}},"400":{"description":"A value was not accepted (code `invalid_request`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"401":{"description":"No key, or the key is wrong or revoked (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"403":{"description":"The key lacks the scope this needs (`insufficient_scope`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"Not found, or not in your account (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"The request body or query is not valid (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"429":{"description":"Too many requests (`rate_limited`); see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"x-required-scope":"webhooks:write"}}},"components":{"schemas":{"Booking":{"properties":{"id":{"type":"string","title":"Id"},"business_id":{"type":"string","title":"Business Id"},"call_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Call Id"},"kind":{"type":"string","title":"Kind","examples":["appointment"]},"ref":{"type":"string","title":"Ref","examples":["K7MQ2P"]},"status":{"type":"string","title":"Status","examples":["confirmed"]},"service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service"},"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"ends_at":{"type":"string","format":"date-time","title":"Ends At"},"party_size":{"type":"integer","title":"Party Size","default":1},"customer_name":{"type":"string","title":"Customer Name"},"customer_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Phone"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"source":{"type":"string","title":"Source","examples":["integration"]},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"cancelled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cancelled At"}},"type":"object","required":["id","business_id","kind","ref","status","starts_at","ends_at","customer_name","source"],"title":"Booking"},"BookingCreate":{"properties":{"business_id":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","title":"Business Id"},"kind":{"type":"string","enum":["appointment","table"],"title":"Kind","default":"appointment"},"starts_at":{"type":"string","format":"date-time","title":"Starts At","description":"With its UTC offset, like 2026-11-04T10:30:00+00:00. It must be a free time the receptionist would offer: open, on the booking grid, after the notice."},"service":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Service","description":"A bookable service's name, when the business lists services (appointments)."},"party_size":{"anyOf":[{"type":"integer","maximum":50.0,"minimum":1.0},{"type":"null"}],"title":"Party Size","description":"Tables: how many people."},"customer_name":{"type":"string","maxLength":80,"minLength":1,"title":"Customer Name"},"customer_phone":{"anyOf":[{"type":"string","pattern":"^\\+[1-9][0-9]{6,14}$"},{"type":"null"}],"title":"Customer Phone"},"notes":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Notes"}},"additionalProperties":false,"type":"object","required":["business_id","starts_at","customer_name"],"title":"BookingCreate","examples":[{"business_id":"3f0c6a8e-1b2d-4c5e-8f90-a1b2c3d4e5f6","customer_name":"Sam Patel","customer_phone":"+447700900123","kind":"appointment","service":"Women's cut and finish","starts_at":"2026-11-04T10:30:00+00:00"}]},"BookingPage":{"properties":{"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Pass as ?cursor= for the next page; null on the last."},"data":{"items":{"$ref":"#/components/schemas/Booking"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"BookingPage"},"Business":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"business_type":{"type":"string","title":"Business Type","examples":["salon"]},"timezone":{"type":"string","title":"Timezone","examples":["Europe/London"]},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","examples":["+441134960000"]},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"hours":{"additionalProperties":true,"type":"object","title":"Hours","examples":[{"mon":[["09:00","17:30"]],"sat":[["10:00","14:00"]],"tue":[["09:00","17:30"]]}]},"closures":{"items":{},"type":"array","title":"Closures","examples":[["2026-12-25"]]},"about":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"About"},"receptionist_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Receptionist Role"},"greeting":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Greeting"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name","examples":["Alex"]},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","name","business_type","timezone"],"title":"Business"},"BusinessCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"business_type":{"type":"string","enum":["salon","restaurant","garage","clinic","trades","estate_agent","other"],"title":"Business Type"},"website":{"anyOf":[{"type":"string","maxLength":300,"pattern":"^https?://"},{"type":"null"}],"title":"Website"},"timezone":{"type":"string","maxLength":64,"title":"Timezone","default":"Europe/London"}},"additionalProperties":false,"type":"object","required":["name","business_type"],"title":"BusinessCreate","examples":[{"business_type":"salon","name":"Kettlewell Hair, Ilkley","website":"https://kettlewellhair.example"}]},"BusinessList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Business"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"BusinessList"},"BusinessUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Name"},"timezone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Timezone"},"address":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Address"},"phone":{"anyOf":[{"type":"string","pattern":"^\\+[1-9][0-9]{6,14}$"},{"type":"null"}],"title":"Phone"},"website":{"anyOf":[{"type":"string","maxLength":300,"pattern":"^https?://"},{"type":"null"}],"title":"Website"},"hours":{"anyOf":[{"additionalProperties":{"items":{"items":{"type":"string"},"type":"array"},"type":"array"},"type":"object"},{"type":"null"}],"title":"Hours","description":"Local opening times per day (mon to sun); a missing or empty day is closed."},"closures":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":200},{"type":"null"}],"title":"Closures","description":"Local dates closed all day, YYYY-MM-DD."},"about":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"About","description":"About your business, in your words."},"receptionist_role":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Receptionist Role","description":"What the receptionist should do for callers."},"greeting":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}],"title":"Greeting","description":"The receptionist's first words. It always says it is an AI first; this follows."},"agent_name":{"anyOf":[{"type":"string","maxLength":40,"minLength":1},{"type":"null"}],"title":"Agent Name"}},"additionalProperties":false,"type":"object","title":"BusinessUpdate","examples":[{"greeting":"Hello, you're through to Kettlewell Hair. How can I help?","hours":{"mon":[["09:00","17:30"]],"sat":[["10:00","14:00"]],"tue":[["09:00","17:30"]]}}]},"Call":{"properties":{"id":{"type":"string","title":"Id"},"business_id":{"type":"string","title":"Business Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"seconds":{"type":"integer","title":"Seconds","default":0},"outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome","examples":["booked"]},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"caller_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caller Phone","examples":["+447700900123"]},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","examples":["en"]}},"type":"object","required":["id","business_id","started_at"],"title":"Call"},"CallDetail":{"properties":{"id":{"type":"string","title":"Id"},"business_id":{"type":"string","title":"Business Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"seconds":{"type":"integer","title":"Seconds","default":0},"outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome","examples":["booked"]},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"caller_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caller Phone","examples":["+447700900123"]},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","examples":["en"]},"transcript":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Transcript","description":"Only with ?include=transcript. Callers' personal data."}},"type":"object","required":["id","business_id","started_at"],"title":"CallDetail"},"CallPage":{"properties":{"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Pass as ?cursor= for the next page; null on the last."},"data":{"items":{"$ref":"#/components/schemas/Call"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"CallPage"},"Deleted":{"properties":{"deleted":{"type":"boolean","title":"Deleted","default":true}},"type":"object","title":"Deleted"},"Document":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"kind":{"type":"string","title":"Kind"},"bytes":{"type":"integer","title":"Bytes"},"status":{"type":"string","title":"Status","examples":["processing"]}},"type":"object","required":["id","name","kind","bytes","status"],"title":"Document"},"ErrorBody":{"properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"}},"type":"object","required":["error"],"title":"ErrorBody"},"ErrorDetail":{"properties":{"code":{"type":"string","title":"Code","examples":["not_found"]},"message":{"type":"string","title":"Message","examples":["No such business."]}},"type":"object","required":["code","message"],"title":"ErrorDetail"},"Fact":{"properties":{"kind":{"type":"string","enum":["about","service","faq","hours","policy","other"],"title":"Kind"},"title":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Title"},"body":{"type":"string","maxLength":4000,"title":"Body","default":""},"price":{"anyOf":[{"type":"number","exclusiveMaximum":100000.0,"minimum":0.0},{"type":"null"}],"title":"Price"},"price_from":{"type":"boolean","title":"Price From","default":false},"duration_minutes":{"anyOf":[{"type":"integer","maximum":600.0,"minimum":5.0},{"type":"null"}],"title":"Duration Minutes"},"bookable":{"type":"boolean","title":"Bookable","default":true}},"additionalProperties":false,"type":"object","required":["kind"],"title":"Fact"},"KnowledgeReplace":{"properties":{"facts":{"items":{"$ref":"#/components/schemas/Fact"},"type":"array","maxItems":200,"title":"Facts"},"source":{"type":"string","enum":["manual","website"],"title":"Source","description":"Which set of facts to replace: `manual` (the ones typed in the app) or `website` (the ones read from the website). The other set is kept.","default":"manual"}},"additionalProperties":false,"type":"object","required":["facts"],"title":"KnowledgeReplace","examples":[{"facts":[{"duration_minutes":60,"kind":"service","price":48,"title":"Women's cut and finish"},{"body":"Yes, free parking behind the salon.","kind":"faq","title":"Is there parking?"}]}]},"Message":{"properties":{"id":{"type":"string","title":"Id"},"business_id":{"type":"string","title":"Business Id"},"call_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Call Id"},"kind":{"type":"string","title":"Kind","examples":["callback"]},"caller_name":{"type":"string","title":"Caller Name"},"caller_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caller Phone"},"body":{"type":"string","title":"Body"},"urgent":{"type":"boolean","title":"Urgent","default":false},"callback_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callback Time"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"status":{"type":"string","title":"Status","examples":["new"]},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","business_id","kind","caller_name","body","status","created_at"],"title":"Message"},"MessagePage":{"properties":{"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Pass as ?cursor= for the next page; null on the last."},"data":{"items":{"$ref":"#/components/schemas/Message"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"MessagePage"},"Saved":{"properties":{"saved":{"type":"integer","title":"Saved"}},"type":"object","required":["saved"],"title":"Saved"},"Webhook":{"properties":{"id":{"type":"string","title":"Id"},"business_id":{"type":"string","title":"Business Id"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string"},"type":"array","title":"Events"},"enabled":{"type":"boolean","title":"Enabled","default":true},"last_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Status"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","business_id","url","events"],"title":"Webhook"},"WebhookCreate":{"properties":{"business_id":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","title":"Business Id"},"url":{"type":"string","maxLength":500,"pattern":"^https://[^/@\\s]+(/\\S*)?$","title":"Url"},"events":{"anyOf":[{"items":{"type":"string","enum":["call.completed","message.created","booking.created","booking.cancelled"]},"type":"array","minItems":1},{"type":"null"}],"title":"Events","description":"Default: all four events."}},"additionalProperties":false,"type":"object","required":["business_id","url"],"title":"WebhookCreate","examples":[{"business_id":"3f0c6a8e-1b2d-4c5e-8f90-a1b2c3d4e5f6","events":["call.completed","booking.created"],"url":"https://example.com/hooks/receptionist"}]},"WebhookCreated":{"properties":{"id":{"type":"string","title":"Id"},"business_id":{"type":"string","title":"Business Id"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string"},"type":"array","title":"Events"},"enabled":{"type":"boolean","title":"Enabled","default":true},"last_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Status"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"signing_secret":{"type":"string","title":"Signing Secret","description":"Shown once. Use it to check the X-Receptionist-Signature header."}},"type":"object","required":["id","business_id","url","events","signing_secret"],"title":"WebhookCreated"},"WebhookList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/Webhook"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"WebhookList"}},"securitySchemes":{"ApiKey":{"type":"http","description":"Your API key, from Settings, Developers in the app.","scheme":"bearer","bearerFormat":"ls_live_..."}}}}