Skip to content

Change History

Read who changed a listing's settings, what they changed, and when: the same history the Beyond dashboard shows on a listing's history page.

Endpoint Method Scope Token Tier Description
/api/v1/listings/<id>/change-history/ GET listings:read Both List a listing's settings changes, newest first

Try it out

Explore schemas and make live requests in the Swagger UI.

What is recorded

Beyond records a change every time a listing's settings are written, from any surface: the Beyond API (every PATCH to a listing customization), the Beyond dashboard and calendar, bulk edits, the Beyond MCP server, and Beyond itself. One change is one write: the settings saved together appear together in its changes list.

Each setting in a change carries a human-readable description of its new state, such as Set Base Price to 150. The previous value is not recorded. To know what a setting was before, read the earlier change to the same setting, or subscribe to the listing.base_price_changed webhook, which carries both the old and the new base price.

Prices the algorithm computes each day are not settings changes and do not appear here; read them from the calendar.

Who made a change

Two attributes say where and by whom, exactly as the "Location" and "User" columns of the dashboard's history page show them.

source is the surface the change was made from:

Value Surface
beyond-api A Beyond API client.
bulk-edit, bulk-edit-undo A bulk edit in the Beyond app, or its undo. Writes through the Beyond MCP server are bulk edits.
listing-customize, listing-calendar, listing-update, listing-onboarding, listing-review, pricing-dashboard, grid A page of the Beyond app.
group A listing group's settings in the Beyond app.
copy-from-listing Settings copied from another listing.
recommendation An accepted or rejected Beyond recommendation.
revenue-goal-rollover A revenue goal rollover.
internal-tools, internal-tools-copy-settings Beyond support.

source is null when the surface was not recorded. New values may appear, so treat an unknown source like null.

changed-by is who made the change, as recorded: usually the email or name of the account credential that made it (for a Beyond API change, the credential the token is bound to, or the user's primary credential for an application-level token), Beyond for an automated Beyond process, a Beyond support email, or a label such as External approval for a recommendation approved through a shared link. It is free text kept as written at the time, so it does not follow a later email change. Display it, do not parse it.

List Change History

Request

GET /api/v1/listings/123/change-history/?filter[changed-after]=2026-09-01T00:00:00Z
Parameter Description
filter[changed-after] Only changes made at or after this ISO 8601 timestamp (e.g. 2026-09-01T00:00:00Z).
filter[changed-before] Only changes made at or before this ISO 8601 timestamp. Combine with changed-after to bound a window.
page[number], page[size] Standard pagination. Default page size 25, maximum 100. Changes are ordered newest first.

Response

{
  "data": [
    {
      "type": "listing-changes",
      "id": "88213",
      "attributes": {
        "changed-at": "2026-09-21T14:03:11Z",
        "source": "beyond-api",
        "changed-by": "ops@example.com",
        "changes": [
          {"setting": "base-price", "description": "Set Base Price to 150"},
          {"setting": "min-price", "description": "Set Min Price to 90"}
        ]
      }
    },
    {
      "type": "listing-changes",
      "id": "88160",
      "attributes": {
        "changed-at": "2026-09-19T17:22:40Z",
        "source": "listing-customize",
        "changed-by": "host@example.com",
        "changes": [
          {
            "setting": "seasonal-min-stays",
            "description": "Set Min Stay to 3 from 2026-12-20 to 2027-01-03"
          }
        ]
      }
    },
    {
      "type": "listing-changes",
      "id": "88107",
      "attributes": {
        "changed-at": "2026-09-18T08:40:52Z",
        "source": "internal-tools",
        "changed-by": "support@beyondpricing.com",
        "changes": [
          {"setting": "max-stay", "description": "Set Max Stay to 30"}
        ]
      }
    }
  ],
  "meta": {
    "pagination": {"page": 1, "pages": 1, "count": 3}
  }
}

Fields

Field Description
id Change identifier. Higher ids are more recent.
changed-at When the change was made (UTC, ISO 8601).
source Where the change was made, or null. See Who made a change.
changed-by Who made the change, as recorded, or null. See Who made a change.
changes The settings this change wrote, in the order they were recorded.
changes[].setting The setting this change touched, named as the listing or listing customization resources name it, or will name it once exposed. null for a change that sets no single setting. See Setting names.
changes[].description Human-readable summary of the new state, in English, as the dashboard shows it. The wording may change: display it, do not parse it. null when Beyond has no description for the change.

Setting names

Settings you can read and change through the API:

setting Where to read or change it
enabled Listing activation
base-price Base price
extra-guest-fee Extra guest fees
min-price, max-price, monthly-min-price, day-of-week-min-prices, seasonal-day-of-week-min-prices, seasonal-prices, seasonal-monthly-prices Min/max prices
min-stay, gap-fill-min-stay, seasonal-min-stays, last-minute-min-stays, day-of-week-min-stays, seasonal-day-of-week-min-stays, seasonal-gap-fill-min-stays, seasonal-time-based-min-stays Min stays
dynamic-time-based-adjustments, time-based-adjustments, seasonal-time-based-adjustments Time-based adjustments
manual-overrides Manual overrides
occupancy-based-pricing (any of its attributes) Occupancy-based pricing
dynamic-gap-price-adjustments, gap-price-adjustments Gap price adjustments
checkin-days, checkout-days, seasonal-checkin-checkout-days, changeover-days-gap-fill-enabled Check-in and check-out days

Settings the API does not expose yet. Their names are the ones their API attributes will use once exposed; until then, read the change from description:

setting What it is
max-stay, seasonal-max-stays Maximum stays
min-booking-value, seasonal-min-booking-values Minimum booking values
monthly-pricing-enabled, seasonal-monthly-pricing-enabled, monthly-manual-overrides Monthly price posting and its overrides
time-based-min-prices, seasonal-time-based-min-prices Time-based minimum prices
time-based-gap-fill-min-stays, seasonal-time-based-gap-fill-min-stays Time-based gap fill minimum stays
time-based-day-of-week-min-stays, seasonal-time-based-day-of-week-min-stays Time-based day-of-week minimum stays
seasonal-length-of-stay-adjustments Seasonal length-of-stay adjustments
extra-guest-fee-tiers Extra guest fees that change with the number of guests
listing-goal, revenue-goal The listing's pricing goal and yearly revenue goal
on-program, special-requirements, listing-benchmark-enabled Program membership, special requirements, and listing benchmarking

An accepted or rejected Beyond recommendation (source: recommendation) is named after the setting it recommended, such as base-price or min-price; its description says whether it was accepted.

setting is null for a change that sets no single setting: a listing joining or leaving a group, or switching which group its settings come from. Those changes also have a null description. New names may appear, so treat an unknown setting like null.

Use cases

  1. Audit your own writes. Keep the changes whose source is beyond-api (the endpoint filters by time only, so filter source on your side) and match changed-at against your request log to confirm each PATCH landed.
  2. Detect edits made outside your integration. Poll with filter[changed-after] set to your last check, and react to changes to a setting you manage whose source is not beyond-api, for example by re-reading the customization before your next write.
  3. Show a history timeline. Render changed-at, source, changed-by, and each description as a per-listing activity feed, like the dashboard's history page.

Errors

Status Cause
400 A malformed timestamp filter, a sort parameter (the order is fixed, newest first), or an unknown query parameter.
401 Missing or invalid bearer token.
403 Token does not have the listings:read scope.
404 No listing with that id is visible to your token.
429 Rate limit exceeded. See Rate Limiting.