Beyond Pricing Insights API
The Insights API from Beyond Pricing — 1 operation(s) for insights.
The Insights API from Beyond Pricing — 1 operation(s) for insights.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/beyond-pricing:beyond-pricing-insights-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Beyond Insights API
version: 2.0.0
description: Bearer-protected API for third-party integrations. Supports OAuth2 client credentials and personal access tokens. Follows JSON:API specification.
tags:
- name: Insights
paths:
/api/v1/listings/{listing_id}/market-insights/:
get:
operationId: get_listing_market_insights
description: 'Compare a listing''s daily performance with its neighborhood.
**Required scope:** `insights:read`
Returns one entry per stay date. Each entry carries both sides of the
comparison: `listing` is this listing, `benchmark` is built from
scraped OTA data for the cohort the listing belongs to, narrowed to its
bedroom count and to entire-home rentals. Studios and one-bedrooms
share one cohort (`meta.cohort-bedrooms` is `["0", "1"]` for both). Which cohort that is follows
`filter[compare-to]`.
**`null` never means zero.** A metric is `null` when it could not be
computed for that date -- no availability, no bookings, or no scrape
coverage. A genuine zero is returned as `0.0`. This matters most for
`average-booked-rate`, which is `null` on a date with no bookings; use
`average-posted-rate` where you need a price on such dates.
**Precision is not symmetric.** The `benchmark` side of every metric is
aggregated across the cohort and rounded to a whole number upstream;
the `listing` side is exact. Rates are in `meta.currency` and in major
units -- `84.46` means 84.46, not 84 cents.
**Entry ids** are `{listing-id}:{compare-to}:{stay-date}`. The
benchmark half of a row depends on both, so neither can be left out of
the identity.
**Comparison scope:** `filter[compare-to]=cluster` (default) or
`market`. Widen to `market` when the cluster cohort has no data
(`meta.benchmark-data-available` is `false`).
**Currency:** Derived from the listing owner''s billing configuration
and echoed in `meta.currency`. There is no currency parameter. This is
not the listing''s own currency, which is what calendar prices and the
listing''s own price fields are quoted in; the two can differ.
**Date range:** `filter[start-date]` and `filter[end-date]`
(YYYY-MM-DD). Defaults to the current calendar year, which fits in a
single page.
**Pagination:** `page[number]` and `page[size]`.
**Example:** `GET /api/v1/listings/123/market-insights/?filter[start-date]=2026-01-01&filter[end-date]=2026-06-30`'
summary: Compare a listing with its market
parameters:
- in: path
name: listing_id
schema:
type: integer
required: true
- name: page[number]
required: false
in: query
description: A page number within the paginated result set.
schema:
type: integer
- name: page[size]
required: false
in: query
description: Number of results to return per page.
schema:
type: integer
- in: query
name: filter[start-date]
schema:
type: string
format: date
description: First stay date (YYYY-MM-DD). Defaults to 1 January of the current year.
- in: query
name: filter[end-date]
schema:
type: string
format: date
description: Last stay date (YYYY-MM-DD). Defaults to 31 December of the current year. The range must not exceed 731 days.
- in: query
name: filter[compare-to]
schema:
type: string
enum:
- cluster
- market
description: 'Which benchmark to compare against: `cluster` (default) for the listing''s immediate neighborhood, or `market` for its whole market.'
- in: query
name: fields[market-insights]
schema:
type: array
items:
type: string
enum:
- id
- date
- adj-occupancy
- occupancy
- average-booked-rate
- average-posted-rate
description: endpoint return only specific fields in the response on a per-type basis by including a fields[TYPE] query parameter.
explode: false
tags:
- Insights
security:
- oauth2:
- insights:read
- oauth2:
- beyond:read
- personalAccessToken: []
responses:
'200':
content:
application/vnd.api+json:
schema:
$ref: '#/components/schemas/PaginatedMarketInsightsList'
examples:
DailyComparisonEntries:
value:
data:
- data:
- type: market-insights
id: 123:cluster:2026-03-01
attributes:
date: '2026-03-01'
adj-occupancy:
listing: 71.4
benchmark: 63.0
occupancy:
listing: 68.2
benchmark: 59.0
average-booked-rate:
listing: 210.5
benchmark: 188.0
average-posted-rate:
listing: 225.0
benchmark: 191.0
- type: market-insights
id: 123:cluster:2026-08-20
attributes:
date: '2026-08-20'
adj-occupancy:
listing: 0.0
benchmark: 58.0
occupancy:
listing: 0.0
benchmark: 55.0
average-booked-rate:
listing: null
benchmark: 175.0
average-posted-rate:
listing: 240.0
benchmark: 179.0
meta:
pagination:
page: 1
pages: 1
count: 2
currency: GBP
benchmark-data-available: true
compare-to: cluster
cohort-bedrooms:
- '2'
start-date: '2026-01-01'
end-date: '2026-12-31'
links:
first: http://example.com/articles?page%5Bsize%5D=10&page%5Bnumber%5D=1
last: http://example.com/articles?page%5Bsize%5D=10&page%5Bnumber%5D=9
prev: http://example.com/articles?page%5Bsize%5D=10&page%5Bnumber%5D=1
next: http://example.com/articles?page%5Bsize%5D=10&page%5Bnumber%5D=3
meta:
pagination:
count: 42
page: 2
pages: 5
summary: Daily comparison entries
description: ''
'400':
description: Validation error
'401':
description: Unauthorized - invalid or missing bearer token
'403':
description: Forbidden
'404':
description: Not found - resource does not exist
'422':
description: Unprocessable - the listing cannot be placed in a market cohort
'429':
description: Rate limit exceeded
'500':
description: Internal server error
components:
schemas:
PaginatedMarketInsightsList:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/MarketInsights'
links:
type: object
description: Pagination links for the primary data. These keys MUST be used for pagination links; each MUST be omitted or `null` when that link is unavailable. Values follow JSON:API link rules (URI string, link object, or null). https://jsonapi.org/format/#fetching-pagination https://jsonapi.org/format/#document-links
properties:
first:
type:
- string
- 'null'
format: uri
example: http://example.com/articles?page%5Bsize%5D=10&page%5Bnumber%5D=1
description: 'The first page of data. A JSON:API link: URI string, link object, or null. See https://jsonapi.org/format/#document-links.'
last:
type:
- string
- 'null'
format: uri
example: http://example.com/articles?page%5Bsize%5D=10&page%5Bnumber%5D=9
description: 'The last page of data. A JSON:API link: URI string, link object, or null. See https://jsonapi.org/format/#document-links.'
prev:
type:
- string
- 'null'
format: uri
example: http://example.com/articles?page%5Bsize%5D=10&page%5Bnumber%5D=1
description: 'The previous page of data. A JSON:API link: URI string, link object, or null. See https://jsonapi.org/format/#document-links.'
next:
type:
- string
- 'null'
format: uri
example: http://example.com/articles?page%5Bsize%5D=10&page%5Bnumber%5D=3
description: 'The next page of data. A JSON:API link: URI string, link object, or null. See https://jsonapi.org/format/#document-links.'
additionalProperties: false
meta:
type: object
description: Non-standard meta-information. Page-number stacks often nest totals under `pagination`. JSON:API does not define these keys. Servers MAY add other `meta` members; this schema documents the usual djangorestframework-json-api shape only. https://jsonapi.org/format/#document-meta
properties:
pagination:
type: object
description: Typical page-number metadata from djangorestframework-json-api; not mandated by JSON:API.
properties:
count:
type: integer
minimum: 0
example: 42
description: Total number of resources across all pages.
page:
type: integer
minimum: 1
example: 2
description: Current page number (1-based).
pages:
type: integer
minimum: 0
example: 5
description: Total number of pages.
additionalProperties: false
additionalProperties: false
required:
- data
MarketInsightResourceTypeEnum:
type: string
enum:
- market-insights
MarketInsightsComparison:
type: object
description: 'One metric, on both sides of the comparison.
`null` means the metric could not be computed for that date -- no
availability, no bookings, or no scrape coverage. It never means zero;
a real zero is returned as `0.0`.
The two sides do not carry the same precision: `benchmark` is aggregated
across the cohort and rounded to a whole number upstream, `listing` is
exact. Do not read a sub-point difference between them as signal.'
properties:
listing:
type:
- number
- 'null'
format: double
description: Value for this listing, at full precision (aggregated over its sub-units for a multi-unit parent).
benchmark:
type:
- number
- 'null'
format: double
description: 'Value for the comparison cohort, from scraped OTA data. Which cohort that is follows `filter[compare-to]`: the listing''s neighborhood by default, or its whole market. Rounded to a whole number upstream, so it carries no decimals.'
required:
- benchmark
- listing
MarketInsights:
type: object
required:
- type
- id
additionalProperties: false
properties:
type:
allOf:
- $ref: '#/components/schemas/MarketInsightResourceTypeEnum'
description: The [type](https://jsonapi.org/format/#document-resource-object-identification) member is used to describe resource objects that share common attributes and relationships.
id:
type: string
description: '`{listing-id}:{compare-to}:{stay-date}`, e.g. `4033897:cluster:2026-03-01`. The benchmark half of a row depends on which listing was asked about and on `filter[compare-to]`, so both are part of the entry''s identity rather than the date alone.'
attributes:
type: object
properties:
date:
type: string
format: date
description: Stay date this entry describes
adj-occupancy:
allOf:
- $ref: '#/components/schemas/MarketInsightsComparison'
description: 'Adjusted occupancy percentage: booked nights over *available* nights, so blocked and unavailable nights do not count against it.'
occupancy:
allOf:
- $ref: '#/components/schemas/MarketInsightsComparison'
description: 'Occupancy percentage over all nights, including nights that were not available to book. Its `benchmark` side is `null` whenever `adj-occupancy`''s is: the scraped series publishes only the adjusted denominator, so neither variant is verifiable without it.'
average-booked-rate:
allOf:
- $ref: '#/components/schemas/MarketInsightsComparison'
description: Average nightly rate actually booked, in `meta.currency` and in major units (`84.46` is 84.46, not 84 cents). `null` when there were no bookings on that date.
average-posted-rate:
allOf:
- $ref: '#/components/schemas/MarketInsightsComparison'
description: Average nightly rate on offer, in `meta.currency` and in major units, booked or not. Useful as a fallback where `average-booked-rate` is `null`.
required:
- date
- adj-occupancy
- occupancy
- average-booked-rate
- average-posted-rate
securitySchemes:
oauth2:
type: oauth2
description: Use OAuth2 client credentials to mint an application token, or add `user_id` and optional `credential_id` in the Authorize dialog to request a user- or credential-scoped token.
flows:
clientCredentials:
tokenUrl: /o/token/
refreshUrl: /o/token/
scopes:
listings:read: Read listings
listings:write: Modify listings
reservations:read: Read reservations
accounts:read: Read account information
user:read: Read user information
user:write: Create and modify users
insights:read: Read market insights
compsets:read: Read competitive set data
neyoba:ask: Ask Neyoba
beyond:read: Read listings, performance, and market data via the Beyond MCP server
beyond:write: Modify pricing and listing settings via the Beyond MCP server
beyond:skills: Load Beyond revenue-management skills via the Beyond MCP server
beyond:usage: Read tool-call history and usage via the Beyond MCP server
webhooks:read: Read delivered webhook events
webhooks:write: Modify webhook configuration
personalAccessToken:
type: http
scheme: bearer
bearerFormat: PersonalAccessToken
description: Paste a `bpat_...` personal access token. PATs use the same Bearer header as OAuth2 tokens and must still include the runtime-required scopes for each endpoint, even though OpenAPI cannot encode scopes for non-OAuth bearer schemes.
x-provenance:
method: harvested
publisher: Beyond Pricing
source: https://developers.beyondpricing.com/api/v1/schema/
note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
stamped by stamp-openapi-provenance.py (roadmap#793)