# Scope reference

Every scope Haven declares, what it grants, and what it deliberately does not.

This page is generated from the scope registry the server enforces, so it cannot describe a permission the code does not implement. If a scope is missing here, it does not exist.

There are 47 declared scopes: 26 you can request today, 7 planned, and 14 that no application will ever hold.

## Tiers

Every grantable scope carries a tier, which decides how much review it needs before Haven adds it to your application and how it appears on the host consent screen.

| Tier | What it means |
| --- | --- |
| `standard` | Ordinary business data the host already sees on their own dashboard, or a reversible change to it. Any approved application may hold it. |
| `sensitive` | Third-party personal data, or an irreversible action such as cancelling a stay or messaging a guest. Needs a named sign-off from Haven staff, and the consent screen carries a warning. |
| `restricted` | Arrival secrets and money leaving the account. Same sign-off, and the consent row is never pre-ticked: the host has to select it individually. |

## Scopes you can request

### Account

| Scope | Tier | What it allows |
| --- | --- | --- |
| `account:read` | standard | See which Haven account it is connected to and what it is allowed to do. |

#### `account:read`

See which Haven account it is connected to and what it is allowed to do.

Grants:

- The account reference code, display name, time zone and default currency
- Which kind of context the grant acts in: your own account, a workspace seat, or an agency link
- The effective role the grant carries (OWNER, MANAGER or VIEWER)
- The connected app’s own name and client id
- The exact scope list on the token, and when the connection was made
- The current rate-limit budget and reset time

Does not grant:

- The name or email address of the person who approved the connection
- Any listing, booking, guest, message or discount code
- Billing state, subscription plan, payout balance or ad wallet
- The list of other apps connected to this account

### Listings

| Scope | Tier | What it allows |
| --- | --- | --- |
| `listings:read` | standard | Read your listings and collection sites, including photos, the full address, descriptions, amenities and site branding. |
| `listings:write` | standard | Change your listing content: title, description, house rules, amenities, capacity, and check-in and check-out times. |
| `listings:publish` | sensitive | Archive or hide a listing, and turn booking or instant book on and off. |

#### `listings:read`

Read your listings and collection sites, including photos, the full address, descriptions, amenities and site branding.

Grants:

- Every listing on the account, by reference code, including archived ones
- Title, public URL, archived flag, a 20-photo preview and the full photo set
- The street address, coordinates, neighborhood and display location
- Descriptions, house rules, amenities and the listing’s logo, contact and social profiles
- The host profile used as an author byline, when one exists
- Capacity: maxGuests, bedrooms, bathrooms, halfBaths, beds
- Check-in and check-out times and the listing’s IANA time zone
- City, region and country
- Currency code and the default nightly rate in integer minor units
- pmsOwner and lockedDomains, so a partner can tell what it may write
- Every collection site, and one collection in full: logo, contact, social profiles, author, target cities and neighborhoods

Does not grant:

- Wifi password, gate code, directions or check-in instructions — see guidebook:secrets:read
- Guests, bookings, messages or discount codes
- Any change to a listing — see listings:write and listings:publish

#### `listings:write`

Change your listing content: title, description, house rules, amenities, capacity, and check-in and check-out times.

Grants:

- The update_listing_content operation, over the content half of a listing’s editable fields

Does not grant:

- Archiving or hiding a listing, or turning booking or instant book on and off — see listings:publish
- Nightly rates, price overrides, promotions and holiday bumps — see rates:write
- Minimum stays and check-in / check-out day rules — see stay-rules:write
- The wifi network and password, gate code, directions, check-in method details, check-in instructions or check-in photos. Reading those is guidebook:secrets:read, which is restricted tier and needs a named staff sign-off; a standard content scope must not write by omission what a restricted scope is needed to read.
- The listing’s contact email, phone number, custom domain or URL slug
- Creating or deleting a listing — creation is declared as listings:create and deferred; deletion is not offered

Writes target the `PROPERTY_CONTENT`, `LISTING_CONTENT` source-of-truth domains. A listing whose channel manager owns that domain will refuse the write. See [Requests and responses](../03-conventions/01-requests-and-responses.md).

#### `listings:publish`

Archive or hide a listing, and turn booking or instant book on and off.

**An app with this permission can stop your listings taking bookings.**

