interface RetryConfig { maxAttempts?: number; baseDelay?: number; maxDelay?: number; onRateLimit?: (info: { retryAfter: number; endpoint: string; attempt: number; }) => void; } interface CacheConfig { enabled?: boolean; ttl?: number; maxSize?: number; } declare class MemoryCache { private store; private readonly ttl; private readonly maxSize; constructor(config?: CacheConfig); get(key: string): T | undefined; set(key: string, value: T): void; has(key: string): boolean; delete(key: string): boolean; clear(): void; get size(): number; } declare function cacheKey(prefix: string, params?: Record): string; type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; interface RequestOptions { method?: HttpMethod; params?: Record; body?: unknown; headers?: Record; } interface HttpClientConfig { baseURL: string; getAuthHeader: () => Promise; onUnauthorized?: () => Promise; debug?: boolean; retryConfig?: RetryConfig; } declare class HttpClient { private readonly config; constructor(config: HttpClientConfig); private parseResponse; request(path: string, options?: RequestOptions): Promise; get(path: string, params?: RequestOptions['params']): Promise; post(path: string, body?: unknown): Promise; put(path: string, body?: unknown): Promise; patch(path: string, body?: unknown): Promise; delete(path: string): Promise; } interface CalendarDayPrice { amount: number; currency: string; formatted: string; } interface CalendarDayStatus { reason: string; source: string | null; sourceType: string; available: boolean; } interface CalendarDay$1 { date: string; day: string; minStay: number; closedForCheckin: boolean; closedForCheckout: boolean; status: CalendarDayStatus; price: CalendarDayPrice; } interface CalendarData { listingId: string; provider: string; startDate: string; endDate: string; days: CalendarDay$1[]; } interface CalendarUpdate { date: string; price?: { amount: number; }; available?: boolean; minStay?: number; /** Block check-in on this date. Useful for enforcing min-stay edges. */ closedForCheckin?: boolean; /** Block check-out on this date. Useful for enforcing min-stay edges. */ closedForCheckout?: boolean; /** Per-date note. Pass `null` to clear. Max 512 chars. */ note?: string | null; } /** * Resource for reading and mutating per-property calendar state: day * availability, nightly price, minimum stay, and owner blocks. * * Dates are always ISO `YYYY-MM-DD`. `update` and `block` are **additive** — * Hospitable merges the payload with existing calendar state rather than * replacing it. * * @see https://developer.hospitable.com/docs/public-api-docs/w7lb6cwd1dvx6-calendar-resource */ declare class CalendarResource { private readonly http; constructor(http: HttpClient); /** * Fetch calendar days for a property in `[startDate, endDate]` inclusive. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/calendar */ get(propertyId: string, startDate: string, endDate: string): Promise; /** * Apply a batch of per-day calendar updates (price, availability, minStay, * check-in/out restrictions, notes). Merges additively — only the fields * provided on each `CalendarUpdate` entry are modified. * * `options.note` sets a top-level note applied to every date in `updates` * that doesn't define its own `note`. Pass `null` to clear. Max 512 chars. * * @see PUT https://public.api.hospitable.com/v2/properties/{id}/calendar */ update(propertyId: string, updates: CalendarUpdate[], options?: { note?: string | null; }): Promise; /** * Block a date range (e.g. owner stay, maintenance). * * @see POST https://public.api.hospitable.com/v2/properties/{id}/calendar/block */ block(propertyId: string, startDate: string, endDate: string, reason?: string): Promise; /** * Remove a previously placed block on a date range. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/calendar/unblock */ unblock(propertyId: string, startDate: string, endDate: string): Promise; } interface PaginatedResponse { data: T[]; meta: { currentPage: number; lastPage: number; perPage: number; total: number; }; links: { first: string | null; last: string | null; prev: string | null; next: string | null; }; } interface PropertyAddress { number: string | null; street: string; city: string; state: string; postcode: string; country: string; /** * Full country name (e.g. "United States"). The API may return `null` * when country metadata is not resolved — don't assume this is populated. */ countryName: string | null; coordinates: { latitude: string; longitude: string; }; display: string; } interface PropertyCapacity { max: number; bedrooms: number; beds: number; bathrooms: number; } interface PropertyHouseRules { petsAllowed: boolean; smokingAllowed: boolean; eventsAllowed: boolean; } /** * Individual bed entry within a {@link PropertyRoomDetail}. * * `type` values seen in the wild: `king_bed`, `queen_bed`, `double_bed`, * `single_bed`, `sofa_bed`, `crib`. Kept as open string union. */ interface PropertyRoomBed { type: string; quantity: number; } /** * Structured room/bed layout returned on the property object under * `room_details`. Non-sleeping rooms (kitchen, living_room, backyard) * appear with an empty `beds` array. */ interface PropertyRoomDetail { /** * Room type. Values seen: `bedroom`, `full_bathroom`, `half_bathroom`, * `kitchen`, `living_room`, `dining_room`, `backyard`, `patio`. Open * string union — new room types may appear. */ type: string; beds: PropertyRoomBed[]; } /** * Tag object returned by `GET /v2/properties/{id}/tags` — the * organization-level tag registry, distinct from the free-text tags that * appear inline on the property object (see {@link Property.tags}). */ interface PropertyTag { id: string; name: string; } /** * Parent/child relationship metadata for listings that are part of a * multi-unit or sub-unit setup. `null` for standalone listings. Exact * shape varies by platform — kept as `unknown` so agents narrow it. */ type PropertyParentChild = unknown | null; /** * Include fields accepted by `GET /v2/properties` and `GET /v2/properties/{id}`. * * Empirically verified against the live API on 2026-04-11. Unknown * includes are silently ignored by the server (return 200 with no extra * fields) — passing an invalid value won't error. * * @see https://developer.hospitable.com/docs/public-api-docs/qc4x36uhxinx3-get-properties */ type PropertyIncludeField = 'user' | 'listings' | 'details' | 'bookings'; /** * Host/account info returned when `include=user` is requested on a * property. Same shape as the nested `user` on a reservation — minimal * identity (no billing, no business profile). For the full profile call * `client.user.get()` separately. */ interface PropertyUser { id: string; email: string; name: string; profilePicture: string | null; } /** * Co-host entry on a property listing — one of potentially multiple * people with admin access to a single channel. Empty array for listings * with no co-hosts. */ interface PropertyListingCoHost { userId: string; name: string; channelName: string; } /** * A single platform listing for a property — one per booking channel * (airbnb, vrbo, booking_com, direct, manual, gvr, etc.). Returned as an * array when `include=listings` is requested. */ interface PropertyListing { /** Booking platform, e.g. `'airbnb'`, `'vrbo'`, `'direct'`. */ platform: string; /** Platform's listing id for this property on this channel. */ platformId: string; /** Platform's user id for the host on this listing. */ platformUserId: string | null; /** Host's profile picture URL on the platform, if any. */ platformPicture: string | null; /** Display name on the platform, if any. */ platformName: string | null; /** Host email on the platform, if any. */ platformEmail: string | null; /** Co-hosts with access to this listing. */ coHosts: PropertyListingCoHost[]; } /** * Host-operational details about a property — returned when * `include=details` is requested. These are the fields the host populates * in Hospitable to answer common guest questions and feed automated * responses. * * **`wifiPassword` is NOT redacted** by `sanitize()`. It's semi-public by * design — hosts share it with every guest — and agents fetching this * field to include in a check-in message need to see the real value in * debug output. The SDK's `SAFE_OVERRIDES` allowlist explicitly excludes * `wifiPassword`/`wifi_password` from the broad `/password/i` match. */ interface PropertyDetails { /** Additional house rules beyond the structured `houseRules` object. */ additionalRules: string | null; /** Directions and transit info. */ gettingAround: string | null; /** How guests get in (lockbox, keypad, greeter, etc.). */ guestAccess: string | null; /** House manual / operations guide. */ houseManual: string | null; /** Neighborhood / area description. */ neighborhoodDescription: string | null; /** Free-form "other details" field. */ otherDetails: string | null; /** Short overview of the space. */ spaceOverview: string | null; /** Wi-Fi network name (SSID). */ wifiName: string | null; /** Wi-Fi password — passed through sanitize() unchanged (see SAFE_OVERRIDES). */ wifiPassword: string | null; } /** * A configurable fee on the property — appears in {@link PropertyBookings.fees}. * Distinct from per-reservation fees which live on * `Reservation.financials.guest.fees`. */ interface PropertyBookingFee { /** Human-readable fee name, e.g. `"Cleaning Fee"`, `"Resort Fee"`. */ name: string; /** Fee type, e.g. `"flat"`, `"percentage"`, `"per_night"`. Open string union. */ type: string; /** Configured value for the fee — either flat amount or percentage. */ value: { /** Amount in minor currency units for flat fees, or raw percentage × 100 for percentage fees. */ amount: number; /** Pre-formatted display string, e.g. `"$201.00"` or `"5%"`. */ formatted: string; }; } /** * Per-platform price markup — how much the property charges above base * rate on a specific channel. Appears in * {@link PropertyBookings.listingMarkups}. */ interface PropertyListingMarkup { /** Booking platform, e.g. `"airbnb"`, `"vrbo"`, `"direct"`. */ platform: string; /** Markup type, e.g. `"percentage"`, `"flat"`. Open string union. */ type: string; /** Markup value — interpretation depends on `type`. */ markup: number; } /** * Extra-guest / pet fee configuration returned inside * {@link PropertyBookings.occupancyBasedRules}. */ interface PropertyOccupancyFee { /** Fee type — typically `"per_night"` or `"flat"`. Open string union. */ type: string; value: { amount: number; formatted: string; }; } /** * Occupancy-based pricing rules — what's included in the base rate and * what costs extra beyond a threshold. */ interface PropertyOccupancyBasedRules { /** Number of guests included in the base rate. */ guestsIncluded: number; /** Fee charged per additional guest over `guestsIncluded`. */ extraGuestFee: PropertyOccupancyFee; /** Fee charged per pet (independent of guest count). */ petFee: PropertyOccupancyFee; } /** * Payment-term configuration returned inside * {@link PropertyBookingPolicies.paymentTerms}. */ interface PropertyPaymentTerms { /** Payment status, e.g. `"full_payment"`, `"deposit_required"`. */ status: string; /** Human-readable description lines explaining the terms. */ description: string[]; /** Grace period in hours before payment is considered late. */ gracePeriod: number; } /** * Cancellation + payment policies attached to the property. */ interface PropertyBookingPolicies { /** Cancellation policy description lines — one per rule/tier. */ cancellation: string[]; paymentTerms: PropertyPaymentTerms; } /** * Booking configuration returned when `include=bookings` is requested — * pricing policies, fees, discounts, and occupancy rules for the * property. Structured based on empirical probing of the live API; all * fields are always present on the response (arrays may be empty). * * Fields like `discounts`, `securityDeposits`, and * `securityDepositCollector` are typed as `unknown`/`unknown[]` because * populated examples haven't been observed yet — narrow with a type * guard at the call site if you encounter one. */ interface PropertyBookings { /** Configurable property-level fees. */ fees: PropertyBookingFee[]; /** Occupancy-based extra charges (extra guest, pet). */ occupancyBasedRules: PropertyOccupancyBasedRules; /** Available discounts. Shape not yet observed populated. */ discounts: unknown[]; /** Per-platform price markups. */ listingMarkups: PropertyListingMarkup[]; /** Security deposit definitions. Shape not yet observed populated. */ securityDeposits: unknown[]; /** Which party collects the security deposit. */ securityDepositCollector: unknown | null; bookingPolicies: PropertyBookingPolicies; /** URLs where this property is listed across platforms. */ siteUrls: string[]; } /** * An iCal feed imported from an external source — used to sync * third-party calendar blocks (Airbnb, Crewdogs, Google Calendar, etc.) * into Hospitable's unified calendar. * * ⚠️ **`url` is a shared secret.** iCal URLs from most platforms embed * an opaque auth token in the path (`https://example.com/ical/.ics`). * Anyone holding the URL can read the full booking calendar. Don't log * `icalImports[].url` to stdout in shared contexts and don't commit it * to version control. The SDK's `sanitize()` does NOT redact this field * because `url` is too common a field name to blanket-mask. */ interface PropertyIcalImport { id: string; /** The iCal feed URL — ⚠️ effectively a credential, see interface JSDoc. */ url: string; /** Display name for this import source. */ name: string; /** Host of the external calendar, if known. */ host: { firstName: string; lastName: string; }; /** ISO 8601 timestamp of the most recent successful sync. */ lastSyncAt: string; /** ISO 8601 timestamp when the feed was disconnected, or `null` if active. */ disconnectedAt: string | null; } interface Property { id: string; name: string; publicName: string; picture: string | null; address: PropertyAddress; timezone: string; listed: boolean; currency: string; summary: string | null; description: string | null; /** Local check-in time as `HH:MM`. */ checkin: string; /** Local check-out time as `HH:MM`. */ checkout: string; amenities: string[]; capacity: PropertyCapacity; propertyType: string; roomType: string; /** * Free-text tags attached to the property (e.g. `"Anaheim"`, * `"shorterm"`). Distinct from {@link PropertyTag} objects returned by * `PropertiesResource.listTags()`, which are structured org-level tags. */ tags: string[]; houseRules: PropertyHouseRules; /** Structured room layout. Not all properties populate this. */ roomDetails: PropertyRoomDetail[]; /** * External iCal feeds synced into this property's calendar. * * **Gated on `include=listings`** — this field is part of the * listings bundle conceptually, so it's populated only when * `include=listings` (or a multi-include that contains `listings`) * is requested. Empirically verified against the live API; the * Hospitable docs don't mention this gating. * * See {@link PropertyIcalImport} for the security caveat on `.url`. */ icalImports?: PropertyIcalImport[]; calendarRestricted: boolean; /** Parent/child linkage for multi-unit listings. `null` for standalone. */ parentChild: PropertyParentChild; /** Populated when `include=user` is requested. */ user?: PropertyUser; /** Populated when `include=listings` is requested — one entry per channel. */ listings?: PropertyListing[]; /** Populated when `include=details` is requested. Contains `wifiPassword`. */ details?: PropertyDetails; /** Populated when `include=bookings` is requested. Opaque — narrow at use site. */ bookings?: PropertyBookings; } /** * Options for creating an iCal import on a property. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/ical-imports */ interface CreateIcalImportOptions { name?: string; host?: { firstName?: string; lastName?: string; }; } /** * Options for updating an existing iCal import on a property. * * @see PUT https://public.api.hospitable.com/v2/properties/{id}/ical-imports/{icalUuid} */ interface UpdateIcalImportOptions { url?: string; name?: string; host?: { firstName?: string; lastName?: string; }; /** When `true`, triggers an immediate resync of the feed. */ resync?: boolean; } type PropertyList = PaginatedResponse; /** * An image attached to a property. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/images */ interface PropertyImage { url: string; thumbnailUrl: string; /** Caption text. May be empty string. */ caption: string; /** Display order (0-indexed). */ order: number; /** ISO 8601 timestamp. */ lastUpdatedAt: string; } /** * Parameters for `GET /v2/properties/search` — availability search. * * All three fields are required by the API. The endpoint returns properties * that are available for the given window and party size. */ interface PropertySearchParams { /** ISO `YYYY-MM-DD` — desired check-in date. */ startDate: string; /** ISO `YYYY-MM-DD` — desired check-out date. */ endDate: string; /** Number of adult guests. */ adults: number; /** Number of children. */ children?: number; /** Number of infants. */ infants?: number; /** Number of pets. */ pets?: number; page?: number; perPage?: number; } /** * A message attachment — typically a photo attached to a guest or host * message on platforms like Airbnb that support rich conversations. * * Shape verified against live API (2026-04-11). Only `type: 'image'` has * been observed in the wild, but the union is left open so future media * types (e.g. video, document) don't break consumers. * * Note: attachment URLs returned by Airbnb are **pre-signed and * short-lived** (AWS S3 signatures with ~1h expiry). Don't persist the * URL — re-fetch the message when you need the content. */ interface MessageAttachment { type: 'image' | (string & {}); url: string; } /** * A message reaction — reserved for future use. Hospitable's API returns * this field on every message but it has never been observed populated in * our probes. Left as `unknown` so the SDK doesn't force a shape on data * we haven't seen yet; narrow with a type guard if you encounter one. */ type MessageReaction = unknown; interface MessageSender { firstName: string; /** Display name — often just the first name, sometimes full. */ fullName: string; /** Locale code (e.g. `"en"`). Empty string when unset on host accounts. */ locale: string; pictureUrl: string | null; thumbnailUrl: string | null; /** * Free-form location string, e.g. `"High Point, NC"` or * `"Kippa-Ring, Australia"`. Empty string when the platform has no * location set for this user (common for hosts). */ location: string; } /** * Who sent the message — `host` or `guest`. Open string union to allow * future values (e.g. `co_host`, `agent`) without breaking consumers. */ type MessageSenderType = 'host' | 'guest' | (string & {}); /** * Where the message originated. Values seen in production: * * - `hospitable` — sent via the Hospitable web app * - `platform` — sent via the upstream platform (Airbnb, VRBO, etc.) * - `automated` — triggered by a Hospitable rule/schedule * - `AI` — Hospitable's AI auto-reply feature * - `public_api` — sent via the Hospitable Public API (i.e. this SDK) * * Open string union so unobserved sources don't break consumers. */ type MessageSource = 'hospitable' | 'platform' | 'automated' | 'AI' | 'public_api' | (string & {}); /** * MIME-like content type. Only `text/plain` has been observed in the * wild, but this is a full MIME string field so the union is open. */ type MessageContentType = 'text/plain' | (string & {}); interface Message { id: number | string; /** Booking platform, e.g. `airbnb`, `vrbo`, `booking_com`, `direct`. */ platform: string; /** * Upstream platform's message identifier. Distinct from {@link id} * (which is Hospitable's internal id). Useful for correlating against * platform webhooks or support tickets. */ platformId: string; conversationId: string; reservationId: string; /** * MIME content type of {@link body}. Currently always `text/plain`, * but the field exists to support future rich-content messages. */ contentType: MessageContentType; body: string; attachments: MessageAttachment[]; /** * Message reactions (emoji responses, etc.). Never observed populated * in probes — treat as opaque and narrow with a type guard if needed. */ reactions: MessageReaction[]; senderType: MessageSenderType; /** Sender's role on the conversation (e.g. `host`). May be `null`. */ senderRole: string | null; sender: MessageSender; createdAt: string; source: MessageSource; /** * Third-party integration metadata — for messages routed through * external tools. Almost always `null` for messages sent directly * through Hospitable or platforms. Shape is opaque until we see a * populated example. */ integration: unknown | null; /** * Correlates with {@link MessageReceipt.sentReferenceId} from a * previous `send()` call. `null` for messages the SDK didn't send. * Use this to confirm async delivery of messages sent via the API. */ sentReferenceId: string | null; } interface MessageThread { reservationId: string; messages: Message[]; } /** * Options accepted by both reservation and inquiry send endpoints. * The `senderId` is the co-host user id — leave blank to send as the listing * owner. Only supported on Airbnb reservations per the upstream API. */ interface SendMessageOptions { senderId?: string; } /** * Reservation-only extension of {@link SendMessageOptions}. The reservation * send endpoint additionally accepts an `images` array of URLs to attach * photos to the message. Inquiry send does NOT support image attachments — * pre-booking channels reject them — so this field is intentionally excluded * from {@link SendMessageOptions}. */ interface SendReservationMessageOptions extends SendMessageOptions { /** URLs of images to attach to the message. */ images?: string[]; } /** * Async receipt returned by the `POST /v2/inquiries/{uuid}/messages` and * `POST /v2/reservations/{uuid}/messages` endpoints. * * Both endpoints respond with 202 Accepted — delivery happens out of band on * the upstream channel (Airbnb / VRBO / etc). Match `sentReferenceId` against * the `sentReferenceId` field of Message resources fetched afterwards to * confirm delivery landed. */ interface MessageReceipt { sentReferenceId: string; } interface MessageTemplate$1 { id: string; name: string; body: string; variables: string[]; } interface InquiryGuestCounts { total: number; adultCount: number; childCount: number; infantCount: number; petCount: number; } /** * Inquiry guests return only first/last name by default. Extra fields may appear * when `include=guest` is passed — kept optional to avoid breaking on bare responses. */ interface InquiryGuest { firstName: string; lastName: string; email?: string | null; phoneNumbers?: string[]; profilePicture?: string | null; language?: string; } interface InquiryListing { platform: string; platformId: string; platformName?: string; platformEmail?: string; } interface InquiryUser { id: string; email: string; name: string; } /** * An inquiry — the pre-booking conversation/request stage. * * `inquiry.id` **is the conversation ID** — pass it directly to * `client.messages.list(inquiry.id)` to fetch the message thread, or to * `client.messages.sendForInquiry(inquiry.id, body)` to reply. * * The Hospitable API returns a single `Property` in a field awkwardly named * `properties` (plural-but-singular). {@link normalizeInquiry} aliases it to * `property` for nicer DX — both reference the same object. Prefer * `inquiry.property` in new code. */ interface Inquiry { id: string; platform: string; inquiryDate: string; arrivalDate?: string; departureDate?: string; guests: InquiryGuestCounts; guest: InquiryGuest; /** * Included via `include=properties`. Singular despite the plural name — API quirk. * @deprecated Prefer {@link Inquiry.property}. Both point at the same object. */ properties?: Property; /** Alias for `properties`, populated by `normalizeInquiry`. Same object reference. */ property?: Property; /** Included via `include=listings`. */ listings?: InquiryListing[]; /** Included via `include=user`. */ user?: InquiryUser; /** Included via `include=messages` (only available on get-by-uuid). */ messages?: Message[]; } type InquiryList = PaginatedResponse; type InquiryIncludeField = 'financials' | 'guest' | 'user' | 'properties' | 'listings' | 'messages'; interface InquiryListParams { /** Required by the API — array of property UUIDs to query. */ properties: string[]; /** Comma-separated: any of `financials,guest,properties,listings`. */ include?: string; /** Inquiries where the last message is after the specified datetime (ISO 8601). */ lastMessageAt?: string; page?: number; perPage?: number; } /** * Normalize an Inquiry response by aliasing the `properties` field to `property`. * * Contract: * - Mutates and returns the same inquiry object (resource code relies on identity). * - No-op when `properties` is undefined (happens when the include was not requested). * - Does NOT overwrite an existing `property` field if already set. */ declare function normalizeInquiry(inquiry: Inquiry): Inquiry; /** * Resource for the Hospitable Inquiries API — pre-booking conversations. * * Note: an inquiry's `id` is also the conversation ID, so you can pass it * directly to `client.messages.list(inquiry.id)` to fetch the message thread. * * @see https://developer.hospitable.com/docs/public-api-docs/9lujw5cgctxti-get-inquiries * @see https://developer.hospitable.com/docs/public-api-docs/yczg8erku08qw-get-inquiry-by-uuid */ declare class InquiriesResource { private readonly http; private cache; constructor(http: HttpClient, cacheConfig?: CacheConfig); private fetchList; /** * List inquiries for the given properties. * * `params.properties` is required by the API — enforced at the type level. * Each returned inquiry is passed through {@link normalizeInquiry}, so the * `property` alias is populated alongside the raw `properties` field when * `include=properties` is requested. * * @see GET https://public.api.hospitable.com/v2/inquiries */ list(params: InquiryListParams): Promise; /** * Fetch a single inquiry by UUID (which is the conversation ID). * * The optional `include` parameter accepts a comma-separated list of: * `financials`, `guest`, `properties`, `listings`, `messages`. Note that * `messages` is only supported on this endpoint, not on {@link list}. * * **Envelope quirk**: unlike the list endpoint, the single-inquiry * response is wrapped in `{data: Inquiry}`. The SDK unwraps it so * callers always receive a bare {@link Inquiry}. * * @see GET https://public.api.hospitable.com/v2/inquiries/{uuid} * @throws {NotFoundError} on 404 (inquiry does not exist) * @throws {HospitableError} on 410 (inquiry has been deleted upstream) * @throws {ServerError} on 5xx after retries are exhausted */ get(uuid: string, include?: string): Promise; /** * Stream every inquiry matching `params`, auto-paginating through all pages. * * Memory-efficient — pulls one page at a time. Pass the same params you'd * pass to {@link list}, minus `page` which is managed by the generator. * * @see GET https://public.api.hospitable.com/v2/inquiries */ iter(params: Omit): AsyncGenerator; /** Drop the in-memory cache. Called automatically by the client on 401 re-auth. */ clearCache(): void; } /** * Resource for reading and sending messages on reservations and inquiries. * * **Which send method to use?** * * | Conversation state | Call | * | ---------------------------------------- | ---------------------------------------- | * | `reservation.id` known (booking exists) | {@link send} — accepts `images` attachments | * | `inquiry.id` known, no reservation yet | {@link sendForInquiry} — no `images` | * * Calling the wrong endpoint returns 410 or 422. Since `inquiry.id === * conversation_id`, reading a message thread works the same for both: * `client.messages.list(reservationOrInquiryId)`. * * Both send methods return `202 Accepted` with a `MessageReceipt` — * delivery happens out-of-band on the upstream channel (Airbnb, VRBO, * Booking.com, direct). Persist `receipt.sentReferenceId` and match it * against `Message.sentReferenceId` on a subsequent `list()` to confirm. * * Rate limits (both endpoints): **2/minute per target**, **50 per 5 * minutes globally**. The retry layer handles 429 automatically. */ declare class MessagesResource { private readonly http; constructor(http: HttpClient); /** * List the message thread for a reservation. * * @see GET https://public.api.hospitable.com/v2/reservations/{uuid}/messages */ list(reservationId: string): Promise; /** * Send a message on a reservation. * * Returns an async receipt with a `sentReferenceId` — the API responds with * 202 Accepted and delivers asynchronously on the upstream channel. Match * the `sentReferenceId` against messages fetched via {@link list} afterwards * to confirm delivery landed. * * Rate limits: 2/minute per reservation, 50 per 5 minutes globally. The * SDK's retry layer handles 429 responses automatically. * * @see POST https://public.api.hospitable.com/v2/reservations/{uuid}/messages */ send(reservationId: string, body: string, options?: SendReservationMessageOptions): Promise; /** * Send a message on an inquiry (pre-booking conversation). * * The `inquiryUuid` is the conversation_id — same as `inquiry.id`. Use this * endpoint when a conversation exists but hasn't yet produced a reservation * (i.e. the guest is still in the "inquiry" stage). Once it becomes a * reservation, switch to {@link send} instead. * * Returns an async receipt with a `sentReferenceId` — match it against the * `sentReferenceId` on Message resources fetched afterwards to correlate * delivery on upstream channels (Airbnb, VRBO, etc). * * Rate limits: 2/minute per inquiry, 50 per 5 minutes globally. * * @see POST https://public.api.hospitable.com/v2/inquiries/{uuid}/messages * @throws {HospitableError} 410 if the inquiry has been deleted upstream. * @throws {RateLimitError} 429 after retries are exhausted (`.retryAfter` in seconds). * @throws {ValidationError} 422 if the conversation has already become a reservation — use {@link send} instead. */ sendForInquiry(inquiryUuid: string, body: string, options?: SendMessageOptions): Promise; /** * List available message templates. * * @see GET https://public.api.hospitable.com/v2/message-templates */ listTemplates(): Promise; /** * Send a message on a reservation using a message template. * * @see POST https://public.api.hospitable.com/v2/reservations/{uuid}/messages/template */ sendTemplate(reservationId: string, templateId: string, variables?: Record): Promise; } /** * Parameters for requesting a price quote on a property. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/quote */ interface CreateQuoteParams { /** ISO `YYYY-MM-DD` check-in date. */ checkinDate: string; /** ISO `YYYY-MM-DD` check-out date. */ checkoutDate: string; guests: { adults: number; children?: number; infants?: number; pets?: number; }; guestDetails?: { firstName?: string; lastName?: string; email?: string; phone?: string; }; promoCode?: string; } /** * Quote response from the API. Typed as `unknown` because the account * used for probing lacks the "Direct" feature required to generate quotes. * Narrow at the call site once the response shape is observed. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/quote */ type Quote = unknown; interface PropertyListParams { page?: number; perPage?: number; tags?: string[]; /** * Comma-separated include fields. Valid values are members of * {@link PropertyIncludeField}: `'user'`, `'listings'`, `'details'`, * `'bookings'`. Unknown values are silently ignored by the API — pass * only the literals to avoid typos that fail open. * * Example: `include: 'user,listings,details'` */ include?: string; } /** * Resource for the Hospitable Properties API. * * Properties rarely change, so this resource's default cache TTL is 24h * when caching is enabled. Cache is cleared automatically by the client * on 401 re-auth. * * @see https://developer.hospitable.com/docs/public-api-docs/1i1kr1bhpg0ku-properties-resource */ declare class PropertiesResource { private readonly http; private cache; constructor(http: HttpClient, cacheConfig?: CacheConfig); private fetchList; /** * List properties, optionally filtered by tags. * * @see GET https://public.api.hospitable.com/v2/properties */ list(params?: PropertyListParams): Promise; /** * Fetch a single property by UUID. * * Pass `include` as a comma-separated list of {@link PropertyIncludeField} * values — `'user'`, `'listings'`, `'details'`, `'bookings'` — to * side-load related data onto the response. * * **Envelope quirk**: unlike the list endpoint, the single-property * response is wrapped in `{data: Property}`. The SDK unwraps it so * callers always receive a bare {@link Property}. This is an API-side * inconsistency (also present on `/v2/user`), not an SDK bug. * * @see GET https://public.api.hospitable.com/v2/properties/{id} * @throws {NotFoundError} on 404 */ get(id: string, include?: string): Promise; /** * List all tags attached to a given property. These are the structured * org-level tags from the tag registry, distinct from the free-text * `Property.tags` field inline on the property object. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/tags */ listTags(id: string): Promise; /** * Fetch all images attached to a property, ordered by display position. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/images */ getImages(id: string): Promise; /** * Search for available properties matching a window and party size. * * All three of `startDate`, `endDate`, and `adults` are **required** by * the API — the SDK passes them through as-is and the server returns 400 * if any are missing. * * Unlike {@link list}, search results are availability-filtered — only * properties that can host the given dates/guests appear. * * @see GET https://public.api.hospitable.com/v2/properties/search */ search(params: PropertySearchParams): Promise; /** * Stream every property matching `params`, auto-paginating through all pages. * * Memory-efficient — pulls one page at a time. Pair with * `collectAll(client.properties.iter())` to drain into an array. */ iter(params?: Omit): AsyncGenerator; /** * Add tags to a property. The API accepts 1-10 tags per call. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/tags * @throws {ConfigurationError} when `tags` is empty or exceeds 10 items */ addTags(uuid: string, tags: string[]): Promise; /** * Request a price quote for a property. * * Requires the "Direct" feature on the Hospitable account. Response * shape is typed as `unknown` — see {@link CreateQuoteParams} for the * input contract. * * @returns The quote response from the API. Typed as `unknown` because * the return shape couldn't be probed (account lacks "Direct" feature). * Inspect the response object and narrow with a type guard at the call * site. Expected to contain pricing breakdown fields. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/quote */ createQuote(uuid: string, params: CreateQuoteParams): Promise; /** * Create an iCal import feed on a property. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/ical-imports */ createIcalImport(uuid: string, url: string, options?: CreateIcalImportOptions): Promise; /** * Update an existing iCal import feed on a property. * * @see PUT https://public.api.hospitable.com/v2/properties/{id}/ical-imports/{icalUuid} */ updateIcalImport(uuid: string, icalUuid: string, options?: UpdateIcalImportOptions): Promise; /** Drop the in-memory cache. Called automatically by the client on 401 re-auth. */ clearCache(): void; } /** * Status of a reservation as returned by the Hospitable API. * * Values are lowercase snake_case strings. Use {@link isReservationStatus} * to narrow an unknown string to this type. * * ⚠️ Spelling trap: the legacy {@link Reservation.status} and * {@link ReservationStatusHistoryEntry} fields use British `cancelled`, while * the older {@link ReservationLegacyStatusHistoryEntry} (exposed on the * `status_history` field) uses American `canceled`. New code should read * {@link Reservation.reservationStatus} and avoid both legacy shapes. */ type ReservationStatus$1 = 'not_accepted' | 'request' | 'accepted' | 'cancelled' | 'checkpoint'; declare const RESERVATION_STATUSES: readonly ["not_accepted", "request", "accepted", "cancelled", "checkpoint"]; /** Type guard for {@link ReservationStatus}. */ declare function isReservationStatus(value: unknown): value is ReservationStatus$1; /** * Booking platform the reservation originated on. Kept as an open string * union — the upstream API may surface additional platforms (`homeaway`, * `custom-direct`, etc.) that agents should pass through rather than reject. */ type ReservationPlatform = 'airbnb' | 'vrbo' | 'booking_com' | 'direct' | (string & {}); /** * Include fields accepted by `GET /v2/reservations` and `GET /v2/reservations/{id}`. * * Empirically verified against the live API on 2026-04-11. Unknown includes * are silently ignored by the server — passing an invalid value won't error, * it just won't populate any extra fields. */ type ReservationIncludeField = 'guest' | 'user' | 'financials' | 'listings' | 'properties' | 'review' | 'smartlock_code'; /** * Selector for which date field `startDate`/`endDate` filter against. * * - `checkin` (default) — filter by `check_in` date. Use this to find * reservations arriving in a window. * - `checkout` — filter by `check_out` date. Use this to find reservations * departing in a window, or guests currently in-house. * * The API only accepts these two literal values. Other values (including * `checkin_or_checkout`) return 400. */ type ReservationDateQuery = 'checkin' | 'checkout'; interface Guest { id: string; firstName: string; lastName: string; email: string | null; phoneNumbers: string[]; profilePicture: string | null; location: string | null; language: string; } interface ReservationGuests { total: number; adultCount: number; childCount: number; infantCount: number; petCount: number; } /** * A single line-item on a reservation's financial breakdown. Used by * every entry inside the `guest` and `host` subsections of * {@link ReservationFinancials} — accommodation, fees, discounts, taxes, * adjustments, payments, and totals all share this exact shape. * * ⚠️ **`amount` can be negative** — discounts and host-side service * fees arrive as negative integers (e.g. `-121365` for a * `-$1,213.65` early-bird discount). Don't assume positivity. */ interface ReservationFinancialLineItem { /** Minor currency units (cents for USD). May be negative. */ amount: number; /** Pre-formatted display string, e.g. `"$1,483.35"` or `"-$1,213.65"`. */ formatted: string; /** Human-readable label, e.g. `"Cleaning Fee"`, `"Early Bird Discount"`. */ label: string; /** * Grouping category. Values seen: `"Accommodation"`, `"Guest fees"`, * `"Guest total price"`, `"Host Tax"`, `"Service fees"`, `"Discounts"`, * `"Revenue"`. Open string union for forward compatibility. */ category: string; } /** * Guest-facing financial breakdown — what the guest is shown and charged * on the booking platform. Every sub-array is `[]` when no entries * apply; arrays are never `null`. */ interface ReservationFinancialsGuest$1 { /** Base room rate before fees/taxes/discounts. */ accommodation: ReservationFinancialLineItem; /** Accommodation amount divided by night count, for display. */ averageNightlyRate: ReservationFinancialLineItem; /** Guest-side fees (cleaning, pet, extra-guest, etc.). */ fees: ReservationFinancialLineItem[]; /** Guest-side discounts. Amounts are negative. */ discounts: ReservationFinancialLineItem[]; /** Taxes charged to the guest (occupancy, lodging, VAT, etc.). */ taxes: ReservationFinancialLineItem[]; /** Manual adjustments applied to the guest total. */ adjustments: ReservationFinancialLineItem[]; /** Payment records (typically populated post-stay). */ payments: ReservationFinancialLineItem[]; /** Final total charged to the guest. */ totalPrice: ReservationFinancialLineItem; } /** * Host-side financial breakdown — what the host earns after platform * fees. This is the "revenue" side of the ledger. */ interface ReservationFinancialsHost$1 { /** Base accommodation revenue. */ accommodation: ReservationFinancialLineItem; /** * Per-day rate breakdown. `null` when the stay is a single flat rate; * otherwise an array with one entry per night, labeled with the date. */ accommodationBreakdown: ReservationFinancialLineItem[] | null; /** Fees collected from the guest and passed through to the host. */ guestFees: ReservationFinancialLineItem[]; /** Host-side service fees charged by the platform. Amounts typically negative. */ hostFees: ReservationFinancialLineItem[]; /** Host-side discounts (promotional, loyalty, etc.). Amounts negative. */ discounts: ReservationFinancialLineItem[]; /** Manual adjustments applied to host revenue. */ adjustments: ReservationFinancialLineItem[]; /** Taxes withheld from host revenue (rare — usually guest-side). */ taxes: ReservationFinancialLineItem[]; /** Final amount the host receives after all adjustments. */ revenue: ReservationFinancialLineItem; } /** * Full financial breakdown for a reservation. Returned when the * `include=financials` query parameter is passed to the reservations * list or get endpoint. Requires the `financials:read` OAuth2 scope on * the access token. * * Split into `guest` (what the guest pays) and `host` (what the host * receives). The two sides are reconciled via platform fees, taxes, and * service charges — see {@link ReservationFinancialsHost.hostFees} for * the platform's cut. * * @see GET https://public.api.hospitable.com/v2/reservations (include=financials) */ interface ReservationFinancials$1 { /** ISO 4217 currency code (e.g. `"USD"`). */ currency: string; guest: ReservationFinancialsGuest$1; host: ReservationFinancialsHost$1; } /** * Structured status object returned by the current API on the * `reservation_status` field. Carries both the current state and a full * history of transitions with sub-category detail the flat {@link * Reservation.status} string cannot express (e.g. `accepted` + * `early_checkin_requested`). * * Prefer this over {@link Reservation.status} / {@link Reservation.statusHistory} * in new code. */ interface ReservationStatusObject { current: { category: ReservationStatus$1; subCategory: string | null; }; history: ReservationStatusHistoryEntry[]; } interface ReservationStatusHistoryEntry { category: ReservationStatus$1; subCategory: string | null; changedAt: string; } /** * Legacy status history entry exposed on the `status_history` field. * * ⚠️ The `status` field here uses **American** spelling (`canceled`) while * everything else in the API uses British spelling (`cancelled`). Strict * equality against `'cancelled'` will silently miss matches. Migrate to * {@link ReservationStatusObject.history} which uses consistent British spelling. * * @deprecated Use {@link Reservation.reservationStatus}. */ interface ReservationLegacyStatusHistoryEntry { /** Human-readable label, e.g. "Accepted", "Cancelled". */ category: string; /** Raw status value — **uses American spelling** (`canceled` vs `cancelled`). */ status: string; changedAt: string; } interface Reservation$1 { id: string; code: string; platform: ReservationPlatform; platformId: string; bookingDate: string; arrivalDate: string; departureDate: string; checkIn: string; checkOut: string; nights: number; stayType: string; ownerStay: boolean | null; /** * Structured status with history. Preferred over {@link status} and * {@link statusHistory} — carries sub-category detail the flat string * cannot express, and uses consistent British spelling throughout. */ reservationStatus: ReservationStatusObject; /** * Legacy flat status string. Uses British spelling (`cancelled`). * @deprecated Read {@link reservationStatus}.current.category instead. */ status: ReservationStatus$1; /** * Legacy status history array. * * ⚠️ **Spelling trap**: each entry's `.status` field uses **American** * spelling (`canceled`) while the modern {@link ReservationStatus} union * uses British spelling (`cancelled`). Strict-equality checks against * `'cancelled'` would silently miss matches on raw API data. * * The SDK's `ReservationsResource` normalizes this on every response * (via `normalizeReservation()`), so you'll actually see `'cancelled'` * here when reading through the client. But if you receive a Reservation * from any other source — webhook payload, cached pre-normalization, * hand-constructed test fixture — the raw value may still be `'canceled'`. * * @deprecated Read {@link reservationStatus}.history instead — it uses * consistent British spelling upstream and includes `subCategory` * detail this legacy field can't express. */ statusHistory: ReservationLegacyStatusHistoryEntry[]; guests: ReservationGuests; /** Only populated when `include=guest` is requested. */ guest?: Guest; /** Only populated when `include=user` is requested. */ user?: ReservationUser; /** * Full financial breakdown. Populated only when `include=financials` * is requested and the access token has the `financials:read` scope. */ financials?: ReservationFinancials$1; /** Only populated when `include=properties` is requested. */ properties?: unknown[]; /** Only populated when `include=listings` is requested. */ listings?: unknown[]; /** * Only populated when `include=review` is requested. `null` when the * reservation has no review yet (e.g. still in progress, or cancelled). */ review?: unknown | null; /** * Smart-lock access code for the property during this reservation, * typically a 4-digit numeric string. Populated only when * `include=smartlock_code` is requested. `null` when the property has * no smart lock configured, or the reservation doesn't have a code * assigned yet (e.g. cancelled, far-future, not-accepted). * * This field is **not** redacted by `sanitize()` — like `wifiPassword` * on a property, it's a shareable credential an agent needs to include * in guest check-in messages. Don't log raw Reservation objects to * stdout in contexts where bystanders might see them. * * Wire format: the API serializes this as `smartlock_code` * (snake_case); the SDK's `deepSnakeToCamel` converts it to * `smartlockCode` on the TypeScript side. */ smartlockCode?: string | null; notes: string | null; conversationId: string; conversationLanguage: string | null; lastMessageAt: string | null; issueAlert: unknown; } /** User/host attached to a reservation via `include=user`. */ interface ReservationUser { id: string; email: string; name: string; profilePicture: string | null; } type ReservationList = PaginatedResponse; /** * Normalize a Reservation returned by the API so legacy fields are safe * to compare against modern `ReservationStatus` values. * * Specifically: the legacy `status_history[].status` field uses American * spelling (`canceled`), while every other status field in the API uses * British spelling (`cancelled`). An agent doing * `r.statusHistory.some(h => h.status === 'cancelled')` would silently * miss cancelled reservations — a business-logic bug with real financial * impact (charges sent to guests who canceled, "in-house" classification * of guests who canceled, etc.). * * This normalizer rewrites `canceled` → `cancelled` in place on each * `statusHistory` entry's `status` field. It's called by * `ReservationsResource.list()`, `.get()`, and `.iter()` so consumers * always see consistent British spelling. * * Idempotent and safe on partial / incomplete data: missing fields are * left alone. * * Contract: * - Mutates and returns the same reservation object. * - Only touches `statusHistory[].status` when the value is exactly * `'canceled'` — any other value is preserved. */ declare function normalizeReservation(reservation: Reservation$1): Reservation$1; /** * Who initiated the cancellation — used as the body of * `POST /v2/reservations/{uuid}/cancel`. */ type CancelReservationInitiatedBy = 'host' | 'guest'; /** * WRITE-side input shape for reservation financials. NOT the same as * {@link ReservationFinancials} (READ-side with nested guest/host * subsections). All amounts in minor currency units (cents). * * @see POST https://public.api.hospitable.com/v2/reservations */ interface CreateReservationFinancials { /** ISO 4217 currency code (e.g. `"USD"`). */ currency: string; /** Base accommodation amount in minor currency units. */ accommodation: number; cleaningFee?: number; linenFee?: number; managementFee?: number; communityFee?: number; petFee?: number; resortFee?: number; passThroughTaxes?: number; otherFees?: Array<{ label: string; amount: number; }>; } /** Guest contact info for creating a reservation. */ interface CreateReservationGuest { firstName: string; lastName: string; email: string; phone?: string; } /** Guest headcounts for creating/updating a reservation. */ interface CreateReservationGuestCounts { adults: number; children?: number; infants?: number; pets?: number; } /** * Parameters for `POST /v2/reservations` — creating a direct reservation. * * @see POST https://public.api.hospitable.com/v2/reservations */ interface CreateReservationParams { propertyId: string; /** ISO `YYYY-MM-DD` check-in date. */ checkIn: string; /** ISO `YYYY-MM-DD` check-out date. */ checkOut: string; guests: CreateReservationGuestCounts; guest: CreateReservationGuest; /** Two-letter language code (e.g. `"en"`). */ language: string; financials: CreateReservationFinancials; channel?: string; notes?: string; reservationCode?: string; include?: string; } /** * Parameters for `PUT /v2/reservations/{uuid}` — updating an existing * reservation. Currency is not required on update (inherited from the * existing reservation). * * @see PUT https://public.api.hospitable.com/v2/reservations/{uuid} */ interface UpdateReservationParams { checkIn: string; checkOut: string; guests: CreateReservationGuestCounts; guest: CreateReservationGuest; language: string; financials: Omit; notes?: string; include?: string; } interface ReservationListParams$1 { /** * Property UUIDs to scope the search to. **Required by the API** — omit * this and the server returns `400 "The properties field is required."`. * The SDK throws a {@link ConfigurationError} before the request is sent * so agents get actionable feedback without a round trip. */ properties: string[]; /** ISO `YYYY-MM-DD` — lower bound on the date field chosen by `dateQuery`. */ startDate?: string; /** ISO `YYYY-MM-DD` — upper bound on the date field chosen by `dateQuery`. */ endDate?: string; /** * Which date field `startDate`/`endDate` filter against. * Defaults to `checkin` on the API side if omitted. */ dateQuery?: ReservationDateQuery; /** * Only reservations whose last-message timestamp is on or after this value. * * ⚠️ Format quirk: the API expects **`YYYY-MM-DD HH:MM:SS`** (space-separated, * no timezone), NOT ISO 8601. Example: `'2026-01-15 14:30:00'`. */ lastMessageAt?: string; /** * Filter by reservation status. Single value or array. Serialized as * repeated `status[]=` query params. */ status?: ReservationStatus$1 | ReservationStatus$1[]; /** * Comma-separated include fields. Prefer {@link ReservationIncludeField}. * Unknown values are silently ignored by the API. */ include?: string; page?: number; perPage?: number; } /** * A single enrichment field on a reservation — key/value metadata that * agents or integrations attach to a booking for downstream workflows * (e.g. guest verification status, arrival time, parking instructions). * * @see GET https://public.api.hospitable.com/v2/reservations/{id}/enrichment */ interface EnrichmentField { key: string; value: string | null; description: string; example: string; } /** * Resource for the Hospitable Reservations API. * * Default cache TTL is 60 seconds when caching is enabled — reservations * move too quickly for long-lived caching. * * @see https://developer.hospitable.com/docs/public-api-docs/a6ba5e23bc9cb-reservations-resource */ declare class ReservationsResource$1 { private readonly http; private cache; constructor(http: HttpClient, cacheConfig?: CacheConfig); /** * Private fetcher used by `list()` and `iter()`. Trusts its caller to * have already validated `params.properties` via `assertPropertiesPresent` * — do not call this directly without validation. */ private fetchList; /** * List reservations, filtered by the supplied params. * * `params.properties` is required — the API returns 400 without it, so the * SDK throws a {@link ConfigurationError} before making the request. * * Use `dateQuery` to choose whether `startDate`/`endDate` filter against * `check_in` (default) or `check_out`. Swap to `'checkout'` to find * reservations departing in a window or guests currently in-house — see * {@link getInHouse} for the convenience wrapper. * * Every returned reservation passes through `normalizeReservation()` so * the legacy `statusHistory[].status` field uses consistent British * spelling (`'cancelled'`, not `'canceled'`) — see the type's JSDoc for * the full rationale. * * @see {@link ReservationFilter} for a fluent builder * @see GET https://public.api.hospitable.com/v2/reservations * @throws {ConfigurationError} when `properties` is empty or missing */ list(params: ReservationListParams$1): Promise; /** * Fetch a single reservation by UUID. * * **Envelope quirk**: unlike the list endpoint, the single-reservation * response is wrapped in `{data: Reservation}`. The SDK unwraps it so * callers always receive a bare {@link Reservation}. Mutating endpoints * ({@link cancel}, {@link create}, {@link update}) wrap their responses * the same way and unwrap identically. * * @see GET https://public.api.hospitable.com/v2/reservations/{id} * @throws {NotFoundError} on 404 */ get(id: string, include?: string): Promise; /** * Convenience wrapper: accepted reservations arriving on or after today, * for the given properties. Equivalent to * `list({ properties, startDate: today, status: 'accepted', dateQuery: 'checkin' })`. * * Defaults `include` to `'guest,properties'` so agents get a useful * payload without needing to remember the include-field list. */ getUpcoming(propertyIds: string[], options?: { include?: string; }): Promise; /** * Convenience wrapper: guests **currently in-house** — accepted * reservations that have started but not yet ended. * * Returns a plain `Reservation[]` rather than a paginated wrapper because * this method performs a client-side filter and pagination metadata from * the upstream response would be misleading (it would count reservations * filtered out locally). * * Implementation: streams `iter()` with `dateQuery: 'checkout'` and * `startDate: today` — fetching every reservation whose check-out is * today or later (haven't departed yet) — and filters locally to those * whose `arrivalDate` is today or earlier (already arrived). * * The two-filter approach is necessary because the Hospitable API only * accepts a single `date_query` at a time, and "in-house" needs * constraints on both check-in and check-out. * * Defaults `include` to `'guest,properties'` so agents have usable data * without remembering the include-field list. * * ⚠️ **Timezone caveat**: "today" is computed from the SDK host's UTC * clock (`new Date().toISOString().split('T')[0]`), not from each * property's local timezone. For properties in strongly offset * timezones (e.g. Hawaii at UTC-10), calling this method during the * UTC-boundary window (~0:00–10:00 UTC) can misclassify a same-day * turnover by one day — a guest arriving "today" local time may read * as arriving "yesterday" UTC, and the filter may either include or * exclude them depending on their check-out date. If your properties * span multiple timezones and you need millisecond-correct boundary * behavior, query `list()` directly with a timezone-aware `today`. */ getInHouse(propertyIds: string[], options?: { include?: string; }): Promise; /** * Stream every reservation matching `params`, auto-paginating through all pages. * * Memory-efficient — pulls one page at a time. Pair with * `collectAll(client.reservations.iter(...))` to drain into an array. * * @throws {ConfigurationError} when `params.properties` is empty or missing */ iter(params: Omit): AsyncGenerator; /** * Cancel a reservation. * * @see POST https://public.api.hospitable.com/v2/reservations/{uuid}/cancel */ cancel(uuid: string, initiatedBy: CancelReservationInitiatedBy): Promise; /** * Create a new direct reservation. * * @see POST https://public.api.hospitable.com/v2/reservations */ create(params: CreateReservationParams): Promise; /** * Update an existing reservation. * * @see PUT https://public.api.hospitable.com/v2/reservations/{uuid} */ update(uuid: string, params: UpdateReservationParams): Promise; /** * List all enrichment fields for a reservation. * * @see GET https://public.api.hospitable.com/v2/reservations/{uuid}/enrichment */ listEnrichment(uuid: string): Promise; /** * Get a single enrichment field by key. * * @see GET https://public.api.hospitable.com/v2/reservations/{uuid}/enrichment/{key} */ getEnrichment(uuid: string, key: string): Promise; /** * Update a single enrichment field. Pass `null` to clear the value. * * @see PUT https://public.api.hospitable.com/v2/reservations/{uuid}/enrichment/{key} */ updateEnrichment(uuid: string, key: string, value: string | null): Promise; /** Drop the in-memory cache. Called automatically by the client on 401 re-auth. */ clearCache(): void; } /** * Detailed rating category returned inside `private.detailed_ratings`. * * Airbnb returns all 9 values even when the platform doesn't collect them * (zeroed out) — see `facilities`, `staff`, `services`, which are VRBO / * Booking.com only. Kept as an open string union so the SDK doesn't reject * future categories the API may add. */ type ReviewDetailedRatingType = 'value' | 'cleanliness' | 'communication' | 'location' | 'checkin' | 'accuracy' | 'facilities' | 'staff' | 'services' | (string & {}); interface ReviewDetailedRating$1 { type: ReviewDetailedRatingType; /** Integer 0-5. `0` means the category was not rated on this platform. */ rating: number; comment: string | null; } /** * Public-facing portion of a review — what the guest chose to publish on * the booking platform. Visible to future guests considering the listing. */ interface ReviewPublic { /** Normalized integer 1-5. */ rating: number; /** Platform's original rating string (e.g. `"5.00"`, `"4.5/5"`). Provider-specific format. */ ratingPlatformOriginal: string; /** Guest's public review text. May be empty string. */ review: string; /** Host's public response, if any. */ response: string | null; } /** * Private host feedback attached to a review — not shown to other guests. * Hospitable exposes it here alongside the public side. */ interface ReviewPrivate { /** Host-only feedback text. `null` when the guest left no private note. */ feedback: string | null; detailedRatings: ReviewDetailedRating$1[]; } /** * Minimal guest info returned when `include=guest` is passed to the * reviews list endpoint. Deliberately sparse — only first/last name and * language are exposed (no email/phone). If you need richer guest data, * fetch the reservation via `client.reservations.get(reservationId, * 'guest')`. */ interface ReviewGuest { firstName: string; lastName: string; language: string; } /** * Minimal reservation info returned when `include=reservation` is passed. * Contains just enough to cross-reference without a second API call. * For the full reservation, call `client.reservations.get(review.reservation.id)`. */ interface ReviewReservation { id: string; /** Platform-facing reservation code (e.g. `HMQBZEMSPZ`). */ code: string; /** ISO 8601 with timezone offset. */ checkIn: string; /** ISO 8601 with timezone offset. */ checkOut: string; } /** * Minimal property info returned when `include=property` is passed. * Contains just enough to label the review without a second API call — * useful for building "recent reviews across all properties" feeds. * For the full property, call `client.properties.get(review.property.id)`. */ interface ReviewProperty { id: string; /** Internal property name (host-facing). */ name: string; /** Public-facing listing name shown to guests on booking platforms. */ publicName: string; } /** * A guest review from a booking platform. * * @see https://developer.hospitable.com/docs/public-api-docs/v8ue8kuzpfgvj-reviews-resource */ interface Review$1 { id: string; platform: string; public: ReviewPublic; private: ReviewPrivate; /** ISO 8601 — when the guest submitted the review on the platform. */ reviewedAt: string; /** ISO 8601 — when the host responded, or `null` if not yet responded. */ respondedAt: string | null; /** * Whether the host can still post a response. `false` after the * platform's response window closes, or after the review is finalized. */ canRespond: boolean; /** Populated only when `include=guest` is requested. */ guest?: ReviewGuest; /** Populated only when `include=reservation` is requested. */ reservation?: ReviewReservation; /** Populated only when `include=property` is requested. */ property?: ReviewProperty; } type ReviewList = PaginatedResponse; /** * Include fields accepted by the reviews list endpoint. * * Empirically verified against the live API on 2026-04-11. Note that * `reservation` is **singular** — passing `'reservations'` (plural) * returns HTTP 200 with no side-loaded field (silent ignore). Same for * `property` vs `'properties'` — use the singular form. */ type ReviewIncludeField = 'guest' | 'reservation' | 'property'; interface ReviewListParams$1 { /** Filter by whether the host has responded. Omit to include both. */ responded?: boolean; /** * Comma-separated include fields. Prefer {@link ReviewIncludeField}. * Unknown values are silently ignored by the API. * * Example: `'guest,reservation'` — populates both `review.guest` and * `review.reservation` on each returned object. */ include?: string; page?: number; perPage?: number; } /** * Body for posting a host response to a review. * * @see POST https://public.api.hospitable.com/v2/reviews/{id}/respond */ interface ReviewRespondBody { response: string; } /** * Resource for listing and responding to guest reviews. * * Reviews are scoped to a property: all list/iter calls take a `propertyId` * as the first argument. Use `params.responded = false` to pull only the * reviews still awaiting a host response. * * @see https://developer.hospitable.com/docs/public-api-docs/v8ue8kuzpfgvj-reviews-resource */ declare class ReviewsResource$1 { private readonly http; constructor(http: HttpClient); private fetchList; /** * List reviews for a property. Pass `{ responded: false }` to surface * only reviews still waiting on a host response. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/reviews */ list(propertyId: string, params?: ReviewListParams$1): Promise; /** * Post a host response to a review. * * @see POST https://public.api.hospitable.com/v2/reviews/{id}/respond */ respond(id: string, responseText: string): Promise; /** * Stream every review matching `params` for a property, auto-paginating * through all pages. */ iter(propertyId: string, params?: Omit): AsyncGenerator; } /** * Authenticated user and business/billing info returned by `GET /v2/user`. * * This is the single "who am I" endpoint — useful for agents to discover * the account's company metadata, billing address, and host identity * without scraping it from a reservation include. * * @see GET https://public.api.hospitable.com/v2/user */ interface User { id: string; email: string; name: string; profilePicture: string | null; /** `true` when the account is configured as a business entity. */ business: boolean; /** Registered company name, if any. */ company: string | null; /** VAT identifier (European accounts). */ vat: string | null; /** Tax ID (e.g. EIN in the US). */ taxId: string | null; /** Billing address line 1. */ streetLine1: string | null; /** Billing address line 2. */ streetLine2: string | null; postalCode: string | null; city: string | null; state: string | null; country: string | null; } /** * Resource for the single-user `/v2/user` endpoint. * * Returns the authenticated account's identity + business profile. This is * the canonical "who am I" call — agents can use it to discover the * account's company metadata, billing address, and host identity without * scraping it from a reservation include. * * **Envelope quirk**: unlike `/v2/properties/{id}` which returns the * resource object directly, `/v2/user` wraps its response in `{data: ...}`. * The SDK unwraps this envelope so callers get a bare {@link User} object. * This is an API-side inconsistency, not an SDK bug — see * `examples/probe-api-surface.ts` for the raw shape. * * **Not cached**: user identity changes rarely but not never (business * profile edits, email changes). The SDK does not cache this response; if * you're calling it in a hot loop, hoist the result yourself. * * @see GET https://public.api.hospitable.com/v2/user */ declare class UserResource { private readonly http; constructor(http: HttpClient); /** * Fetch the authenticated user's profile and business info. * * @see GET https://public.api.hospitable.com/v2/user */ get(): Promise; } /** * A money amount with currency metadata. The API returns these as nested * objects rather than primitive numbers so you get the pre-formatted * display string alongside the raw integer (cents). */ interface Money { /** Amount in minor currency units (cents for USD, pence for GBP, etc.). */ amount: number; /** Pre-formatted display string, e.g. `"$191.48"`. */ formatted: string; /** ISO 4217 currency code. */ currency: string; } /** * A financial transaction — rent collected, payout issued, refund, etc. * * The Hospitable API mixes several transaction kinds under the same * endpoint. Check {@link Transaction.type} to distinguish. * * @see GET https://public.api.hospitable.com/v2/transactions */ interface Transaction$1 { id: string; platform: string; /** * Transaction kind. Values seen: `"Payout"`, `"Rent"`, `"Refund"`, * `"Adjustment"`. Kept as open string union. */ type: string; /** Free-text description, e.g. bank account "••4169 (USD)". */ details: string | null; /** Platform-provided reference/external id. */ reference: string | null; /** ISO 4217 currency code. */ currency: string; /** * Raw amount. The API sometimes returns `null` here when * {@link paidOutAmount} is used instead (e.g. for Payout rows). Prefer * reading both fields and falling through. */ amount: number | null; /** Structured amount for payout rows. */ paidOutAmount: Money | null; /** Transaction date (ISO 8601). */ date: string; /** Start of the period this transaction covers, for range-based rows. */ startDate: string | null; /** Populated when `include=payout` is requested. */ payout?: unknown; /** Populated when `include=reservation` is requested. */ reservation?: unknown; } type TransactionList = PaginatedResponse; interface TransactionListParams$1 { /** ISO `YYYY-MM-DD` — lower bound on transaction date. */ startDate?: string; /** ISO `YYYY-MM-DD` — upper bound on transaction date. */ endDate?: string; /** Scope to specific property UUIDs. */ properties?: string[]; page?: number; perPage?: number; } /** * Resource for the Hospitable Transactions API. * * Requires the `financials:read` scope on the access token. * * ⚠️ **Unbounded-query risk for agents**: unlike `reservations.list()`, * this endpoint does not require any mandatory filter. Calling * `transactions.iter()` with no params will stream the account's **entire * transaction history** (hundreds to thousands of rows on active * accounts). Always pass `startDate`/`endDate` or `properties` to scope * the query when building agentic workflows — a prompt-injected agent * that calls `iter()` without bounds will happily exfiltrate the full * financial history in one turn. * * @see GET https://public.api.hospitable.com/v2/transactions */ declare class TransactionsResource$1 { private readonly http; constructor(http: HttpClient); private fetchList; /** * Fetch a single transaction by UUID. * * @see GET https://public.api.hospitable.com/v2/transactions/{uuid} * @throws {NotFoundError} on 404 */ get(uuid: string, include?: string): Promise; /** * List financial transactions. Use `startDate`/`endDate` to scope to a * reporting window. * * @see GET https://public.api.hospitable.com/v2/transactions */ list(params?: TransactionListParams$1): Promise; /** * Stream every transaction matching `params`, auto-paginating through * all pages. * * ⚠️ **Always pass bounds.** Calling this with no params streams the * entire account history — see the resource-level JSDoc. Prefer * `{ startDate, endDate }` or `{ properties }` scoping, especially in * agent-driven code paths. */ iter(params?: Omit): AsyncGenerator; } /** * A payout — money disbursed from the platform to the host's bank account. * * Payouts are a narrower view than {@link Transaction} — they represent * the actual bank-transfer events, not the underlying rental income. * * @see GET https://public.api.hospitable.com/v2/payouts */ interface Payout$1 { id: string; platform: string; /** Platform's payout identifier (e.g. Airbnb's `G-...`). */ platformId: string; /** Human-readable bank account display, e.g. `"LLC Checking ••4169 (USD)"`. */ bankAccount: string; reference: string | null; amount: Money; /** ISO 8601 timestamp of when the payout was disbursed. */ date: string; /** Populated when `include=transactions` is requested. */ transactions?: unknown[]; } type PayoutList = PaginatedResponse; interface PayoutListParams$1 { /** ISO `YYYY-MM-DD` — lower bound on payout date. */ startDate?: string; /** ISO `YYYY-MM-DD` — upper bound on payout date. */ endDate?: string; /** Scope to specific property UUIDs. */ properties?: string[]; page?: number; perPage?: number; } /** * Resource for the Hospitable Payouts API. * * Requires the `financials:read` scope on the access token. * * ⚠️ **Unbounded-query risk for agents**: like {@link TransactionsResource}, * this endpoint does not require any mandatory filter. Calling * `payouts.iter()` with no params will stream the **entire payout * history** (often hundreds of rows). Scope with `startDate`/`endDate` or * `properties` when building agent workflows, especially if inputs may * be attacker-influenced. * * @see GET https://public.api.hospitable.com/v2/payouts */ declare class PayoutsResource$1 { private readonly http; constructor(http: HttpClient); private fetchList; /** * Fetch a single payout by UUID. * * @see GET https://public.api.hospitable.com/v2/payouts/{uuid} * @throws {NotFoundError} on 404 */ get(uuid: string, include?: string): Promise; /** * List payouts. Use `startDate`/`endDate` to scope to a reporting window. * * @see GET https://public.api.hospitable.com/v2/payouts */ list(params?: PayoutListParams$1): Promise; /** * Stream every payout matching `params`, auto-paginating through all pages. * * ⚠️ **Always pass bounds.** See resource-level JSDoc for the rationale. */ iter(params?: Omit): AsyncGenerator; } /** * A data source that contributed content to the Knowledge Hub — e.g. inbox * auto-detection, manual entry, or a third-party integration. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub */ interface KnowledgeHubSource { id: number; type: string; name: string; state: string; editable: boolean; parsedAt: string; metadata: unknown[]; } /** * A single knowledge item within a {@link KnowledgeHubTopic}. Items are * the atomic pieces of information the AI draws on when composing guest * replies. */ interface KnowledgeHubItem { id: number; content: string; originalContent: string | null; isEdited: boolean; state: string; createdVia: string | null; lastUpdatedVia: string | null; sources: KnowledgeHubSource[]; updatedAt: string; } /** * A topic grouping within the Knowledge Hub — e.g. "Local Attractions", * "Check-in Instructions", "Pool Rules". Each topic contains one or more * {@link KnowledgeHubItem} entries. */ interface KnowledgeHubTopic { id: number; name: string; createdVia: string | null; lastUpdatedVia: string | null; aggregateItems: KnowledgeHubItem[]; updatedAt: string; } /** Property summary embedded in the Knowledge Hub response. */ interface KnowledgeHubProperty { id: number; name: string; picture: string; } /** * Full Knowledge Hub payload for a property — topics, items, and sources. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub */ interface KnowledgeHub { property: KnowledgeHubProperty; sources: KnowledgeHubSource[]; topics: KnowledgeHubTopic[]; } /** * Options for creating a Knowledge Hub item. * * Supply either `topicId` (to append to an existing topic) or `topicName` * (to create a new topic and add the item under it). If both are provided, * `topicId` takes precedence on the API side. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/items */ interface CreateKnowledgeHubItemOptions { topicId?: number; topicName?: string; } /** * Options for updating a Knowledge Hub item. * * @see PUT https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/items/{itemId} */ interface UpdateKnowledgeHubItemOptions { topicId?: number; topicName?: string; } /** * Resource for the Hospitable Knowledge Hub API. * * The Knowledge Hub stores structured Q&A content that the Hospitable AI * draws on when composing guest replies. Content is organized by * property, grouped into topics, and broken into individual items. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub */ declare class KnowledgeHubResource { private readonly http; constructor(http: HttpClient); /** * Fetch the full Knowledge Hub for a property — topics, items, and sources. * * @see GET https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub */ get(propertyUuid: string): Promise; /** * Create a new Knowledge Hub item under an existing or new topic. * * Pass `topicId` to append to an existing topic, or `topicName` to * create a new topic and add the item under it. * * @see POST https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/items */ createItem(propertyUuid: string, content: string, options?: CreateKnowledgeHubItemOptions): Promise; /** * Update an existing Knowledge Hub item's content and/or topic assignment. * * @see PUT https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/items/{itemId} */ updateItem(propertyUuid: string, itemId: number, content: string, options?: UpdateKnowledgeHubItemOptions): Promise; /** * Delete a Knowledge Hub item. * * @see DELETE https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/items/{itemId} */ deleteItem(propertyUuid: string, itemId: number): Promise; /** * Delete an entire Knowledge Hub topic and all its items. * * @see DELETE https://public.api.hospitable.com/v2/properties/{id}/knowledge-hub/topics/{topicId} */ deleteTopic(propertyUuid: string, topicId: number): Promise; } interface ResourceCacheConfig { properties?: CacheConfig; reservations?: CacheConfig; inquiries?: CacheConfig; } interface HospitableClientConfig { /** Personal Access Token. Also read from HOSPITABLE_API_PAT env var. */ token?: string; /** OAuth2 refresh token */ refreshToken?: string; /** OAuth2 client ID */ clientId?: string; /** OAuth2 client secret */ clientSecret?: string; /** API base URL. Defaults to https://public.api.hospitable.com */ baseURL?: string; /** Retry configuration */ retry?: RetryConfig; /** Enable debug logging */ debug?: boolean; /** Cache configuration per resource */ cache?: ResourceCacheConfig; } declare class HospitableClient { readonly properties: PropertiesResource; readonly reservations: ReservationsResource$1; readonly calendar: CalendarResource; readonly messages: MessagesResource; readonly reviews: ReviewsResource$1; readonly inquiries: InquiriesResource; readonly user: UserResource; readonly transactions: TransactionsResource$1; readonly payouts: PayoutsResource$1; readonly knowledgeHub: KnowledgeHubResource; constructor(config?: HospitableClientConfig); } /** * An AuthCode is a 5-minute magic link used to authenticate a * {@link Customer} into Hospitable Connect so they can connect, * reconnect, or refresh a channel. The customer must already exist * before requesting an auth code. * * `returnUrl` is the URL to send the customer to. * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface AuthCode { expiresAt: string; returnUrl: string; } /** * Request body for `POST /auth-codes`. `customerId` identifies which * customer the link authenticates. `redirectUrl` is where Hospitable * returns the user after the connect/reconnect flow completes. */ interface CreateAuthCodeInput { customerId: string; /** * URL Hospitable redirects the customer to after a successful * channel-connection flow. Must be a fully-qualified HTTPS URL. */ redirectUrl?: string; } /** * Resource for the Connect Auth Codes API. * * Auth codes are 5-minute magic links used to authenticate a Customer * into Hospitable Connect. The customer must already exist before * requesting a code. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class AuthCodesResource { private readonly http; constructor(http: HttpClient); /** * Create an auth code for a customer. Returns the magic-link URL to * send the customer to and its absolute expiry timestamp (5 minutes). * * @see POST https://connect.hospitable.com/api/v1/auth-codes */ create(input: CreateAuthCodeInput): Promise; } /** * Financial amount object. `amount` is an integer in the minor unit of * `currency` (e.g. cents for USD, öre for SEK). `formatted` is the * server-rendered display string. `label` describes the line item when * the financial appears in an array (taxes, fees, discounts). */ interface Financial { amount: number; formatted: string; currency: string; label: string | null; } /** * OTA platform identifier on Connect entities. Currently only `'airbnb'` * is returned for connected channels, but kept as an open string union * to tolerate future additions without breaking the type. */ type ConnectPlatform = 'airbnb' | (string & {}); /** * Pagination `links` object on a Connect paginated list. All members * except `first` may be `null` depending on current position. */ interface ConnectPaginationLinks { first: string; last: string | null; prev: string | null; next: string | null; } /** * Pagination `meta` object on a Connect paginated list. * * Note: Connect's `meta` shape differs from the Public API — * `current_page`, `from`, `to`, `path`, `per_page` and (sometimes) * `total`. The Public SDK's shape (`currentPage`, `lastPage`, `perPage`, * `total`) is not one-to-one compatible, so this is a separate type. */ interface ConnectPaginationMeta { currentPage: number; from: number | null; to: number | null; path: string; perPage: number; total?: number; lastPage?: number; } /** * Standard Connect list envelope. `links` and `meta` are always present; * `data` is the resource array. */ interface ConnectPaginatedResponse { data: T[]; links: ConnectPaginationLinks; meta: ConnectPaginationMeta; } /** * A Channel represents an established connection with an OTA (currently * only Airbnb) via a customer's Hospitable account. Channels are * created through the auth-code / magic-link flow and subsequently * sync listings, reservations, and reviews. * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface Channel { id: string; platform: ConnectPlatform; platformId: string; name: string; picture: string | null; location: string | null; description: string | null; firstConnectedAt: string; /** * `true` when the customer's channel has already been connected to a * full Hospitable account (indicating the customer could be migrated * from Connect to a direct Hospitable subscription). `null` when the * platform has not computed this flag. */ readyToMigrate: boolean | null; } /** * A Customer represents a single user of the partner application. Each * customer owns zero or more {@link Channel} connections. Partner-chosen * IDs are allowed — pass any stable string in `id` at creation. * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface Customer { id: string; email: string; name: string; phone: string; /** IPv4 of the end-user at channel-connection time. `null` if unknown. */ ipAddress: string | null; /** IANA timezone identifier, e.g. `'UTC'`, `'America/Los_Angeles'`. */ timezone: string; } /** * Request body for `POST /customers`. The partner provides `id` as a * stable external identifier (their own user ID); the other fields seed * the channel-connection flow. */ interface CreateCustomerInput { id: string; email: string; name: string; phone: string; timezone: string; } interface ListingAddress { street: string; zipcode: string; city: string; state: string; apt: string; countryCode: string; latitude: number; longitude: number; } interface ListingCapacity { max: number | null; bedrooms: number | null; beds: number | null; bathrooms: number | null; } interface ListingRoomBed { type: string; quantity: number; } /** * Room-by-room layout. Non-sleeping rooms (kitchen, living_room) * appear with an empty `beds` array. */ type ListingRoomDetails = Array<{ beds: ListingRoomBed[]; }>; interface ListingDetails { spaceOverview: string | null; guestAccess: string | null; houseManual: string | null; notes: string | null; additionalRules: string | null; neighborhoodDescription: string | null; gettingAround: string | null; wifiName: string | null; wifiPassword: string | null; } interface ListingHouseRules { petsAllowed: boolean; smokingAllowed: boolean; eventsAllowed: boolean; } /** * A per-listing fee configured by the host. `fee` is either a * {@link Financial} (when `type === 'flat'`) or an integer percentage * (when `type === 'percent'`). `chargeType` determines the multiplier * (per group / per pet / per person) and `chargePeriod` determines * whether the fee applies per night or once per booking. */ interface ListingFee { name: string; type: 'flat' | 'percent'; fee: Financial | number; chargeType: 'per_group' | 'per_pet' | 'per_person'; chargePeriod: 'per_night' | 'per_booking'; } /** * A listing is a rentable unit on an OTA channel. Channels may expose * the same listing under `channel` (primary) and `channels` (all). * * **Field naming quirk:** the API returns `check-in` and `check-out` * with a hyphen, not underscore. The SDK's snake-to-camel converter * only transforms underscores, so these keys pass through unchanged * — hence the quoted property names below. * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface Listing { id: string; platform: ConnectPlatform; platformId: string; publicName: string; privateName: string; summary: string; description: string; roomType: string; propertyType: string; picture: string; address: ListingAddress; capacity: ListingCapacity; roomDetails: ListingRoomDetails; bathrooms: number; bedrooms: number; available: number; channel: Channel; channels: Channel[]; fees: ListingFee[]; amenities: string[]; 'check-in': string | null; 'check-out': string | null; details: ListingDetails; houseRules: ListingHouseRules; } interface ListingImage { url: string; thumbnailUrl: string; caption: string; order: number; } /** * A single day on the listing's pricing + availability calendar. * * The Connect calendar endpoint returns an array of these per listing. * `date` is `YYYY-MM-DD`. `availability` reflects whether the day is * bookable; `price` holds the host-set price for the day. */ interface CalendarDay { date: string; availability: { available: boolean; minStay?: number; maxStay?: number; closedForCheckIn?: boolean; closedForCheckOut?: boolean; }; price: Financial; } /** * Input for `PUT /listings/{listing}/calendar`. Batch of day-level * updates for pricing and/or availability. */ interface UpdateCalendarDay { date: string; price?: { amount: number; currency: string; }; availability?: { available?: boolean; minStay?: number; maxStay?: number; closedForCheckIn?: boolean; closedForCheckOut?: boolean; }; } /** * Reservation lifecycle status. The API returns freeform strings in * practice — kept as an open union. See * [[genesis/api_docs/hospitable/connect_api/reference/reference_enums_and_statuses]] * for the full enumerated set. */ type ReservationStatus = 'accept' | 'request' | 'at_checkpoint' | 'canceled_by_guest' | 'canceled_by_host' | 'not_possible' | 'checkpoint_voided' | 'timeout' | 'awaiting_payment' | (string & {}); interface ReservationStatusEntry { category: string; status: string; createdAt: string; } interface ReservationGuestCounts { total: number; adultCount: number; childCount: number; infantCount: number; petCount: number; } interface ReservationGuest { email: string; phoneNumbers: string[]; firstName: string; lastName: string; locale: string; } /** * Financial breakdown from the guest's perspective on a reservation. * Arrays (`taxes`, `fees`, `discounts`) may be empty. */ interface ReservationFinancialsGuest { accommodation: Financial; cleaningFee: Financial; serviceFee: Financial; taxes: Financial[]; fees: Financial[]; totalFees: Financial; discounts: Financial[]; subtotal: Financial; totalPrice: Financial; } /** * Financial breakdown from the host's perspective. Includes `payout` * instead of `totalPrice` — the net amount the host receives after * channel service fees. */ interface ReservationFinancialsHost { accommodation: Financial; cleaningFee: Financial; serviceFee: Financial; taxes: Financial[]; fees: Financial[]; totalFees: Financial; discounts: Financial[]; subtotal: Financial; payout: Financial; } interface ReservationFinancials { guest: ReservationFinancialsGuest; host: ReservationFinancialsHost; } /** * A booking on a Connect listing. `status` snapshots the current state; * `statusHistory` chronologically lists every transition. * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface Reservation { id: string; platform: ConnectPlatform; platformId: string; bookingDate: string; arrivalDate: string; departureDate: string; status: ReservationStatus; checkInLocal?: string; checkOutLocal?: string; timezone?: string; statusHistory: ReservationStatusEntry[]; guests: ReservationGuestCounts; guest: ReservationGuest; financials: ReservationFinancials; } type ReviewerRole = 'guest' | 'host'; /** * Detailed category-level ratings on a review — e.g. cleanliness, * communication, respect_house_rules. `category` is open-ended since * the platform adds new categories over time. */ interface ReviewDetailedRating { rating: number; comment: string | null; category: string; } /** * A review of a reservation or listing. `rating` is 1–5 (inclusive) or * `null` while the review is in progress. Public text is only visible * once both parties have completed their reviews or the review window * has expired (`expiresAt`). * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface Review { id: string; platform: ConnectPlatform; platformId: string; reservationPlatformId: string | null; listingPlatformId: string | null; guestPlatformId: string | null; guestName: string | null; reviewerRole: ReviewerRole; rating: number | null; detailedRatings: ReviewDetailedRating[]; visible: boolean; publicText: string | null; privateText: string | null; responseText: string | null; expiresAt: string | null; firstCompletedAt: string | null; submittedAt: string | null; respondedAt: string | null; channel: Channel; } /** * A transaction line item — a single guest-side or host-side charge on * the payment ledger. `type` is an open string (values seen: * `'Reservation'`, `'Adjustment'`, `'Resolution'`). `date` is when the * transaction posted; `startDate` is the service date (often the * reservation arrival). * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface Transaction { id: string; type: string; details: string | null; reference: string | null; currency: string; amount: Financial; date: string; startDate: string; } /** * A payout represents a single bank transfer from the OTA to the host. * `transactions` is the ledger of items rolled into this payout. * `date` is when the transfer was initiated; `null` while pending. * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface Payout { id: string; platform: string; platformId: string; bankAccount: string | null; reference: string | null; amount: Financial; date: string | null; channel: Channel; transactions: Transaction[]; } /** * A resolution is an OTA-mediated dispute between guest and host — * typically a security-deposit claim, damage claim, or refund request. * * - `initiator*` and `responder*` identify the two parties on the OTA. * - `status` / `statusText` describe progress (open / closed, etc.). * - `amountRequested` / `amountPaid` / `amountCharged` are the three * money perspectives tracked through resolution lifecycle. * * **Beta endpoint**: the Connect resolutions surface is in development; * field shapes may shift. `isCxInitiated` marks whether the platform's * support team opened the case. * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface Resolution { id: string; platform: string; platformId: string; initiatorPlatformId: string; initiatorName: string; responderPlatformId: string; responderName: string; reservationPlatformId: string; reasonName: string; status: string; statusText: string; currency: string; amountRequested: Financial; amountPaid: Financial; amountCharged: Financial; date: string; isCxInitiated: boolean; detailLink: string; } /** * A placeholder in a {@link MessageTemplate}. Partners fill these when * sending a message — `key` names the slot (`'discount'`, `'url'`, * etc.); `editable` indicates whether the partner can override the * default; `regex` (if present) constrains the value shape. */ interface MessagePlaceholder { key: string; editable: boolean; description: string | null; regex: string | null; } /** * A custom message template configured in the Hospitable Partner Portal. * `message` is the template body with `{{placeholder}}` tokens matching * `placeholders[].key`. * * @see https://developer.hospitable.com/docs/connect-api-docs */ interface MessageTemplate { id: string; message: string; placeholders: MessagePlaceholder[]; } /** * Request body for `POST /reservations/{reservation}/messages`. Pass * `templateId` to render against a stored template, then supply values * for each editable `placeholder` keyed by `key`. * * Example: * ```ts * { * templateId: '8bb28...', * placeholders: { url: 'https://example.com', discount: '10%' } * } * ``` */ interface SendMessageInput { templateId: string; placeholders?: Record; } interface CustomerListParams { page?: number; perPage?: number; /** Comma-separated subset of Customer fields to return (e.g. `'id,email'`). */ _select?: string; } /** * Resource for the Connect Customers API. A Customer is one end-user of * the partner application; they own Channels (OTA connections). * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class CustomersResource { private readonly http; constructor(http: HttpClient); private fetchList; /** * List customers, paginated. * * @see GET https://connect.hospitable.com/api/v1/customers */ list(params?: CustomerListParams): Promise>; /** * Stream every customer. Memory-efficient — one page at a time. */ iter(params?: Omit): AsyncGenerator; /** * Create a customer. The `id` field is partner-assigned — use any * stable string (your app's user ID is the typical choice). * * @see POST https://connect.hospitable.com/api/v1/customers */ create(input: CreateCustomerInput): Promise; /** * Fetch a single customer by id. * * @see GET https://connect.hospitable.com/api/v1/customers/{customer} * @throws {NotFoundError} on 404 */ get(customerId: string): Promise; /** * Delete a customer and all associated channels / data. * * @see DELETE https://connect.hospitable.com/api/v1/customers/{customer} */ delete(customerId: string): Promise; } /** * Resource for the Connect Channels API. A Channel is an OTA connection * (currently Airbnb only) owned by a Customer. Channels aggregate * Listings and Reviews from the connected platform. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class ChannelsResource { private readonly http; constructor(http: HttpClient); /** * List all channels a customer has connected. * * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/channels */ list(customerId: string): Promise; /** * Fetch a single channel by id, scoped to a customer. * * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/channels/{channel} */ get(customerId: string, channelId: string): Promise; /** * Disconnect a channel from a customer. * * Note: this does **not** revoke the customer's authorization on the * OTA itself (e.g. the Airbnb account stays linked in the guest's * Airbnb app). It only severs Hospitable's sync with that channel. * * @see DELETE https://connect.hospitable.com/api/v1/customers/{customer}/channels/{channel} */ delete(customerId: string, channelId: string): Promise; /** * List all listings published on a given channel. Excludes * unpublished or draft listings on the OTA side. * * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/listings */ listListings(channelId: string): Promise; /** * Fetch a single listing scoped to a channel. * * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/listings/{listing} */ getListing(channelId: string, listingId: string): Promise; } interface ListingListParams { page?: number; perPage?: number; _select?: string; } interface CalendarRangeParams { /** ISO `YYYY-MM-DD`, inclusive. */ startDate: string; /** ISO `YYYY-MM-DD`, inclusive. Up to 365 days per request. */ endDate: string; } /** * Resource for the Connect Listings, Pricing & Availability API. * * Customer-scoped listings: what the Customer owns across every channel. * Use {@link ChannelsResource.listListings} when you need channel-scoped * listings instead. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class ListingsResource { private readonly http; constructor(http: HttpClient); private fetchList; /** * List all listings a customer owns, across every channel. * Unpublished listings are excluded. * * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/listings */ list(customerId: string, params?: ListingListParams): Promise>; /** * Stream every listing for a customer. Memory-efficient — paginates * one page at a time. */ iter(customerId: string, params?: Omit): AsyncGenerator; /** * Fetch a single listing scoped to a customer. * * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/listings/{listing} */ get(customerId: string, listingId: string): Promise; /** * Fetch photo gallery for a listing, ordered by `order`. * * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/listings/{listing}/images */ getImages(customerId: string, listingId: string): Promise; /** * Fetch day-level pricing + availability for a listing. * * API limits: up to 540 days in the future, max 365 days per * request (split into batches for wider windows). * * @see GET https://connect.hospitable.com/api/v1/listings/{listing}/calendar * @throws {ConfigurationError} when `startDate` or `endDate` is missing */ getCalendar(listingId: string, params: CalendarRangeParams): Promise; /** * Batch-update day-level pricing and/or availability. * * @see PUT https://connect.hospitable.com/api/v1/listings/{listing}/calendar * @throws {ConfigurationError} when `days` is empty */ updateCalendar(listingId: string, days: UpdateCalendarDay[]): Promise; } interface ReservationListParams { page?: number; perPage?: number; _select?: string; /** * Free-form filter bag — Connect uses `field[operator]=value` syntax * (see Filters reference). Keys map 1:1 to query params, so to filter * by `arrival_date[after]=2026-01-01` pass * `{ 'arrival_date[after]': '2026-01-01' }`. Use `ConnectFilter` for * a typed builder. * * Value type intentionally excludes `string[]`: Connect's filter * serialization is comma-joined strings (see `ConnectFilter.where`), * so arrays should be pre-joined before hitting this bag. Allowing * `string[]` here also accidentally satisfied the numeric `page` / * `perPage` slots at compile time, producing silent `NaN` paginator * loops — see issue #49. */ [key: string]: string | number | boolean | undefined; } /** * Resource for the Connect Reservations API. * * Reservations can be queried per-listing (`listings.../reservations`) * or per-customer (`customers.../reservations`). The per-customer * variant is useful for dashboards aggregating a host's entire book; * per-listing is useful for per-property views. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class ReservationsResource { private readonly http; constructor(http: HttpClient); private fetchByListing; private fetchByCustomer; /** * List reservations on a single listing. * * @see GET https://connect.hospitable.com/api/v1/listings/{listing}/reservations */ listByListing(listingId: string, params?: ReservationListParams): Promise>; /** Stream every reservation on a listing, auto-paginating. */ iterByListing(listingId: string, params?: Omit): AsyncGenerator; /** * Fetch a single reservation scoped to a listing. * * @see GET https://connect.hospitable.com/api/v1/listings/{listing}/reservations/{reservation} */ getByListing(listingId: string, reservationId: string): Promise; /** * List every reservation a customer has across all their listings. * * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/reservations */ listByCustomer(customerId: string, params?: ReservationListParams): Promise>; /** Stream every reservation for a customer, auto-paginating. */ iterByCustomer(customerId: string, params?: Omit): AsyncGenerator; /** * Fetch a single reservation scoped to a customer. * * @see GET https://connect.hospitable.com/api/v1/customers/{customer}/reservations/{reservation} */ getByCustomer(customerId: string, reservationId: string): Promise; } interface MessageTemplateListParams { page?: number; perPage?: number; _select?: string; } /** * Resource for the Connect Messaging API. Messages are sent via * **pre-configured templates** — freeform text is not supported. * Configure templates in the Partner Portal, then reference them by * `templateId` when sending. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class MessagingResource { private readonly http; constructor(http: HttpClient); private fetchTemplates; /** * List all message templates available to this vendor. * * @see GET https://connect.hospitable.com/api/v1/message-templates */ listTemplates(params?: MessageTemplateListParams): Promise>; /** Stream every template, auto-paginating. */ iterTemplates(params?: Omit): AsyncGenerator; /** * Fetch a single template by id. * * @see GET https://connect.hospitable.com/api/v1/message-templates/{template} */ getTemplate(templateId: string): Promise; /** * Send a templated message to the guest on a reservation. Placeholder * values are substituted into the template body; the rendered message * appears in the guest's OTA inbox. * * @see POST https://connect.hospitable.com/api/v1/reservations/{reservation}/messages * @throws {ConfigurationError} when `templateId` is missing */ send(reservationId: string, input: SendMessageInput): Promise; } interface ReviewListParams { page?: number; perPage?: number; _select?: string; /** Free-form `field[operator]=value` filter bag. See issue #49 for the `string[]` exclusion rationale. */ [key: string]: string | number | boolean | undefined; } /** * Resource for the Connect Reviews API. Reviews are scoped to a * channel — pass the channel id of the OTA account the review came * through. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class ReviewsResource { private readonly http; constructor(http: HttpClient); private fetchList; /** * List reviews on a channel, paginated. * * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/reviews */ list(channelId: string, params?: ReviewListParams): Promise>; /** Stream every review on a channel. */ iter(channelId: string, params?: Omit): AsyncGenerator; } interface TransactionListParams { page?: number; perPage?: number; _select?: string; /** Free-form `field[operator]=value` filter bag. See issue #49 for the `string[]` exclusion rationale. */ [key: string]: string | number | boolean | undefined; } /** * Resource for the Connect Transactions API (beta). * * **Beta**: this surface is not GA. For customers whose Airbnb channel * was authorized before 2024-01-12, re-run the auth-code flow to pick * up transactions + payouts permissions. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class TransactionsResource { private readonly http; constructor(http: HttpClient); private fetchList; /** * List transactions on a channel, paginated. * * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/transactions */ list(channelId: string, params?: TransactionListParams): Promise>; /** Stream every transaction on a channel. */ iter(channelId: string, params?: Omit): AsyncGenerator; /** * Fetch a single transaction scoped to a channel. * * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/transactions/{transaction} */ get(channelId: string, transactionId: string): Promise; } interface PayoutListParams { page?: number; perPage?: number; _select?: string; /** Free-form `field[operator]=value` filter bag. See issue #49 for the `string[]` exclusion rationale. */ [key: string]: string | number | boolean | undefined; } /** * Resource for the Connect Payouts API (beta). * * Channel-scoped. For customers whose Airbnb channel was authorized * before 2024-01-12, re-run the auth-code flow to pick up payout * permissions. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class PayoutsResource { private readonly http; constructor(http: HttpClient); private fetchList; /** * List payouts on a channel, paginated. * * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/payouts */ list(channelId: string, params?: PayoutListParams): Promise>; /** Stream every payout on a channel. */ iter(channelId: string, params?: Omit): AsyncGenerator; /** * Fetch a single payout scoped to a channel. * * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/payouts/{payout} */ get(channelId: string, payoutId: string): Promise; } interface ResolutionListParams { page?: number; perPage?: number; _select?: string; /** Free-form `field[operator]=value` filter bag. See issue #49 for the `string[]` exclusion rationale. */ [key: string]: string | number | boolean | undefined; } /** * Resource for the Connect Resolutions API (beta). * * Resolutions are OTA-mediated disputes — security-deposit claims, * damage claims, refund requests. Channel-scoped. This surface is * **in active development**; response shapes may evolve. * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class ResolutionsResource { private readonly http; constructor(http: HttpClient); private fetchList; /** * List resolutions on a channel, paginated. * * @see GET https://connect.hospitable.com/api/v1/channels/{channel}/resolutions */ list(channelId: string, params?: ResolutionListParams): Promise>; /** Stream every resolution on a channel. */ iter(channelId: string, params?: Omit): AsyncGenerator; } interface HospitableConnectClientConfig { /** * Partner-portal bearer token. Also read from `HOSPITABLE_CONNECT_TOKEN` * env var. Generate in partners.hospitable.com → Connect → Settings → * Access tokens (shown only once — store securely). */ token?: string; /** API base URL. Defaults to `https://connect.hospitable.com/api/v1`. */ baseURL?: string; /** Retry configuration. Connect rate-limits at 60 req/min per vendor. */ retry?: RetryConfig; /** Enable debug logging. */ debug?: boolean; /** * Optional callback invoked when a 401 is returned by the API. Should * resolve to a freshly-minted bearer token, which the SDK will swap in * and use to transparently retry the failing request. * * Without this callback, 401s throw {@link AuthenticationError} and the * caller must reconstruct the client — fine for short-lived scripts but * a dead-end for long-running agent processes that rotate tokens * mid-session. Supply it to cover that case. * * @example * ```ts * new HospitableConnectClient({ * token: initialToken, * onTokenExpired: () => fetchFreshConnectToken(), * }) * ``` */ onTokenExpired?: () => string | Promise; } /** * Client for the Hospitable Connect API — partner-facing, multi-customer * integration surface. Distinct from {@link HospitableClient} (Public API, * host-facing). * * Auth is a static bearer token minted in the Hospitable Partner Portal; * there is no OAuth refresh loop. By default, 401s surface as * {@link AuthenticationError} and are terminal — regenerate the token in * the portal and reconstruct the client. Supply {@link HospitableConnectClientConfig.onTokenExpired} * to plug in a custom refresh path (e.g. for long-running agents that * rotate tokens via an external system). * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class HospitableConnectClient { readonly authCodes: AuthCodesResource; readonly customers: CustomersResource; readonly channels: ChannelsResource; readonly listings: ListingsResource; readonly reservations: ReservationsResource; readonly messaging: MessagingResource; readonly reviews: ReviewsResource; readonly transactions: TransactionsResource; readonly payouts: PayoutsResource; readonly resolutions: ResolutionsResource; constructor(config?: HospitableConnectClientConfig); } /** * Every Connect webhook payload shares this envelope. `id` is a ULID, * `created` is ISO-8601, `action` identifies the event, `version` is * the schema version the platform used to serialize the event, and * `data` carries the domain object + embedded related resources. * * Return 200 to acknowledge receipt — the platform retries on any * non-2xx response. * * ⚠️ **Security.** The type guards ({@link isConnectWebhookAction}, * {@link isConnectWebhookFamily}) only narrow the shape — they do NOT * authenticate the sender. Anyone who discovers your webhook URL can POST * a forged body that passes both guards. Before trusting any incoming * payload, verify its HMAC signature with {@link verifyWebhookSignature} * using the shared secret from your Hospitable integration. */ interface ConnectWebhookEnvelope { id: string; created: string; action: Action; version: string; data: Data; } type ChannelWebhookAction = 'channel.activated'; interface ChannelWebhookData extends Channel { /** * Customer who owns this channel connection. Always embedded on * channel events so partners can route the payload to the right * tenant without a follow-up GET. */ customer: Customer; } type ChannelWebhookPayload = ConnectWebhookEnvelope; type ListingWebhookAction = 'listing.created' | 'listing.changed' | 'listing.deactivated' | 'listing.reactivated'; interface ListingWebhookData extends Listing { customer: Customer; } type ListingWebhookPayload = ConnectWebhookEnvelope; type ReservationWebhookAction = 'reservation.created' | 'reservation.changed'; interface ReservationWebhookData extends Reservation { /** Listing this reservation is against. */ listing: Listing; /** Channel the booking came through. */ channel: Channel; /** Customer who owns the channel. */ customer: Customer; } type ReservationWebhookPayload = ConnectWebhookEnvelope; type ReviewWebhookAction = 'review.created' | 'review.submitted' | 'review.published' | 'review.changed' | 'review.expired' | 'review.response_submitted'; type ReviewWebhookPayload = ConnectWebhookEnvelope; type PayoutWebhookAction = 'payout.created' | 'payout.changed'; type PayoutWebhookPayload = ConnectWebhookEnvelope; type TransactionWebhookAction = 'transaction.created' | 'transaction.changed'; interface TransactionWebhookData extends Transaction { payout?: Payout; channel?: Channel; listing?: Listing; reservation?: Reservation; } type TransactionWebhookPayload = ConnectWebhookEnvelope; type ConnectWebhookPayload = ChannelWebhookPayload | ListingWebhookPayload | ReservationWebhookPayload | ReviewWebhookPayload | PayoutWebhookPayload | TransactionWebhookPayload; type ConnectWebhookAction = ConnectWebhookPayload['action']; /** * Type guard factory — narrows a generic payload to the requested event * family. Use at webhook-endpoint entry points to route by event type * without manual `as` casts. * * @example * ```ts * if (isConnectWebhookAction(payload, 'reservation.created')) { * // payload.data is typed as ReservationWebhookData here * } * ``` */ declare function isConnectWebhookAction(payload: ConnectWebhookPayload, action: A): payload is Extract; /** * Broader family guard — narrows to all events sharing a prefix. * * @example * ```ts * if (isConnectWebhookFamily(payload, 'reservation')) { * // payload is ReservationWebhookPayload * } * ``` */ declare function isConnectWebhookFamily(payload: ConnectWebhookPayload, family: F): payload is Extract; /** * Digest algorithm used to compute the HMAC. `sha256` is the default and * what Hospitable uses; `sha1` is supported only for legacy compatibility. */ type WebhookSignatureAlgorithm = 'sha256' | 'sha1'; /** * Encoding of the signature as sent in the HTTP header. Hex is the * Hospitable default; base64 is supported for callers who bridge from * other webhook providers. */ type WebhookSignatureEncoding = 'hex' | 'base64'; interface VerifyWebhookSignatureOptions { /** * The raw request body, exactly as received. Do NOT pass the parsed * JSON — the byte-for-byte original is required for the HMAC to match. * Most frameworks expose this as `req.rawBody`, `request.body` (when * configured for raw), or the result of a `body-parser`-style raw reader. * * Node's `Buffer` is accepted transparently since it extends * `Uint8Array`; the SDK itself doesn't depend on `@types/node`. */ rawBody: string | Uint8Array; /** * The signature header value received from Hospitable. If the header * contains an `algo=` prefix (e.g. `sha256=abc123…`), it is stripped * automatically before comparison. */ signatureHeader: string; /** * The shared secret configured when the webhook was registered in the * Hospitable Partner Portal. Store this in an env var or secret manager * — never hardcode it. */ secret: string; /** Defaults to `'sha256'`. */ algorithm?: WebhookSignatureAlgorithm; /** Defaults to `'hex'`. */ encoding?: WebhookSignatureEncoding; /** * Optional timestamp header value. When supplied, the signed payload is * `` `${timestamp}.${rawBody}` `` — a common anti-replay scheme. Pair * this with {@link toleranceSeconds} to reject stale deliveries. */ timestamp?: string; /** * Maximum age in seconds allowed for a timestamped payload. Signatures * older than this (relative to `Date.now()`) are rejected. Only consulted * when {@link timestamp} is provided. Defaults to 300 (5 minutes). */ toleranceSeconds?: number; } /** * Verify the HMAC signature on an incoming Hospitable Connect webhook. * * Hospitable signs every webhook delivery with a shared secret; verifying * the signature is the caller's responsibility and is mandatory for any * production integration — without it, an attacker who knows your webhook * URL can forge events and trigger arbitrary downstream behavior in your * tenant. * * Resolves to `true` when the signature is valid and (if supplied) the * timestamp is within tolerance. Resolves to `false` for any mismatch, * malformed input, or stale payload. Never throws for signature mismatch * — throwing on verification failure invites a DoS where crafted bodies * crash the receiver. * * Uses a constant-time comparison to prevent side-channel leaks of the * expected signature byte-by-byte. * * Implemented via Web Crypto (`globalThis.crypto.subtle`) so the SDK * stays free of `@types/node`. Works on Node 20+ (native) and in any * runtime that ships Web Crypto. * * @example * ```ts * // Express route handler — be sure to capture the raw body. * app.post('/webhooks/hospitable', express.raw({ type: 'application/json' }), async (req, res) => { * const ok = await verifyWebhookSignature({ * rawBody: req.body, * signatureHeader: req.header('X-Hospitable-Signature') ?? '', * secret: process.env.HOSPITABLE_WEBHOOK_SECRET!, * }) * if (!ok) return res.status(401).end() * const payload = JSON.parse(new TextDecoder().decode(req.body)) * // ... handle payload ... * res.status(200).end() * }) * ``` * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare function verifyWebhookSignature(opts: VerifyWebhookSignatureOptions): Promise; /** * Operators supported by Connect's `field[operator]=value` filter * syntax. Multi-value operators accept comma-separated lists; the * single-value ones take one value. */ type ConnectFilterOperator = /** Include values. Multi-value. */ 'is' /** Exclude values. Multi-value. */ | 'not' /** `<` — single value. */ | 'lt' /** `<=` — single value. */ | 'lte' /** `>` — single value. */ | 'gt' /** `>=` — single value. */ | 'gte' /** Inclusive range. Two values. */ | 'between' /** `<` date. Single value. */ | 'before' /** `>` date. Single value. */ | 'after'; /** * Fluent, immutable builder for Connect list params — composes * `field[operator]=value` filters, `sort[asc|desc]=field`, `_select=`, * and pagination (page / perPage). * * Every chainable method returns a new `ConnectFilter`; branch safely * without mutating shared state. Terminate with {@link toParams}. * * @example * ```ts * const params = new ConnectFilter() * .where('city', 'is', ['New York', 'Seattle']) * .where('status', 'not', ['deny', 'cancelled']) * .where('arrival_date', 'before', '2024-02-01') * .sortDesc('arrival_date') * .select('id', 'arrival_date', 'financials.host') * .perPage(50) * .toParams() * * await connect.reservations.listByCustomer(customerId, params) * ``` * * @see https://developer.hospitable.com/docs/connect-api-docs */ declare class ConnectFilter { private readonly state; constructor(state?: Record); /** * Add a filter. Operator determines how `value` is stringified: * `is` / `not` join arrays with commas; `between` requires exactly * two values; every other operator takes a single value. * * @throws {ConfigurationError} when the value shape doesn't match the operator */ where(field: string, operator: ConnectFilterOperator, value: string | number | boolean | Array): ConnectFilter; /** Sort ascending by `field`. Replaces any prior sort. */ sortAsc(field: string): ConnectFilter; /** Sort descending by `field`. Replaces any prior sort. */ sortDesc(field: string): ConnectFilter; /** Shortcut for `sort=latest` — sorts by record creation time, newest first. */ sortLatest(): ConnectFilter; /** Shortcut for `sort=oldest` — sorts by record creation time, oldest first. */ sortOldest(): ConnectFilter; /** Request only a subset of response fields via `_select=a,b,c`. */ select(...fields: string[]): ConnectFilter; page(n: number): ConnectFilter; perPage(n: number): ConnectFilter; /** Materialize the filter into a plain params record. */ toParams(): Record; private stripSort; } interface ConnectPageFetcher { (params: P): Promise>; } /** * Page-driver for Connect list endpoints. Terminates when the API * returns a page with an empty `data` array or null `links.next` — * Connect's `meta.last_page` is only sometimes present, so we rely on * the resource-level link header + empty-page signal which every list * endpoint honors. */ declare function paginateConnect(fetcher: ConnectPageFetcher, params: Omit): AsyncGenerator; interface PageFetcher { (params: P): Promise>; } declare function paginate(fetcher: PageFetcher, params: Omit): AsyncGenerator; /** * Drain every item from a paginated source into an array. * * Two forms are supported: * * 1. **Iterable form** — the idiomatic shape for SDK consumers: * ```ts * const all = await collectAll(client.reservations.iter({ startDate: '2026-01-01' })) * ``` * * 2. **Fetcher form** — used when driving pagination against a raw * `PageFetcher` without a resource class in scope: * ```ts * const all = await collectAll(params => http.get('/v2/things', params), { perPage: 50 }) * ``` * * @remarks Both forms eagerly buffer the entire result set in memory. For * large streams (>10k items), prefer iterating directly with `for await` * and processing items as they arrive. */ declare function collectAll(iterable: AsyncIterable): Promise; declare function collectAll(fetcher: PageFetcher, params: Omit): Promise; type index_AuthCode = AuthCode; type index_AuthCodesResource = AuthCodesResource; declare const index_AuthCodesResource: typeof AuthCodesResource; type index_CalendarDay = CalendarDay; type index_CalendarRangeParams = CalendarRangeParams; type index_Channel = Channel; type index_ChannelWebhookAction = ChannelWebhookAction; type index_ChannelWebhookData = ChannelWebhookData; type index_ChannelWebhookPayload = ChannelWebhookPayload; type index_ChannelsResource = ChannelsResource; declare const index_ChannelsResource: typeof ChannelsResource; type index_ConnectFilter = ConnectFilter; declare const index_ConnectFilter: typeof ConnectFilter; type index_ConnectFilterOperator = ConnectFilterOperator; type index_ConnectPageFetcher = ConnectPageFetcher; type index_ConnectPaginatedResponse = ConnectPaginatedResponse; type index_ConnectPaginationLinks = ConnectPaginationLinks; type index_ConnectPaginationMeta = ConnectPaginationMeta; type index_ConnectPlatform = ConnectPlatform; type index_ConnectWebhookAction = ConnectWebhookAction; type index_ConnectWebhookEnvelope = ConnectWebhookEnvelope; type index_ConnectWebhookPayload = ConnectWebhookPayload; type index_CreateAuthCodeInput = CreateAuthCodeInput; type index_CreateCustomerInput = CreateCustomerInput; type index_Customer = Customer; type index_CustomerListParams = CustomerListParams; type index_CustomersResource = CustomersResource; declare const index_CustomersResource: typeof CustomersResource; type index_Financial = Financial; type index_HospitableConnectClient = HospitableConnectClient; declare const index_HospitableConnectClient: typeof HospitableConnectClient; type index_HospitableConnectClientConfig = HospitableConnectClientConfig; type index_Listing = Listing; type index_ListingAddress = ListingAddress; type index_ListingCapacity = ListingCapacity; type index_ListingDetails = ListingDetails; type index_ListingFee = ListingFee; type index_ListingHouseRules = ListingHouseRules; type index_ListingImage = ListingImage; type index_ListingListParams = ListingListParams; type index_ListingRoomBed = ListingRoomBed; type index_ListingRoomDetails = ListingRoomDetails; type index_ListingWebhookAction = ListingWebhookAction; type index_ListingWebhookData = ListingWebhookData; type index_ListingWebhookPayload = ListingWebhookPayload; type index_ListingsResource = ListingsResource; declare const index_ListingsResource: typeof ListingsResource; type index_MessagePlaceholder = MessagePlaceholder; type index_MessageTemplate = MessageTemplate; type index_MessageTemplateListParams = MessageTemplateListParams; type index_MessagingResource = MessagingResource; declare const index_MessagingResource: typeof MessagingResource; type index_Payout = Payout; type index_PayoutListParams = PayoutListParams; type index_PayoutWebhookAction = PayoutWebhookAction; type index_PayoutWebhookPayload = PayoutWebhookPayload; type index_PayoutsResource = PayoutsResource; declare const index_PayoutsResource: typeof PayoutsResource; type index_Reservation = Reservation; type index_ReservationFinancials = ReservationFinancials; type index_ReservationFinancialsGuest = ReservationFinancialsGuest; type index_ReservationFinancialsHost = ReservationFinancialsHost; type index_ReservationGuest = ReservationGuest; type index_ReservationGuestCounts = ReservationGuestCounts; type index_ReservationListParams = ReservationListParams; type index_ReservationStatus = ReservationStatus; type index_ReservationStatusEntry = ReservationStatusEntry; type index_ReservationWebhookAction = ReservationWebhookAction; type index_ReservationWebhookData = ReservationWebhookData; type index_ReservationWebhookPayload = ReservationWebhookPayload; type index_ReservationsResource = ReservationsResource; declare const index_ReservationsResource: typeof ReservationsResource; type index_Resolution = Resolution; type index_ResolutionListParams = ResolutionListParams; type index_ResolutionsResource = ResolutionsResource; declare const index_ResolutionsResource: typeof ResolutionsResource; type index_Review = Review; type index_ReviewDetailedRating = ReviewDetailedRating; type index_ReviewListParams = ReviewListParams; type index_ReviewWebhookAction = ReviewWebhookAction; type index_ReviewWebhookPayload = ReviewWebhookPayload; type index_ReviewerRole = ReviewerRole; type index_ReviewsResource = ReviewsResource; declare const index_ReviewsResource: typeof ReviewsResource; type index_SendMessageInput = SendMessageInput; type index_Transaction = Transaction; type index_TransactionListParams = TransactionListParams; type index_TransactionWebhookAction = TransactionWebhookAction; type index_TransactionWebhookData = TransactionWebhookData; type index_TransactionWebhookPayload = TransactionWebhookPayload; type index_TransactionsResource = TransactionsResource; declare const index_TransactionsResource: typeof TransactionsResource; type index_UpdateCalendarDay = UpdateCalendarDay; type index_VerifyWebhookSignatureOptions = VerifyWebhookSignatureOptions; type index_WebhookSignatureAlgorithm = WebhookSignatureAlgorithm; type index_WebhookSignatureEncoding = WebhookSignatureEncoding; declare const index_collectAll: typeof collectAll; declare const index_isConnectWebhookAction: typeof isConnectWebhookAction; declare const index_isConnectWebhookFamily: typeof isConnectWebhookFamily; declare const index_paginateConnect: typeof paginateConnect; declare const index_verifyWebhookSignature: typeof verifyWebhookSignature; declare namespace index { export { type index_AuthCode as AuthCode, index_AuthCodesResource as AuthCodesResource, type index_CalendarDay as CalendarDay, type index_CalendarRangeParams as CalendarRangeParams, type index_Channel as Channel, type index_ChannelWebhookAction as ChannelWebhookAction, type index_ChannelWebhookData as ChannelWebhookData, type index_ChannelWebhookPayload as ChannelWebhookPayload, index_ChannelsResource as ChannelsResource, index_ConnectFilter as ConnectFilter, type index_ConnectFilterOperator as ConnectFilterOperator, type index_ConnectPageFetcher as ConnectPageFetcher, type index_ConnectPaginatedResponse as ConnectPaginatedResponse, type index_ConnectPaginationLinks as ConnectPaginationLinks, type index_ConnectPaginationMeta as ConnectPaginationMeta, type index_ConnectPlatform as ConnectPlatform, type index_ConnectWebhookAction as ConnectWebhookAction, type index_ConnectWebhookEnvelope as ConnectWebhookEnvelope, type index_ConnectWebhookPayload as ConnectWebhookPayload, type index_CreateAuthCodeInput as CreateAuthCodeInput, type index_CreateCustomerInput as CreateCustomerInput, type index_Customer as Customer, type index_CustomerListParams as CustomerListParams, index_CustomersResource as CustomersResource, type index_Financial as Financial, index_HospitableConnectClient as HospitableConnectClient, type index_HospitableConnectClientConfig as HospitableConnectClientConfig, type index_Listing as Listing, type index_ListingAddress as ListingAddress, type index_ListingCapacity as ListingCapacity, type index_ListingDetails as ListingDetails, type index_ListingFee as ListingFee, type index_ListingHouseRules as ListingHouseRules, type index_ListingImage as ListingImage, type index_ListingListParams as ListingListParams, type index_ListingRoomBed as ListingRoomBed, type index_ListingRoomDetails as ListingRoomDetails, type index_ListingWebhookAction as ListingWebhookAction, type index_ListingWebhookData as ListingWebhookData, type index_ListingWebhookPayload as ListingWebhookPayload, index_ListingsResource as ListingsResource, type index_MessagePlaceholder as MessagePlaceholder, type index_MessageTemplate as MessageTemplate, type index_MessageTemplateListParams as MessageTemplateListParams, index_MessagingResource as MessagingResource, type index_Payout as Payout, type index_PayoutListParams as PayoutListParams, type index_PayoutWebhookAction as PayoutWebhookAction, type index_PayoutWebhookPayload as PayoutWebhookPayload, index_PayoutsResource as PayoutsResource, type index_Reservation as Reservation, type index_ReservationFinancials as ReservationFinancials, type index_ReservationFinancialsGuest as ReservationFinancialsGuest, type index_ReservationFinancialsHost as ReservationFinancialsHost, type index_ReservationGuest as ReservationGuest, type index_ReservationGuestCounts as ReservationGuestCounts, type index_ReservationListParams as ReservationListParams, type index_ReservationStatus as ReservationStatus, type index_ReservationStatusEntry as ReservationStatusEntry, type index_ReservationWebhookAction as ReservationWebhookAction, type index_ReservationWebhookData as ReservationWebhookData, type index_ReservationWebhookPayload as ReservationWebhookPayload, index_ReservationsResource as ReservationsResource, type index_Resolution as Resolution, type index_ResolutionListParams as ResolutionListParams, index_ResolutionsResource as ResolutionsResource, type index_Review as Review, type index_ReviewDetailedRating as ReviewDetailedRating, type index_ReviewListParams as ReviewListParams, type index_ReviewWebhookAction as ReviewWebhookAction, type index_ReviewWebhookPayload as ReviewWebhookPayload, type index_ReviewerRole as ReviewerRole, index_ReviewsResource as ReviewsResource, type index_SendMessageInput as SendMessageInput, type index_Transaction as Transaction, type index_TransactionListParams as TransactionListParams, type index_TransactionWebhookAction as TransactionWebhookAction, type index_TransactionWebhookData as TransactionWebhookData, type index_TransactionWebhookPayload as TransactionWebhookPayload, index_TransactionsResource as TransactionsResource, type index_UpdateCalendarDay as UpdateCalendarDay, type index_VerifyWebhookSignatureOptions as VerifyWebhookSignatureOptions, type index_WebhookSignatureAlgorithm as WebhookSignatureAlgorithm, type index_WebhookSignatureEncoding as WebhookSignatureEncoding, index_collectAll as collectAll, index_isConnectWebhookAction as isConnectWebhookAction, index_isConnectWebhookFamily as isConnectWebhookFamily, index_paginateConnect as paginateConnect, index_verifyWebhookSignature as verifyWebhookSignature }; } declare class HospitableError extends Error { readonly statusCode: number; readonly requestId: string | undefined; constructor(message: string, statusCode: number, requestId?: string); } /** * Thrown on 401 and 403 responses. AGENTS.md §Error Handling spec mandates * a single `HospitableAuthError` covering both. `ForbiddenError` extends * this class so `err instanceof HospitableAuthError` catches 403 too. * * The trailing `statusCode` parameter exists so {@link ForbiddenError} can * reuse the same constructor without duplicating the readonly-field dance. * Callers should prefer {@link ForbiddenError} over `new AuthenticationError(…, 403)`. */ declare class AuthenticationError extends HospitableError { constructor(message?: string, requestId?: string, statusCode?: 401 | 403); } declare class RateLimitError extends HospitableError { readonly retryAfter: number; constructor(retryAfter: number, requestId?: string); } declare class NotFoundError extends HospitableError { readonly resource: string | undefined; constructor(message?: string, requestId?: string, resource?: string); } declare class ValidationError extends HospitableError { readonly fields: Record; constructor(message: string, fields?: Record, requestId?: string); } declare class ForbiddenError extends AuthenticationError { constructor(message?: string, requestId?: string); } declare class ServerError extends HospitableError { readonly attempts: number; constructor(message: string, statusCode: number, attempts: number, requestId?: string); } /** * Thrown for client-side configuration / usage errors detected before any * HTTP request is made — e.g. calling `InquiryFilter.toParams()` without * supplying the required `properties` filter. * * Carries `statusCode = 0` to signal "no HTTP request happened". It still * extends {@link HospitableError} so agents catching the base class handle * it alongside runtime HTTP errors without special-casing. */ declare class ConfigurationError extends HospitableError { constructor(message: string); } declare function createErrorFromResponse(statusCode: number, body: Record, requestId?: string, attempts?: number, retryAfterOverride?: number): HospitableError; interface TokenManagerConfig { token?: string; refreshToken?: string; clientId?: string; clientSecret?: string; baseURL: string; /** * Seconds until the caller-supplied `token` expires. Only consulted when * both `token` and `refreshToken` are provided (OAuth rehydrate path). * Defaults to 3600 — a conservative "fresh" assumption. Pass the server's * `expires_in` response directly if you have it; pass a small value only * when you know the token is near-expiry and want to force a proactive * refresh on the next request. */ expiresIn?: number; } declare class TokenManager { private readonly config; private accessToken; private refreshToken; private expiresAt; private refreshPromise; constructor(config: TokenManagerConfig); getAuthHeader(): Promise; private needsRefresh; private ensureRefreshed; private doRefresh; handleUnauthorized(): Promise; } /** * Recursively masks PII and sensitive fields in an object for safe logging. * Does NOT mutate the original — returns a new object with masked values. * Only affects log output; never called on actual API payloads. * * Patterns matched: * - {@link PII_FIELD_PATTERN} — guest-identifying fields (email, names, phone…) * - {@link SENSITIVE_PATTERN} — auth/credentials (token, secret, apiKey…) * - {@link SENSITIVE_BIZ_PATTERN} — business/financial identity * (taxId, vat, bankAccount, streetLine*, postalCode) * * Override exceptions (pass through unchanged): * - {@link SAFE_OVERRIDES} — explicitly-safe fields that match a sensitive * pattern but are not credentials in practice (e.g. `wifiPassword`) * * The patterns check both camelCase and snake_case forms so this function is * safe to call on raw server responses (pre-`deepSnakeToCamel`) as well as * post-conversion objects. */ declare function sanitize(value: unknown, depth?: number): unknown; /** * Fluent, immutable builder for `client.reservations.list` params. * * Every chainable method returns a new `ReservationFilter` — safe to branch * filters mid-construction without mutating shared state. Terminate the * chain with {@link toParams}. * * @example * ```ts * const params = new ReservationFilter() * .properties([propertyId]) // required by the API * .checkinAfter('2026-01-01') * .checkinBefore('2026-12-31') * .dateQuery('checkout') // optional — defaults to checkin * .status(['accepted', 'request']) * .include('guest', 'properties', 'review') * .perPage(50) * .toParams() * * await client.reservations.list(params) * ``` */ declare class ReservationFilter { private readonly params; constructor(params?: Partial); /** Reservations with date >= this (ISO `YYYY-MM-DD`), on field chosen by {@link dateQuery}. */ checkinAfter(date: string): ReservationFilter; /** Reservations with date <= this (ISO `YYYY-MM-DD`), on field chosen by {@link dateQuery}. */ checkinBefore(date: string): ReservationFilter; /** * Choose which date field `checkinAfter`/`checkinBefore` filter against. * Defaults to `'checkin'` on the API side. Set to `'checkout'` to find * guests currently in-house or departing in a window. */ dateQuery(q: ReservationDateQuery): ReservationFilter; /** * Only reservations whose last-message timestamp is >= this value. * Format: `YYYY-MM-DD HH:MM:SS` (space-separated — NOT ISO 8601). */ lastMessageAt(timestamp: string): ReservationFilter; /** Narrow to one or more statuses. */ status(status: ReservationStatus$1 | ReservationStatus$1[]): ReservationFilter; /** Scope to specific property UUIDs. **Required by the API.** */ properties(ids: string[]): ReservationFilter; /** * Request one or more include fields. Pass as separate arguments: * `.include('guest', 'properties', 'review')`. */ include(...fields: ReservationIncludeField[]): ReservationFilter; perPage(n: number): ReservationFilter; /** * Materialize the filter into a plain params object suitable for * `client.reservations.list()`. * * @throws {ConfigurationError} when `properties` has not been supplied */ toParams(): ReservationListParams$1; } /** * Fluent, immutable builder for `client.properties.list` params. * * @example * ```ts * const params = new PropertyFilter() * .tags(['tag-uuid-1', 'tag-uuid-2']) * .include('user', 'listings') * .perPage(100) * .toParams() * * await client.properties.list(params) * ``` */ declare class PropertyFilter { private readonly params; constructor(params?: PropertyListParams); /** Narrow to properties tagged with any of the given tag UUIDs. */ tags(tagIds: string[]): PropertyFilter; /** * Request one or more include fields. Pass as separate arguments: * `.include('user', 'listings', 'details')`. Accepted values are * `'user'`, `'listings'`, `'details'`, `'bookings'` — unknown values * are silently ignored by the API, so TypeScript narrowing via * {@link PropertyIncludeField} is the only fail-fast check. */ include(...fields: PropertyIncludeField[]): PropertyFilter; perPage(n: number): PropertyFilter; /** Materialize the filter into a plain params object. */ toParams(): PropertyListParams; } /** * Fluent builder for inquiry list params. * * Immutable — every method returns a new `InquiryFilter`. Build up the filter then * call {@link toParams} or pass directly to `client.inquiries.list(filter.toParams())`. * * The underlying API requires a non-empty `properties` filter; * {@link toParams} throws {@link ConfigurationError} if none was supplied. * * @example * ```ts * const params = new InquiryFilter() * .properties(['prop-uuid']) * .include('guest', 'properties') * .lastMessageAfter('2026-01-01T00:00:00Z') * .perPage(50) * .toParams() * * await client.inquiries.list(params) * ``` */ declare class InquiryFilter { private readonly params; constructor(params?: Partial); properties(ids: string[]): InquiryFilter; include(...fields: InquiryIncludeField[]): InquiryFilter; lastMessageAfter(datetime: string): InquiryFilter; page(n: number): InquiryFilter; perPage(n: number): InquiryFilter; /** * Materialize the filter. * * @throws {ConfigurationError} if `.properties()` was never called or was * called with an empty array — the `/v2/inquiries` endpoint requires a * non-empty set of property UUIDs. */ toParams(): InquiryListParams; } declare const VERSION = "0.7.2"; export { AuthenticationError, type CacheConfig, type CalendarData, type CalendarDay$1 as CalendarDay, type CalendarDayPrice, type CalendarDayStatus, CalendarResource, type CalendarUpdate, type CancelReservationInitiatedBy, ConfigurationError, index as Connect, type CreateIcalImportOptions, type CreateKnowledgeHubItemOptions, type CreateQuoteParams, type CreateReservationFinancials, type CreateReservationGuest, type CreateReservationGuestCounts, type CreateReservationParams, type EnrichmentField, ForbiddenError, type Guest, AuthenticationError as HospitableAuthError, HospitableClient, type HospitableClientConfig, ConfigurationError as HospitableConfigurationError, HospitableConnectClient, type HospitableConnectClientConfig, HospitableError, ForbiddenError as HospitableForbiddenError, NotFoundError as HospitableNotFoundError, RateLimitError as HospitableRateLimitError, ServerError as HospitableServerError, ValidationError as HospitableValidationError, InquiriesResource, type Inquiry, InquiryFilter, type InquiryGuest, type InquiryGuestCounts, type InquiryIncludeField, type InquiryList, type InquiryListParams, type InquiryListing, type InquiryUser, type KnowledgeHub, type KnowledgeHubItem, type KnowledgeHubProperty, KnowledgeHubResource, type KnowledgeHubSource, type KnowledgeHubTopic, MemoryCache, type Message, type MessageAttachment, type MessageContentType, type MessageReaction, type MessageReceipt, type MessageSender, type MessageSenderType, type MessageSource, type MessageTemplate$1 as MessageTemplate, type MessageThread, MessagesResource, type Money, NotFoundError, type PageFetcher, type PaginatedResponse, type Payout$1 as Payout, type PayoutList, type PayoutListParams$1 as PayoutListParams, PayoutsResource$1 as PayoutsResource, PropertiesResource, type Property, type PropertyAddress, type PropertyBookingFee, type PropertyBookingPolicies, type PropertyBookings, type PropertyCapacity, type PropertyDetails, PropertyFilter, type PropertyHouseRules, type PropertyIcalImport, type PropertyImage, type PropertyIncludeField, type PropertyList, type PropertyListParams, type PropertyListing, type PropertyListingCoHost, type PropertyListingMarkup, type PropertyOccupancyBasedRules, type PropertyOccupancyFee, type PropertyParentChild, type PropertyPaymentTerms, type PropertyRoomBed, type PropertyRoomDetail, type PropertySearchParams, type PropertyTag, type PropertyUser, type Quote, RESERVATION_STATUSES, RateLimitError, type Reservation$1 as Reservation, type ReservationDateQuery, ReservationFilter, type ReservationFinancialLineItem, type ReservationFinancials$1 as ReservationFinancials, type ReservationFinancialsGuest$1 as ReservationFinancialsGuest, type ReservationFinancialsHost$1 as ReservationFinancialsHost, type ReservationGuests, type ReservationIncludeField, type ReservationLegacyStatusHistoryEntry, type ReservationList, type ReservationListParams$1 as ReservationListParams, type ReservationPlatform, type ReservationStatus$1 as ReservationStatus, type ReservationStatusHistoryEntry, type ReservationStatusObject, type ReservationUser, ReservationsResource$1 as ReservationsResource, type ResourceCacheConfig, type Review$1 as Review, type ReviewDetailedRating$1 as ReviewDetailedRating, type ReviewDetailedRatingType, type ReviewGuest, type ReviewIncludeField, type ReviewList, type ReviewListParams$1 as ReviewListParams, type ReviewPrivate, type ReviewProperty, type ReviewPublic, type ReviewReservation, type ReviewRespondBody, ReviewsResource$1 as ReviewsResource, type SendMessageOptions, type SendReservationMessageOptions, ServerError, TokenManager, type TokenManagerConfig, type Transaction$1 as Transaction, type TransactionList, type TransactionListParams$1 as TransactionListParams, TransactionsResource$1 as TransactionsResource, type UpdateIcalImportOptions, type UpdateKnowledgeHubItemOptions, type UpdateReservationParams, type User, UserResource, VERSION, ValidationError, cacheKey, collectAll, createErrorFromResponse, isReservationStatus, normalizeInquiry, normalizeReservation, paginate, sanitize };