Appearance
Scopes
Scopes define what a host consents to share with your app at install time. Declare them in your manifest; the host sees a human-readable list at the consent screen before approving.
The scope catalog
| Scope | Label | What it grants |
|---|---|---|
read_bookings | Read bookings | Booking details including dates, status, guest counts, and totals. Required for most webhook topics. |
read_contacts | Read guest contacts (PII) | Guest names, email addresses, and phone numbers (personal data). Shown separately on the consent screen to flag PII access. |
read_conversations | Read conversations | Message threads between the host and their guests. |
read_properties | Read properties and unit types | Property names, addresses, and unit type inventory. |
read_rates | Read rates and availability | Nightly rates and availability calendars for the host's properties. |
write_rates | Update rates and restrictions | Set nightly rates and stay restrictions on unit types via ratesUpdate. |
read_payments | Read payments | Payments recorded against bookings: charges, refunds, amounts, and outcomes. |
read_invoices | Read invoices | Issued invoices and credit notes including numbers, totals, and status. |
read_reviews | Read guest reviews | Guest reviews including ratings, review text, and publication status. |
write_conversations | Send guest messages | Send messages to guests on the host's behalf via messageSend. |
write_bookings | Flag and annotate bookings | Add warning flags and notes to bookings via bookingFlagSet, shown to the host in the dashboard. |
write_charges | Add charges to bookings | Add fees or charges to a booking before its invoice is issued via bookingChargeAdd. |
Scopes and webhooks
Most webhook topics require a read scope. A topic is only delivered if the install holds its required scope — subscribing without the scope delivers nothing silently. The scope requirement for each topic is shown in the Webhooks reference.
How consent works
Partner publishes manifest with scopes ["read_bookings", "write_conversations"]
│
Host finds app in marketplace (or visits OAuth authorize URL)
│
Consent screen shows human-readable scope list
· Read bookings
· Send guest messages
│
Host approves → install created with granted_scopes = ["read_bookings", "write_conversations"]
│
Every API call and webhook delivery checks granted_scopes, not the manifestgranted_scopes is stored on the install and is the sole source of truth for access checks. The manifest's scopes array defines the maximum set you may request; consent may be for a subset (when using the OAuth flow with a scope parameter).
Requesting a subset via OAuth
When using the OAuth install flow, you can request fewer scopes than your manifest declares by passing a scope parameter:
GET /oauth/authorize
?client_id=your_client_id
&scope=read_bookings+write_conversations ← space-separated, URL-encoded
&redirect_uri=https://...
&state=...
&response_type=codeThe scope parameter must be a subset of your manifest's declared scopes. Requesting a scope not in the manifest returns a 400 error.
Scope escalation and re-consent
When you publish a new app version that declares additional scopes, existing installs are not automatically upgraded:
- The app keeps running on the install's current
granted_scopes. - API calls and webhook deliveries that require a new scope are denied.
- The host sees a "Requests new permissions" banner on the app's settings page and on their My Apps dashboard.
- The host approves the new scopes →
granted_scopesis updated → the app gains access to the new data.
This means there is never a silent scope escalation. Your app must handle the period between version approval and host re-consent gracefully — the scope checks will return userErrors on any operation that needs a scope the host hasn't approved yet.
Principle of least privilege
Declare only the scopes your app genuinely needs. Hosts see the full list at install; unnecessary scopes reduce conversion and raise trust concerns. If your integration only needs to send messages on booking confirmation, you need read_bookings (for the webhook and booking data) and write_conversations (to send the message) — not read_contacts, read_payments, etc.