Grants:

- The set_listing_market_state operation, over exactly four fields: archived, hidden, allowBooking, instantBook

Does not grant:

- Any other listing field — the operation’s input schema carries these four keys and no others
- Deleting a listing
- Changing prices or rules on a listing it has hidden

Writes target the `PROPERTY_CONTENT` source-of-truth domain. A listing whose channel manager owns that domain will refuse the write. See [Requests and responses](../03-conventions/01-requests-and-responses.md).

### Calendar

| Scope | Tier | What it allows |
| --- | --- | --- |
| `calendar:read` | standard | Read which dates are taken on your listings, and why. |
| `calendar:write` | standard | Block dates on your calendar so they cannot be booked, and remove blocks again. |

#### `calendar:read`

Read which dates are taken on your listings, and why.

Grants:

- Every occupied span on a listing: a booking, a host block, or a sibling listing’s booking in a linked calendar group
- Start and end date of each span and its block type
- The reservation reference code where one exists, so a span can be joined to a booking
- lockedDomains for the listing

Does not grant:

- Who is staying — the guest’s name and email need reservations:read plus guests:read
- What a stay was charged — see reservations:read
- Price overrides or promotions on those dates — see rates:read
- Blocking or unblocking anything — see calendar:write

#### `calendar:write`

Block dates on your calendar so they cannot be booked, and remove blocks again.

Grants:

- The block_dates and unblock_dates operations

Does not grant:

- Cancelling or changing a real booking — see reservations:cancel
- Pricing on the dates it blocks — see rates:write
- Minimum stays — see stay-rules:write
- Writing availability on a listing whose AVAILABILITY domain a channel manager owns, or that follows a linked master: those calls are refused with 409 domain_locked before anything is written

Writes target the `AVAILABILITY` source-of-truth domain. A listing whose channel manager owns that domain will refuse the write. See [Requests and responses](../03-conventions/01-requests-and-responses.md).

### Rates and promotions

| Scope | Tier | What it allows |
| --- | --- | --- |
| `rates:read` | standard | Read your nightly price overrides, promotions and holiday price bumps. |
| `rates:write` | standard | Create, change and remove nightly price overrides, promotions and holiday price bumps. |

#### `rates:read`

Read your nightly price overrides, promotions and holiday price bumps.

Grants:

- Per-night price overrides in integer minor units, with the listing’s currency code
- Promotions and holiday price bump rules
- The date window applied to each collection, echoed back
- lockedDomains and pmsOwner for the listing

Does not grant:

- The listing’s base nightly rate — that is on the listing itself, see listings:read
- What a specific booking was actually charged — see reservations:read
- Discount codes — see discounts:read
- Payout amounts or fee breakdowns paid to Haven

#### `rates:write`

Create, change and remove nightly price overrides, promotions and holiday price bumps.

Grants:

- create_price_override, update_price_override, delete_price_override, clear_price_overrides_for_range
- create_promotion, update_promotion, delete_promotion
- delete_holiday_price_bump_rule

Does not grant:

- The listing’s base nightly rate, which no v1 scope writes. `listings:write` covers listing CONTENT and `rates:write` covers per-night overrides, promotions and holiday bumps; changing the standing nightly price stays a host action in the Haven dashboard.
- Creating a holiday price bump rule: only deletion is on the mobile write surface today, so only deletion is exposed
- Changing what an existing booking was charged — see reservations:refund
- Discount codes — see discounts:write. Checkout codes are Haven-owned and are not part of the RATES sync domain

Writes target the `RATES` source-of-truth domain. A listing whose channel manager owns that domain will refuse the write. See [Requests and responses](../03-conventions/01-requests-and-responses.md).

### Stay rules

| Scope | Tier | What it allows |
| --- | --- | --- |
| `stay-rules:read` | standard | Read your minimum-stay rules and your check-in and check-out day rules. |
| `stay-rules:write` | standard | Create, change and remove minimum-stay rules and check-in and check-out day rules. |

#### `stay-rules:read`

Read your minimum-stay rules and your check-in and check-out day rules.

Grants:

- Date-scoped minimum-stay overrides
- Weekly minimum-stay rules
- Check-in / check-out day rules and the per-day blocks they expand into

Does not grant:

