Skip to content

Cut a house over from its source PMS

POST
/v1/switchover/{connector_id}/cut-over
curl --request POST \
--url https://api.aerandil.com/v1/switchover/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/cut-over \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "channel_connection_ids": [ "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" ], "reason": "example" }'

The switchover’s decision: stop treating the connector’s source PMS as the system of record. Refused unless it is safe: the route first reads the shadow comparison (GET /v1/analytics/switchover-shadow) and answers 409 cutover_blocked — the counts in the message, the blocking discrepancies (at most 50) and the summary in parameters — while anything blocks; it never asks the caller to underwrite an unsafe cutover. A connector already cut over answers 409 already_cut_over (with its cut_over_at), a retired one 409 connector_retired, any other not active one 409 connector_not_active.

Then, in one transaction (cut_over_connector): the connector is paused with a reason naming the decision and stamped cut_over_at / cut_over_by / cut_over_summary (the pre-flight it was taken on), and each named channel conduit is brought live (paused → active; a conduit pending mapping, suspended, closed or unmapped refuses the whole gesture, 422, before anything is written). In-house guests are never re-keyed.

Then each conduit is published in full: a full channel_publication_run over today to the conduit’s horizon, its cells seeded so the dispatcher sends the whole of the house’s availability, rates and restrictions — clearing closures the partner still holds from the old PMS. A conduit the partner’s 24-hour floor refuses is reported skipped (the cutover stands; publish later), one that fails failed.

Needs the catch-all actions:apply or the route’s own grant; not from a desk bound to one property. Accepts an Idempotency-Key. Live data: Cache-Control: no-store.

connector_id
required
string format: uuid

The connector object’s id.

Idempotency-Key
string
>= 1 characters

Opaque idempotency token (Stripe-shape). Repeated POSTs with the same key replay the original response within the cache TTL rather than creating a duplicate object.

Media typeapplication/json
object
channel_connection_ids

The channel conduits to bring live with the cutover: each mapped and paused (or already active).

Array<string>
reason

Why, recorded on the connector.

string
Examplegenerated
{
"channel_connection_ids": [
"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"
],
"reason": "example"
}

Cut over; each conduit’s full publication reported.

Media typeapplication/json
object
conduits
required
Array<object>
object
cells_seeded
required

Outbox cells the horizon seed wrote.

integer format: int64
full_publication
required
string
Allowed values: started skipped failed
id
required
string format: uuid
note

Why a publication was skipped or failed.

string
publication_run_id

The full channel_publication_run opened.

string format: uuid
connector_business_id
required
string
connector_id
required
string format: uuid
cut_over_at
required
string format: date-time
cut_over_by
required
string
idempotent_replay

Present (true) when an Idempotency-Key replay answered.

boolean
preflight
required

The shadow comparison the decision was taken on, as recorded on the connector.

object
as_of
required
string format: date-time
business_date
required
string format: date
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
status
required
string
Allowed values: paused
Example
{
"conduits": [
{
"full_publication": "started"
}
],
"status": "paused"
}
Cache-Control
string

Always no-store. Object and link state is live data and is never cacheable.

Token lacks actions:apply and the route’s own grant, or is a desk session bound to one property.

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, or no such channel conduit.

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 cutover is refused: cutover_blocked (the shadow comparison has blocking discrepancies — parameters.blocking, parameters.by_kind, parameters.summary), already_cut_over, connector_retired, connector_not_active, connector_pipeline_invalid, or an Idempotency-Key still in flight.

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 body, or a named conduit cannot be brought live (pending mapping, suspended, closed or unmapped).

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"
}
}