Disaster Readiness API
For the dashboard flow (enable protection, Validate now, Activate as live, and how Disaster Ready is shown), start with Disaster Readiness.
These endpoints share the dashboard's account permissions and DR configuration services. They cover inventory, setup, isolated validation, status and activation admission—not proof of completed live recovery. Availability of an endpoint or successful preparation does not certify data recoverability. The feature remains subject to regional qualification. Availability of an API is not a completed product release.
All paths below use /api/public/v1. Account-wide calls require user
authentication, not environment tokens. Members only see permitted environments;
account admins configure protection. Internal roles do not bypass membership.
| Endpoint | OAuth scopes | MCP tool |
|---|---|---|
GET /disaster-readiness/sources | quave:read | list-disaster-readiness-sources |
GET /disaster-readiness/configurations | quave:read | list-disaster-readiness-configurations |
POST /disaster-readiness/configure | Both quave:write:config and quave:write:deploy | configure-disaster-readiness |
POST /disaster-readiness/validate | quave:write:deploy | validate-disaster-readiness-now |
POST /disaster-readiness/discard-activation | Both quave:write:deploy and quave:write:dangerous | discard-disaster-readiness-activation |
POST /disaster-readiness/reset | Both quave:write:deploy and quave:write:dangerous | reset-disaster-readiness |
MCP tool-mode keys must authorize the specific tool. Scope-mode keys must have all its required scopes; selecting an unrelated tool does not grant DR access.
Inventory and status
Both GET endpoints accept accountId, optional after, and limit (1–100,
default 50). Responses contain items and optional nextCursor; pass that cursor
as after for the next page.
Sources report volume eligibility, unsupported reasons, eligible destinations and
suggested settings. A protected source also reports target (appEnvId, appId,
appName, environmentName) once its target app env exists: the warm standby,
or the recovered environment after activation. Eligibility is not readiness. Configurations report safe
settings, generation, operation references and readiness evaluated at request time.
Unknown, expired or failed evidence must not be interpreted as Ready. Provider
credentials, signed URLs, private engine settings and execution leases are not
returned.
Bulk configuration
Review selection, destination, mode, schedules, costs and warnings before calling:
{
"accountId": "ACCOUNT_ID",
"common": {
"destinationRegion": "ELIGIBLE_REGION",
"mode": "cold"
},
"items": [
{
"sourceAppEnvId": "SOURCE_ENV_ID",
"requestId": "stable-request-reference",
"expectedGeneration": 0
}
]
}
Select 1–100 distinct environments. Each item may include overrides for common
settings. Supported settings are destinationRegion, mode (cold/warm),
storageCredentialId, snapshotIntervalMs, validationIntervalMs, rpoTargetMs,
rtoTargetMs, and sameRegionAcknowledged. Intervals/targets are milliseconds,
from one minute to 30 days; snapshot intervals must also map exactly to a supported
snapshot schedule. Omitted values use the dashboard defaults. Explicit null
storageCredentialId selects platform storage; omission inherits source storage.
Same-region protection requires explicit acknowledgment and remains limited.
Each item can include target with the recovered names: envName, plus
appName for databases (which always restore into a new app; other apps can set
createNewApp: true with an appName). Warm mode prepares the recovered
destination at setup, so warm items must include target. Cold items may include
it too: the names are saved and returned as plannedDestination in configuration
status, so activation can pre-fill them (activation still sends its own
target). Editing cold protection without target keeps the saved names.
{
"sourceAppEnvId": "SOURCE_ENV_ID",
"requestId": "stable-request-reference",
"target": { "envName": "recovered", "appName": "orders-db-recovered" }
}
The response is HTTP 200 with per-item results: sourceAppEnvId, success,
and either configurationId, operationId, generation, phase or a safe
error. Successful configuration queues asynchronous preparation and can incur
storage/transfer/compute costs. It does not mean the data is restored, Ready,
or live. Inspect each result and poll configuration status.
For edits, pass the current expectedGeneration. Reuse the same item
requestId and payload after an uncertain response; changing the payload under
the same reference is rejected. Retry failed items separately after correcting
the cause. Do not regenerate references simply because a response timed out.
This endpoint does not disable protection, promote a standby, reconnect apps,
change DNS, expose database credentials, or offer a dryRun parameter.
Validate now
An account administrator can request an isolated test of the configuration's retained data in its configured destination. Initial enrollment must have completed and no other recovery operation may be active.
{
"accountId": "ACCOUNT_ID",
"configurationId": "CONFIGURATION_ID",
"expectedGeneration": 2,
"requestId": "stable-validation-reference"
}
The response contains configurationId, operationId, generation and phase.
It confirms a journaled request, not restored data, cleanup completion or Disaster
Ready. Poll configuration status and the validation evidence for the outcome.
This can allocate temporary billable resources. It does not switch source traffic, start the customer's application, promote a live target, or reset the normal snapshot/validation cadence. Admission uses retained configuration and does not require contacting the source region.
Inactive validation bounds engine CPU/memory to the regional standby capacity without resizing its VM. Successful validation is not live compute proof: activation must separately complete and verify the owned VM's vertical resize and 50% baseline. A validation resource/startup failure remains a failed check.
After an uncertain reply, retry the exact same request ID and generation.
Authorization is checked again, but a committed operation is returned rather than
re-created. A changed generation or reused reference for another operation is
rejected. New requests use a fresh reference after refreshing status. Additional
execution fields, actor overrides and dryRun are not accepted.
Retained points and activation
Status may also include warmValidationOperationId for check-only eligibility.
A fully cleaned failed check can permit another isolated check while recovery
remains blocked. The server verifies retained cleanup and receiver ownership;
this hint is neither successful data validation nor Disaster Ready. New clients
prefer this hint for checks; the recovery hint remains separate. A historical
failed check no longer blocks recovery permanently after its cleanup is verified
and a later check succeeds for the protected point. A failed latest check,
pending operation, or unverifiable cleanup still blocks recovery; normal
activation evidence and custody checks remain mandatory.
Status may include warmRecoveryOperationId matching activeOperationId when
warm synchronization is settled and may be taken over for recovery. This is an
advisory action hint, not Disaster Ready evidence or permission. Activation checks
ownership, lease and pending effects again atomically; a new sync pass may make
the hint stale. For warm mode with an established validation schedule, this
same settled-owner hint also enables requesting another isolated check of the
protected point. Admission serializes it with append, resize and recovery; it
never permits concurrent effects. The original receiver stays activeOperationId
while the returned operationId identifies the individual check request. A fresh
request gets a fresh validation execution/history even for the same point; retrying
that request cannot replay an older check as new evidence. Manual checks preserve
both schedule timestamps. Scheduled checks advance from their due timestamp and
skip missed intervals rather than launching a catch-up batch. Neither admission
nor schedule initialization changes Disaster Ready status.
GET /disaster-readiness/points accepts accountId, configurationId, optional
after and limit (1–100). Requires read capability and account membership;
member environment restrictions still apply. Response includes generation,
items and nextCursor. Each item has selectedOperationId, pointId,
cutoffAt and availabilityRequiresVerification: true. These are candidates,
not proof that objects still exist or are readable. Pagination is not chronological.
For warm protection, the selectable item is the configuration-owned validated point
from the original receiver journal, which may be an incremental point rather than
the initial seed. Missing, ambiguous or mismatched custody yields no warm item;
an unfinished newer append is not substituted. This listing does not grant readiness.
When the operation's frozen source contract matches the protection contract,
retainedSizing exposes its replica count, optional zClouds, per-replica CPU
limits/requests (cpu, cpuRequest, in cores), memory limits/requests
(memoryMb, memoryRequestMb, in decimal MB), and volumeCapacities (Kubernetes quantities).
Missing or invalid sizing is omitted, not replaced with current source values or
defaults. No source-region contact is needed. This is a sizing preview, not a VM
reservation, full database topology specification or capacity qualification.
Do not submit this preview as activation resource overrides.
When a source engine cannot be activated as live yet, configuration status includes activationUnavailableReason: restore validation remains available, but new Activate-as-live requests are rejected before ownership or target changes. Do not treat Ready validation as native live-handoff support.
POST /disaster-readiness/activate requires account admin permission and both
quave:write:deploy and quave:write:dangerous capabilities. Send:
{
"accountId": "account-id",
"configurationId": "configuration-id",
"expectedGeneration": 2,
"requestId": "stable-activation-request-id",
"selectedOperationId": "operation-from-points-list",
"pointId": "<64-character-point-hash-from-points-list>",
"cutoffAt": "2026-09-11T10:00:00.000Z",
"target": {
"envName": "recovered",
"createNewApp": true,
"appName": "Recovered app"
},
"writerSafetyAcknowledged": true
}
Select an explicit point and explain its cutoff and possible data loss. Obtain explicit acknowledgment of double-writing risk if the source cannot be fenced; source unavailability does not itself prevent submitting the request. The server owns actor/audit identity and validates the retained configuration and point. Before allocation, the worker verifies retained objects and historical keys. It never silently substitutes another point. Billable resources may be allocated.
For warm protection, setup already created the recovered app and environment.
Configuration status returns their names as warmDestination
(envName, createNewApp, and appName when a new app was created). Send
exactly those names in target; different names are rejected before any work
starts. Cold activation chooses the names at activation time.
Retry the same payload and request ID after an uncertain response. A successful response is an operation journal receipt, not completed recovery. Poll configuration status and inspect operation evidence. This endpoint does not switch DNS or start the customer application. It has no dry-run parameter; use isolated validation for a check. Live ownership handoff and engine-specific recovery are still being qualified; do not treat API availability as a completed product release.
Discard an unfinished activation
An account administrator can discard an activation that has not become live, for example one stuck in progress or started with the wrong destination names. This is the API equivalent of the dashboard Discard action. An activation in progress blocks reset and new activations until it is discarded and cleaned up, except one that keeps failing before promotion (see below): Reset is allowed then.
POST /disaster-readiness/discard-activation requires account admin permission and
both quave:write:deploy and quave:write:dangerous capabilities. Internal roles
do not bypass account membership. Send:
{
"accountId": "ACCOUNT_ID",
"configurationId": "CONFIGURATION_ID",
"operationId": "ACTIVE_ACTIVATION_OPERATION_ID",
"expectedGeneration": 2,
"requestId": "stable-discard-request-id",
"discardAcknowledged": true
}
operationId is the configuration's activeOperationId while the activation is in
progress. discardAcknowledged must be the literal true and represents the user's
explicit acknowledgment that the unfinished recovery target will be discarded.
The server rejects the request when the activation already succeeded, is handing
over live ownership, or no longer matches the configuration generation. It also
rejects an activation that has not reached promotion yet (promoting or starting
phase), because its recovery target is still being prepared, unless a cold
activation keeps failing there: after 6 consecutive failed steps (about 15
minutes of retries) it can be discarded, which removes the recovery target it
created and returns the configuration to protection. A warm activation that keeps
failing before promotion is ended with Reset. Status reports
canRequestDiscard: true once a discard is accepted. Admission
moves the operation to cleanup and revokes the worker lease in one transaction; the
response is an operation journal receipt (operationId, configurationId,
generation, phase), not cleanup completion. Poll configuration status until
cleanup finishes before resetting or activating again. Retry the same payload and
request ID after an uncertain response. The live source and any target that
already became live are never touched. There is no dryRun parameter.
Completed data or native database activation
Configuration status may include activationResult after the atomic completion
of a generic cold activation or an accepted native PostgreSQL/Redis activation.
It contains only operationId, targetAppEnvId, targetAppId,
pointId, the selected cutoffAt, and completedAt, plus engine for a verified
native database completion (postgresql or redis). Generic-volume completion
omits engine. targetAppId is the recovered app. Clients can use it to show reconnection guidance rather than ask
users to deploy a database that recovery already started. This is a historical data
handoff receipt, not current workload health, traffic migration or renewed DR
readiness. Missing metadata is not inferred from a target ID or consumed protection.
For generic recovery, the recovered environment keeps its original persistent-volume roles. Configure the application image and secrets, address source-writer safety, then deploy explicitly and verify the application before reconnecting clients or changing DNS. Activate and validate new protection for the new live environment.
For native PostgreSQL/Redis recovery, completion requires database and public TLS
endpoint verification plus ownership handoff. The recovered environment exposes
the tested database endpoint (Redis uses rediss://); completion does not reconnect
application clients or prove their health. Reconnect and verify clients explicitly,
then establish new protection. Native recovery is still being qualified.
Temporary validation target cleanup
Configuration status may include activeOperation.validationCleanup while a
validation operation waits for temporary target retirement. It contains only
observedAt, an optional retentionUntil, and retentionPending. These are
advisory observations, not evidence of final deletion or Disaster Ready status.
A retention deadline is the earliest policy-permitted deletion time, not a
completion guarantee. Retained storage may continue to incur costs. Cleanup
continues automatically. Parking alone never releases ownership or recovery-point holds.
After verified removal of the isolated test data and compute, the server may atomically transfer cleanup to an independently leased obligation and release the configuration operation lock. A new explicit recovery uses a different target; old cleanup cannot modify it. Disk retention and held snapshot dependencies remain protected until their own verified completion.
Both configuration status and source inventory can include pendingCleanup,
independent of activeOperation and including earlier configuration generations:
pendingCount, retainedDiskCount, retryingCount, and optional
earliestRetentionUntil. Counts cover only the caller-authorized sources.
A retained-disk count is conservative; zero means provider cleanup was confirmed,
not that database/full-path validation succeeded. Pending validation acceptance
remains visible after resources are removed. The earliest retention deadline is
advisory, not a deletion promise. These fields never establish Disaster Ready.
Selected activation cutoff
During activation, activeOperation.cutoffAt is the canonical UTC timestamp of
its explicitly selected, pinned recovery point. activities[].cutoffAt records
that same cutoff on the activation's history entries, including after failure
or completion. These optional fields are omitted when unavailable or invalid;
clients must not replace a missing selected cutoff with a newer snapshot.
The dashboard displays them in browser-local date/time, separately from the
activity's execution time. The selected cutoff is not proof of Live completion.
Validation scheduling prerequisite
Configuration status includes validationScheduleEstablished. A false value
means initial setup has not yet established a valid validation schedule; clients
should explain this before offering a new Validate now request. true is not
proof of successful enrollment, permission to mutate, or Disaster Ready: admission
still checks the current successful enrollment, ownership and operation lock.
Preserve an unconfirmed request's idempotency reference when retrying it. Recovery
point selection has its own availability checks and is not gated by this flag.
Reset
An account administrator can wipe Disaster Readiness for one environment or the whole account and start over. This is for stuck or broken protection, not for turning off a healthy live recovered environment.
POST /disaster-readiness/reset requires account admin permission and both
quave:write:deploy and quave:write:dangerous capabilities. Send:
{
"accountId": "ACCOUNT_ID",
"scope": "environment",
"confirmationName": "exact-environment-name",
"sourceAppEnvId": "SOURCE_ENV_ID"
}
For the whole account, use "scope": "account" and the exact account name as
confirmationName. Do not send sourceAppEnvId on an account reset.
The server deletes Disaster Readiness configuration records and leftover recovery
destinations still owned by those settings. It does not delete the live source
or a destination that already became live. The response is the wipe counts
(configurations, destinations), not a new protection setup. There is no
dryRun parameter.
Reset first fences protection work and retires its exact owned compute, including allocations that have not created a recovery environment yet. While provider cleanup is pending, retry the same reset: configuration and operation records remain available instead of reporting a successful wipe. Compute cleanup retains data disks under their existing retention policy; it does not erase the source, independent live destinations, or other targets in the regional pool.
Recovery destination names
Activation requires target: { envName, createNewApp, appName }, using
the same destination rules as Snapshots → Create new environment. Every
activation sends envName. Database recovery and createNewApp: true require
appName and create a new app; application recovery uses the source app unless
createNewApp: true is selected. Names are trimmed. Omitting target is rejected.
The exact destination payload is part of the idempotency request: retry it
unchanged. App metadata is frozen at admission, but the app is created and the
recovered environment is named/reparented atomically only after verified Live
handoff. The destination remains in the same account. activationResult.targetAppId
identifies the recovered app on every current result.
The region, disk, compute, environment ID, runtime slug, database name, endpoints
and source data are not changed by the naming options. DR does not trigger an
ordinary snapshot restore or build/deploy, and source environment secrets and
hosts are not copied.
Snapshot cutoff semantics
Warm readiness cutoffs and RPO use retained destination evidence, not newer source snapshot notifications. When the source starts a new full backup chain, a warm standby must receive that full chain before it can follow new snapshots again; while the recovery point is past the RPO target for that reason, readiness.reason is chainRollover instead of rpoExceeded. The state stays needsAttention, and cutoffAt/recoveryPointAgeMs still report the real gap. Likewise, while a warm standby is visibly applying a large source change (for example a table rebuild that produced a multi-GB incremental), readiness.reason is catchingUp instead of rpoExceeded, with the same needsAttention state and real gap. Both reasons fall back to rpoExceeded 12 hours past the target, or when the standby stops making progress. A warm point is selectable only when it matches current protected custody, including increments in an active replacement stream. Listing a candidate still does not replace activation-time verification.
Warm standby shape
A warm configuration reports standby with the inactive shape its standby runs on and why:
shape: "standard": the default standby (1/8 CPU baseline).shape: "seedBoost",reason: "catchingUp": a temporary larger standby for a large first copy. It stays until the standby has applied the first copy, the changes that arrived meanwhile, and two consecutive changes well inside the snapshot interval.shape: "sustained",reason: "standardTooSlow": recent changes took more than a third of the snapshot interval to apply on the default standby, so the standby keeps a full CPU baseline (higher standby cost). It returns to standard only after a sustained quiet period.
caughtUp, lastApplySeconds and lastApplyBytes show the latest measurements. readiness.warnings includes sustainedStandby or seedBoost while one of those shapes is in use. A shape change restarts the standby VM between changes; none of these shapes is the live shape.
The dashboard additionally offers cold Choose snapshot to recover, backed by the existing environment snapshot catalog and exact-point isolated validation. This UI workflow does not change the public activation request shape or bypass engine support. After validation, its retained operation/point/cutoff can be selected through the existing activation contract. UI timestamps are browser-local; API timestamps remain canonical UTC.
After a verified native PostgreSQL handoff, the normal replica collector registers the existing ready runtime in the ordinary environment history. The environment then shows Running, actual replicas and CPU/memory metrics; Live on the DR card remains the historical activation result. Registration does not rebuild, restart, copy or replace the retained warm disk. Existing completed PostgreSQL handoffs are reconciled the same way. A handoff receipt alone never creates a Running status, and later failed/unready replicas remain visible through normal runtime telemetry. Client reconnection is still a separate action.
The environment does not use a recovery-specific Live runtime status. Its Running/Stopped state and replicas come from the ordinary environment records; the DR card keeps the historical activation outcome. Native PostgreSQL recovery also uses the regular database status/host reconciliation, including internal connection hosts. No restart or second restore is needed to register them.
Cold recovery and Create environment from recovery point share snapshot-chain selection, restore-package materialization and recovery destination creation. DR adds pinned-point, lease, placement and ownership checks around that core. Warm activation keeps its existing disk rather than invoking restore-on-deploy again.