Skip to content

Read a PMS switchover's shadow comparison

GET
/v1/analytics/switchover-shadow
curl --request GET \
--url 'https://api.aerandil.com/v1/analytics/switchover-shadow?connector_id=2489E9AD-2EE2-8E00-8EC9-32D5F69181C0' \
--header 'Authorization: Bearer <token>'

One connector’s source PMS against Aerandil during the shadow run before cutover: per stream, what the loader has loaded, has still to load, rejected or deferred (and the newest rejects with their reasons); for the business date and the nine days after it, arrivals and departures on both sides (and in-house guests for the day); and per folio, the vendor’s status, dates, room and balance (charges less payments plus settled refunds, over every staged row naming the reservation, loaded or not) against the reservation’s own (its stays’ folios and rooms). Every disagreement is a named discrepancy: not_loaded, status_mismatch, dates_mismatch, balance_mismatch and room_mismatch block a cutover; aerandil_only (a booking at a house this connector feeds that the source never sent) is advisory. Only discrepant folios are listed; summary counts them all. ready_to_cut_over is no blocking discrepancy on an active connector.

Mapping-driven. The vendor side is read through the connector’s own mapping files — the pointers they declare, the loader’s coercion, the lifecycle their update variants dispatch — so it sees what the loader sees. blind_spots names, per provider, what the connector deliberately does not carry.

Live data: always Cache-Control: no-store.

connector_id
required
string format: uuid

The connector object’s id.

business_date
string format: date

The business date, YYYY-MM-DD. Defaults to today in the property’s timezone when the connector feeds one property, else today in UTC.

The shadow comparison.

Media typeapplication/json
object
as_of
required

When the comparison was read.

string format: date-time
blind_spots
required

What this provider’s feed cannot show, so the comparison cannot either (company accounts, pre-arrival deposits, refund legs, …) — the checks the house makes by hand.

Array<string>
business_date
required
string format: date
connector_business_id
required

The connector’s business id (CN-…): the source of its staged rows and the prefix of every external_ref it lands.

string
connector_id
required
string format: uuid
cut_over_at

When the house cut over from this source; absent while shadowing.

string | null format: date-time
day
required

The business date’s movement counts, computed identically both sides: arrivals and departures are non-cancelled reservations arriving / departing that day; in_house is reservations in house.

object
agree
required

Every count matches across the two sides.

boolean
arrivals
required
object
aerandil
required
integer
source
required
integer
departures
required
object
aerandil
required
integer
source
required
integer
in_house
required
object
aerandil
required
integer
source
required
integer
discrepancies
required

Every disagreement, named. Blocking: not_loaded (a pending, rejected or deferred row — detail carries the load error), status_mismatch, dates_mismatch, balance_mismatch, room_mismatch (an in-house reservation whose source room differs from its Aerandil stay’s). Advisory: aerandil_only (a non-cancelled reservation at a property this connector feeds that the source never sent).

Array<object>
object
detail
required
string
external_id
string | null
kind
required
string
Allowed values: not_loaded status_mismatch dates_mismatch balance_mismatch room_mismatch aerandil_only
reservation_id
string | null format: uuid
severity
required
string
Allowed values: blocking advisory
stream
string | null
folios
required

Only the folios with a discrepancy — one per reservation the source sent; summary carries the counts over all of them. The source balance is its charges less its payments over every staged row referencing the reservation, loaded or not; the Aerandil balance is the sum of the reservation’s stays’ folio balances.

Array<object>
object
aerandil
required
object
arrival_date
required
string | null format: date
balance
string | null format: decimal
currency
string | null
departure_date
required
string | null format: date
room

The room code of the reservation’s stay, when one is assigned.

string | null
rows_loaded
required
object
charges
required
integer
payments
required
integer
refunds
required
integer
status
required

The reservation’s status; null when it never loaded.

string | null
confirmation_number
string | null
discrepancies
required
Array<string>
Allowed values: not_loaded status_mismatch dates_mismatch balance_mismatch room_mismatch aerandil_only
external_id
required

The reservation’s id in the source PMS.

string
reservation_id

The Aerandil reservation; null when it never loaded.

string | null format: uuid
source
required
object
arrival_date
required
string | null format: date
balance
required
string format: decimal
charges
required
string format: decimal
currency
string | null
departure_date
required
string | null format: date
payments
required
string format: decimal
refunds
required
string format: decimal
room

The room code the source assigns, when its feed carries one.

string | null
rows
required
object
charges
required
integer
payments
required
integer
refunds
required
integer
status
required

The lifecycle the source row reads as through the mapping: confirmed, in_house, checked_out, cancelled or no_show.

string | null
variant

The mapping’s update variant the row matched (its own name), or null for a create-only row.

string | null
horizon
required

The business date and the nine days after it — the go-live check for overbookings in the next days: arrivals and departures both sides, per date, ascending.

Array<object>
object
agree
required
boolean
arrivals
required
object
aerandil
required
integer
source
required
integer
date
required
string format: date
departures
required
object
aerandil
required
integer
source
required
integer
provider
required
string
ready_to_cut_over
required

No blocking discrepancy and the connector is active.

boolean
rejects
required

The rejected rows, newest first, at most 200.

Array<object>
<= 200 items
object
error
required
string | null
external_id
required
string
mapping_ref
required
string | null
since
required

When the row was last tried and refused.

string format: date-time
stream
required
string
status
required

The connector’s lifecycle status.

string
Allowed values: active paused retired
streams
required

Per staged stream, its rows by load outcome. A staged row with no load outcome yet is pending.

Array<object>
object
deferred
required
integer
loaded
required
integer
mapping_ref
required

The connector’s mapping for the stream (name@version); null when it carries none.

string | null
pending
required
integer
rejected
required
integer
stream
required
string
summary
required
object
advisory
required
integer
blocking
required
integer
folios_agreeing
required
integer
folios_compared
required
integer
Example
{
"discrepancies": [
{
"kind": "not_loaded",
"severity": "blocking"
}
],
"folios": [
{
"discrepancies": [
"not_loaded"
]
}
],
"status": "active"
}
Cache-Control
string

Always no-store — live data.

Token lacks the analytics:read scope, or is a desk session bound to one property (a connector spans the houses it feeds).

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

No such connector.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

The connector’s mappings do not form a runnable pipeline (connector_pipeline_invalid) — the worker pauses such a connector; repoint it first.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

Malformed business_date.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}