- The listing’s default check-in and check-out times — see listings:read
- Availability — see calendar:read
- Changing any of these — see stay-rules:write

#### `stay-rules:write`

Create, change and remove minimum-stay rules and check-in and check-out day rules.

Grants:

- create_min_stay_override, update_min_stay_override, delete_min_stay_override
- create_weekly_min_stay_rule, update_weekly_min_stay_rule, delete_weekly_min_stay_rule, sync_weekly_min_stay_rules
- set_check_in_out_blocks — named for what it actually dispatches (setCheckInOutBlocksBulk), not for the mobile command name create_check_in_out_rule, which misdescribes it

Does not grant:

- Deleting a legacy check-in / check-out RULE row: the mobile command delete_check_in_out_rule declares codes: ['property'] but its action takes only { ruleId }, so the declared code is dead and the command is not reachable through reference codes. Excluded from v1 rather than shipped broken
- Blocking dates — see calendar:write
- Pricing — see rates:write

Writes target the `BOOKING_RULES` source-of-truth domain. A listing whose channel manager owns that domain will refuse the write. See [Requests and responses](../03-conventions/01-requests-and-responses.md).

### Bookings

| Scope | Tier | What it allows |
| --- | --- | --- |
| `reservations:read` | standard | Read your bookings and enquiries: dates, party size, status and what was charged. |
| `reservations:write` | sensitive | Approve or decline requests to book, and answer guests who asked you to price an add-on. |
| `reservations:cancel` | sensitive | Cancel a confirmed booking, which frees the dates and may refund the guest under your cancellation policy. |
| `reservations:refund` | restricted | Send a refund on a booking, and change the amount a booking is charged. |

#### `reservations:read`

Read your bookings and enquiries: dates, party size, status and what was charged.

Grants:

- The booking list and each booking’s detail, by reference code
- Type and origin (HAVEN, or the channel manager that owns it)
- Dates, whole nights, and party size: guests, children, infants, pets
- The pricing snapshot in integer minor units with a sibling currency code, or null where none was persisted
- confirmedAt, cancelledAt and the cancellation reason
- The host’s own note on a block
- A summary of the listing the booking is on

Does not grant:

- The guest’s name or email address — both are returned as null without guests:read
- The guest’s phone number, which is not on this surface at any scope
- The message thread on the booking — see messaging:read
- Card details, Stripe identifiers or identity-verification documents, none of which are on this surface at any scope
- Approving, cancelling, refunding or repricing anything

#### `reservations:write`

Approve or decline requests to book, and answer guests who asked you to price an add-on.

**Approving a request charges the guest and confirms the stay on your calendar.**

Grants:

- approve_booking
- respond_bundle_quote

Does not grant:

- Cancelling a confirmed booking — see reservations:cancel
- Refunding one or changing what it is charged — see reservations:refund
- Creating a booking directly, which is not on the v1 surface
- Reading the bookings it approves — see reservations:read

Writes target the `RESERVATIONS` source-of-truth domain. A listing whose channel manager owns that domain will refuse the write. See [Requests and responses](../03-conventions/01-requests-and-responses.md).

#### `reservations:cancel`

Cancel a confirmed booking, which frees the dates and may refund the guest under your cancellation policy.

**This cannot be undone, and it emails your guest.**

Grants:

- cancel_reservation

Does not grant:

- Issuing a refund outside the cancellation policy — see reservations:refund
- Approving or repricing a booking
- Blocking the dates it freed — see calendar:write

Writes target the `RESERVATIONS` source-of-truth domain. A listing whose channel manager owns that domain will refuse the write. See [Requests and responses](../03-conventions/01-requests-and-responses.md).

#### `reservations:refund`

Send a refund on a booking, and change the amount a booking is charged.

**This moves money out of your account. Every call is confirmed in two steps before anything is charged or refunded.**

Grants:

- issue_booking_refund and adjust_booking_price, both of which declare confirmation: 'required' and are only reachable through propose then commit

Does not grant:

- Payouts to your bank, your Stripe Connect account, or your Haven subscription — none of those are grantable at any tier
- Any charge not attached to one of your bookings
- Cancelling a booking — see reservations:cancel

Writes target the `RESERVATIONS` source-of-truth domain. A listing whose channel manager owns that domain will refuse the write. See [Requests and responses](../03-conventions/01-requests-and-responses.md).

