API

Backups and restores

Create backup policies, inspect runs, and restore data.

The Backups API manages a project's backup policies (what to back up and on what schedule), the runs they produce, and the restores that put a run's data back. It pairs with the Backup Destinations API (where backups are stored) — in the dashboard this is the project's Backups tab, and from the terminal it's the openship backup command.

The routes are split across a few prefixes: policy creation and listing are project-scoped (/api/projects/:projectId/backup-policies), while an existing policy, run, or restore is addressed by its own id (/api/backup-policies/:id, /api/backup-runs/:id, /api/backup-restores/:id). The inbound POST /api/webhooks/backup trigger lives on its own unauthenticated prefix. Available on both self-hosted and cloud instances; the project-scoped policy and run routes proxy to Openship Cloud for cloud projects.

Create a backup policy

A policy binds a project (optionally a single service) to a destination, plus an optional schedule and retention rules. The request body is read inline (there is no TypeBox schema file for this module); destinationId is the only required field.

const result = await ship.backups.createPolicy("proj_123", {
  destinationId: "dst_abc",
  cronExpression: "0 3 * * *",
  retainCount: 7,
});
console.log(result);
curl -X POST "$OPENSHIP_URL/api/projects/proj_123/backup-policies" \
  -H "Authorization: Bearer $OPENSHIP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"destinationId":"dst_abc","cronExpression":"0 3 * * *","retainCount":7}'

Prop

Type

Update a policy

PATCH accepts only the allow-listed fields below — projectId, serviceId, and createdBy cannot be changed, and the webhook token is controlled through the enableWebhook / rotateWebhookToken flags rather than written directly. Unknown fields are dropped.

PATCH /api/backup-policies/:policyId

Prop

Type

Trigger a backup manually

const run = await ship.backups.run("policy_123");
console.log(run);
curl -X POST "$OPENSHIP_URL/api/backup-policies/policy_123/run" \
  -H "Authorization: Bearer $OPENSHIP_TOKEN"

Kicks off a run for the policy immediately. Returns { data: { runId } } — follow it with the run stream.

const result = await ship.backups.run("bkp_abc");
console.log(result);
curl -X POST "$OPENSHIP_URL/api/backup-policies/bkp_abc/run" \
  -H "Authorization: Bearer $OPENSHIP_TOKEN"

Protect a run from retention

Retention prune drops runs past a policy's retainCount / retainDays. Lock a run to keep it, or release the lock so it becomes eligible again.

POST /api/backup-runs/:runId/protect

Prop

Type

Stage and apply a restore

Restoring is two steps. Prepare stages the restore and returns a one-time confirmationToken; apply echoes that token back to actually run the (destructive) restore. This guards against accidental re-submits.

POST /api/backup-runs/:runId/restore/prepare

Prop

Type

The response is { data: { restoreId, confirmationToken } }. Pass both to apply:

POST /api/backup-restores/:restoreId/apply

Prop

Type

Cancel a staged or in-flight restore with POST /api/backup-restores/:restoreId/cancel (openship backup restore cancel rst_123).

Live progress (SSE)

Both runs and restores expose a Server-Sent Events channel that emits a snapshot event with the current row immediately, then live transition / progress events, and a final complete event. Terminal statuses are succeeded, failed, cancelled, and server_error; the stream closes once one is reached (or right away if the row is already terminal).

GET /api/backup-runs/:runId/stream
GET /api/backup-restores/:restoreId/stream

Trigger a backup by webhook

POST /api/webhooks/backup is the one unauthenticated route — the per-policy webhook token is the credential, sent as a bearer header (enable it via enableWebhook on the policy). There is no request body. On success it returns { data: { runId } }; every failure returns an opaque 404 so a probe can't tell a bad token from a disabled policy. The route is rate-limited to blunt trigger-flood abuse.

POST /api/webhooks/backup
curl -X POST "$OPENSHIP_URL/api/webhooks/backup" \
  -H "Authorization: Bearer $POLICY_WEBHOOK_TOKEN"

Errors

400 — invalid cron expression

createPolicy / updatePolicy validate the cron up front so an unparseable schedule can't silently disable the policy. Fix the expression (e.g. 0 3 * * *) and retry.

400 — confirmationToken is required

Applying a restore without the exact token returned by restore/prepare is rejected. Re-run prepare to get a fresh token if you've lost it.

404 on a per-resource route

The :id doesn't belong to your organization (or was deleted) — the same opaque 404 the webhook returns for a bad token. List runs with GET /api/projects/:projectId/backup-runs to get valid IDs.

Operations

OperationSDKREST API
Stream backup execution progress.backups.streamRun(id, options?)GET /api/backup-runs/:runId/stream
backup_destination:backup_run:read
Stream restore progress.backups.streamRestore(id, options?)GET /api/backup-restores/:restoreId/stream
backup_destination:backup_restore:read
List backup policies for the requested source.backups.listPolicies(id)GET /api/projects/:projectId/backup-policies
project:write
Create a backup policy and retention configuration.backups.createPolicy(id, input)POST /api/projects/:projectId/backup-policies
project:write
List recorded backup runs using typed filters.backups.listRuns(id, input?)GET /api/projects/:projectId/backup-runs
project:write
Change a backup policy.backups.updatePolicy(id, input)PATCH /api/backup-policies/:policyId
backup_destination:backup_policy:write
Remove a backup policy.backups.removePolicy(id)DELETE /api/backup-policies/:policyId
backup_destination:backup_policy:write
Trigger a policy’s backup now.backups.run(id, input?)POST /api/backup-policies/:policyId/run
backup_destination:backup_policy:write
Read a backup run and its result.backups.getRun(id)GET /api/backup-runs/:runId
backup_destination:backup_run:read
Protect or unprotect a run from retention pruning.backups.protectRun(id, input?)POST /api/backup-runs/:runId/protect
backup_destination:backup_run:write
Stage and validate a restore without applying it.backups.prepareRestore(id, input?)POST /api/backup-runs/:runId/restore/prepare
backup_destination:backup_run:admin
Read a restore session and its confirmation requirements.backups.getRestore(id)GET /api/backup-restores/:restoreId
backup_destination:backup_restore:read
Apply a prepared restore using the required confirmation.backups.applyRestore(id, input)POST /api/backup-restores/:restoreId/apply
backup_destination:backup_restore:admin
Request cancellation of a restore.backups.cancelRestore(id)POST /api/backup-restores/:restoreId/cancel
backup_destination:backup_restore:admin

On this page