### Discount codes

| Scope | Tier | What it allows |
| --- | --- | --- |
| `discounts:read` | standard | Read your discount codes, what they take off, and what they apply to. |
| `discounts:write` | standard | Change, enable, disable and delete your discount codes. |

#### `discounts:read`

Read your discount codes, what they take off, and what they apply to.

Grants:

- Every discount code on the account, its redeemable string, percentage, date window and enabled state
- The listing or collection reference code it applies to

Does not grant:

- Redemption history or revenue attribution, which are not on the v1 surface
- Validating a code against a specific stay
- Creating or changing a code — see discounts:write

#### `discounts:write`

Change, enable, disable and delete your discount codes.

Grants:

- update_discount_code, toggle_discount_code, delete_discount_code

Does not grant:

- Creating a discount code. The action takes a nested target: { scope, propertyId \| propertyGroupId }, and the shared raw-id refusal scans top-level keys only, so today the only working call path is the raw integer id that refusal cannot see. Creation lands once the nested translator does; a public operation name is permanent, so it is not shipped broken first
- Setting a fixed-amount discount, which the model does not carry

### Guidebook

| Scope | Tier | What it allows |
| --- | --- | --- |
| `guidebook:read` | standard | Read the non-secret parts of your guidebooks: house rules, checkout steps, contact details, and how check-in works. |
| `guidebook:secrets:read` | restricted | See the wifi password, gate code, directions and check-in instructions for your listings. |

#### `guidebook:read`

Read the non-secret parts of your guidebooks: house rules, checkout steps, contact details, and how check-in works.

Grants:

- Check-in and check-out times, and whether check-in is flexible
- checkInMethod — the word "keypad" or "lockbox", never the code itself
- Pet rules prose, checkout instructions and the checkout checklist flags
- The listing’s contact email and phone number

Does not grant:

- The wifi network name and password, gate code, directions, check-in instructions or check-in photos — all six string fields come back empty and the photo array comes back empty without guidebook:secrets:read
- Smart-lock access codes, which are encrypted at rest and are not on this surface at any scope
- Writing any guidebook field — no v1 scope writes the guidebook

#### `guidebook:secrets:read`

See the wifi password, gate code, directions and check-in instructions for your listings.

**These are the details a stranger would need to get inside. Only grant this to an app that has to deliver them to your guests.**

Grants:

- Exactly the fields in PUBLIC_FIELD_GATES['guidebook:secrets:read'], which is asserted equal to LOCKED_GUIDE_STRING_FIELDS plus checkInPhotos, read from src/lib/guide-access/locked-guide-fields.ts at test time so the two can never diverge

Does not grant:

- Smart-lock access codes (EventAccessCode.encryptedCode), which are not on the public surface at any scope
- Writing any of these values — no v1 scope does
- The guidebook itself: this scope only unlocks fields inside a payload guidebook:read returned, which is why it must be requested alongside it

Must be requested alongside: `guidebook:read`.

### Blog

| Scope | Tier | What it allows |
| --- | --- | --- |
| `blog:read` | standard | Read the articles in your blog library, and which of your sites each one is published to. |
| `blog:write` | standard | Add and update articles in your blog library, and choose which of your sites each one appears on. |

#### `blog:read`

Read the articles in your blog library, and which of your sites each one is published to.

Grants:

- GET /blog-posts — title, slug, excerpt, tags, status, publish date, author byline and the live URL of every article in the library
- Which listing and collection sites each article is published to, by reference code
- Which app delivered an article, when one was delivered over this API rather than written in Haven

Does not grant:

- The article body. A partner that wrote an article already has its text, and one that did not has no reason to read a host’s unpublished drafts — see the module note on `blog:write`
- Creating or changing an article — see blog:write
- Any other site content: the guidebook, local guides, FAQs or testimonials

#### `blog:write`

Add and update articles in your blog library, and choose which of your sites each one appears on.

Grants:

- The upsert_blog_post operation, which files an article under the app’s own id and updates that same article on every later delivery. An article sent as published goes live on the sites named in that delivery
- The unpublish_blog_post operation, which takes an article off your public sites and returns it to draft
- Choosing which of your listing and collection sites an article is published to

Does not grant:

- Any control over how an article looks. Fonts, colours, layout and spacing come from your site’s own design, and styling sent with an article is discarded rather than applied
- Your page titles, meta descriptions, canonical links, structured data or sitemap, which Haven writes from your own settings
- Deleting an article, or touching one your blog already had before the app was connected
- Editing any other part of your site

### Messages

| Scope | Tier | What it allows |
| --- | --- | --- |
| `messaging:read` | sensitive | Read your guest message threads and the messages in them. |
| `messaging:send` | sensitive | Send messages to your guests, from you. |
| `messaging:write` | standard | Clear the unread badge on your message threads. |

#### `messaging:read`

Read your guest message threads and the messages in them.

**Message bodies are correspondence between you and your guests.**

Grants:

- The thread list: kind, the booking and listing each thread belongs to, last message time, a 200-character preview, which side sent it, and whether it is unread
- Each message: sender, source (Haven, a channel manager, SMS, WhatsApp, email), body, attachment count, delivery status and timestamp

Does not grant:

- Sending anything — see messaging:send
- Clearing the unread badge — see messaging:write
- The guest’s name or email on a thread — see guests:read
- Attachment bytes, which this surface counts but does not carry

#### `messaging:send`

Send messages to your guests, from you.

**Messages reach a real person by email, SMS or WhatsApp and cannot be recalled.**

Grants:

- send_host_message, into an existing thread addressed by conversation code

Does not grant:

- Reading the thread it is writing into — see messaging:read
- Starting a thread with anyone who is not already a party to one of your bookings or enquiries
- Marketing sends, broadcasts, or messaging a guest after their stay is archived
- Bypassing the per-thread throttle, which is enforced independently of the token’s own rate-limit budget

#### `messaging:write`

Clear the unread badge on your message threads.

Grants:

- mark_conversation_read

Does not grant:

- Sending anything — see messaging:send. Split from it deliberately, so an inbox mirror can keep your badge honest without gaining the ability to write to a guest
- Deleting a thread or a message
- Marking a GUEST’s side of a thread read, which is a different command on a different principal and is not on this surface

### Guests

| Scope | Tier | What it allows |
| --- | --- | --- |
| `guests:read` | sensitive | See guest names and email addresses on your bookings and message threads. |

#### `guests:read`

See guest names and email addresses on your bookings and message threads.

**This shares your guests’ personal details with a third party.**

Grants:

- guestDisplayName and guestEmail on a booking’s detail
- guestDisplayName on a booking in a list
- guestDisplayName on a message thread
- Nothing else — the exact field list is PUBLIC_FIELD_GATES['guests:read'], and a test asserts the projection reads that table rather than an inline list

Does not grant:

- Any booking or thread the token could not already see: this permission only fills in fields on records another permission returned, which is why it must be requested alongside reservations:read
- Guest phone numbers, which are not on the v1 surface at any scope
- Payment instruments or identity-verification documents
- Exporting a guest list, or any guest not attached to one of your bookings or enquiries
- Message bodies — see messaging:read

Must be requested alongside: `reservations:read`.

### Sync settings

| Scope | Tier | What it allows |
| --- | --- | --- |
| `integrations:read` | standard | See which channel manager or property manager owns each listing, and which parts of it Haven will not let anyone else change. |

#### `integrations:read`

See which channel manager or property manager owns each listing, and which parts of it Haven will not let anyone else change.

Grants:

- Whether a listing is synced, and the display name of the partner that owns it
- lockedDomains and writableDomains for the listing
- Whether the listing follows a master in a linked calendar group, and that master’s title

Does not grant:

- The credentials for those connections
- Connecting or disconnecting a channel manager
- Changing which domains are locked, or unlocking a field
- Any other app’s grants on this account

### Platform

| Scope | Tier | What it allows |
| --- | --- | --- |
| `webhooks:manage` | standard | Register and manage the addresses this app uses to be told when something changes. |

#### `webhooks:manage`

Register and manage the addresses this app uses to be told when something changes.

Grants:

- Creating, listing, updating and deleting this app’s own webhook endpoints for this grant
- Sending a test event, reading the delivery log, and replaying a failed delivery

Does not grant:

- Any other app’s endpoints, or endpoints on any other account
- The app’s CLIENT-WIDE endpoint — the one whose `grantId` is null, which receives events for every host the app is connected to. A host access token may only ever touch endpoints whose `grantId` is its own grant; client-wide endpoints are managed from the developer console with client credentials. Without that rule this scope is a confused deputy: one host consenting would let the app repoint, disable, or read the delivery log of a channel carrying every other host’s events.
- The contents of the events themselves, which stay gated by the data scopes: a webhook body carries reference codes and a timestamp, and the follow-up read is what needs reservations:read or calendar:read
- Subscribing to an event class the grant holds no read scope for

## Planned scopes

These are real and specified, but not built. Requesting one returns `invalid_scope` naming the release it is planned for, so you can build a roadmap against it rather than filing a ticket to ask.

| Scope | Planned for | Why it is not in v1 |
| --- | --- | --- |
| `payouts:read` | v1.2 | The payout ledger has no positive-allowlist DTO and reaches Stripe Connect balance data that needs its own redaction pass. Declared now so a partner can plan against it. |
| `reviews:read` | v1.2 | Haven-native and channel-imported reviews have no reconciled shape yet, and one of the two carries private text that is a secret on a par with a gate code. |
| `reviews:write` | v1.2 | Blocked on reviews:read. |
| `tasks:read` | v1.2 | The cleaning and turnover surface is mid-build and its rows are not yet addressed by reference code, so exposing them would publish integer primary keys. |
| `tasks:write` | v1.2 | Blocked on tasks:read. |
| `media:write` | v1.1 | Photo upload needs a signed-upload endpoint and a scan step, neither of which exists. Reordering and deleting existing photos rides on listings:write today. |
| `listings:create` | v1.2 | Creating a listing changes what the account is billed for, so it needs a host-side confirmation the consent screen cannot give in advance. |

## Scopes no application will hold

Declared so the boundary is documented rather than merely absent. An absent scope is indistinguishable from an oversight; a refused one is a decision. Requesting any of these returns `invalid_scope` with the reason below.

| Scope | Category | Why |
| --- | --- | --- |
| `billing:read` | money | Subscription plan, invoices and card details. canManageBilling() returns false for every partner grant unconditionally, so there is nothing behind this scope to read. |
| `billing:write` | money | Starting, changing or cancelling a paid plan spends the host’s money on a decision only the host can make. |
| `payouts:write` | money | Moves the host’s money to a bank account. No third party gets this, at any tier, ever. |
| `ads:read` | money | The advertising wallet is a prepaid balance; its reads are one query away from its writes and the surface is not worth splitting for a third party. |
| `ads:write` | money | Spends a prepaid balance the host topped up. |
| `team:read` | human-consent | Who holds a seat on the account is the account’s own access-control state, not business data. A partner that needs to know who acts for the account gets the effective role on account:read. |
| `team:write` | human-consent | Inviting, removing or re-roling a teammate grants and revokes whole-account access, so it stays a deliberate human action — never delegated to an app. |
| `workspaces:write` | human-consent | Workspace structure decides what every seat on the account can see. canManageWorkspaces() returns false for every partner grant unconditionally. |
| `account:close` | human-consent | Irreversible, cancels billing, and revokes every other grant including this one. |
| `devices:write` | different-principal | Push device registration writes the human’s own install row, keyed on their User.id and visible to nobody else. A partner acting for the account is not that human, and these are the only two commands that skip the workspace write backstop for a person. |
| `guests:write` | different-principal | The nine guest-scoped commands act on the caller’s OWN stay — signing a rental agreement, answering a poll, inviting a co-guest — and deliberately skip the workspace write backstop because a guest writes nothing the account owns. A host-acting token must never reach them. A guest-side grant would be a different grant type with a different consent flow. |
| `notifications:read` | app-shell | Haven’s own in-app alert feed. Every row is derived from a booking, message or listing a resource read already returns, so it is a second shape for the same facts. |
| `notifications:write` | app-shell | Dismissing an alert changes what the host sees in Haven’s own UI and nothing else. It also returns a bare boolean rather than a result, so a failure would answer 200. |
| `guide-chat:use` | unbounded-cost | The guidebook assistant is a language-model channel billed to Haven per token, with a documented rate-limit bypass of its own. A bearer credential on it is an uncapped spend channel pointed at Haven’s bill. |
