API

Backups API

Schedule backup policies, run and inspect backups, stage and apply restores, and trigger backups by webhook.

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.

Base path & auth

All paths are relative to your instance, under /api — e.g. https://your-host/api/backup-runs/<id>. Send a personal access token as a bearer header (Authorization: Bearer <token>), created with openship token create. The dashboard uses your session cookie instead. See the API overview for the full auth model.

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.

Endpoints

Method & pathPermissionWhat it does
GET /api/projects/:projectId/backup-policiesproject:writeList a project's backup policies (schedules/retention).
POST /api/projects/:projectId/backup-policiesproject:writeCreate a backup policy for a project.
PATCH /api/backup-policies/:policyIdbackup_destination:backup_policy:writeUpdate a policy.
DELETE /api/backup-policies/:policyIdbackup_destination:backup_policy:writeDelete a policy.
POST /api/backup-policies/:policyId/runbackup_destination:backup_policy:writeTrigger the policy's backup now.
GET /api/projects/:projectId/backup-runsproject:writeList a project's backup runs (history, status).
GET /api/backup-runs/:runIdbackup_destination:backup_run:readGet one backup run's details/status.
GET /api/backup-runs/:runId/streambackup_destination:backup_run:readSSE stream of a run's live progress.
POST /api/backup-runs/:runId/protectbackup_destination:backup_run:writeProtect a run from retention pruning (or release it).
POST /api/backup-runs/:runId/restore/preparebackup_destination:backup_run:writeStage a restore from a run; returns a confirmation token.
POST /api/backup-restores/:restoreId/applybackup_destination:backup_restore:writeApply a staged restore (destructive).
POST /api/backup-restores/:restoreId/cancelbackup_destination:backup_restore:writeCancel a staged or in-flight restore.
GET /api/backup-restores/:restoreIdbackup_destination:backup_restore:readGet one restore's status.
GET /api/backup-restores/:restoreId/streambackup_destination:backup_restore:readSSE stream of a restore's live progress.
POST /api/webhooks/backuppublicTrigger a backup from an inbound webhook (bearer token is the credential).

Per-resource routes run a second permission check

Beyond the permission tag shown above, most :id routes run an in-handler check too. The policy update, delete, and manual-run routes re-check the parent project (write to update or run, admin to delete). Run and restore routes instead check the run or restore itself: read to view or stream, write to protect a run, and admin for every destructive restore step (prepare, apply, cancel). A :id that isn't in your organization returns 404.

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.

POST /api/projects/:projectId/backup-policies

Prop

Type

curl -X POST https://your-host/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}'
# Same thing from the CLI:
openship backup policy create --project proj_123 --destination dst_abc \
  --cron "0 3 * * *" --retain-count 7

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

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

POST /api/backup-policies/:policyId/run
curl -X POST https://your-host/api/backup-policies/bkp_abc/run \
  -H "Authorization: Bearer $OPENSHIP_TOKEN"
# Trigger and stream to completion:
openship backup policy run bkp_abc --follow

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

# Lock indefinitely, or release it:
openship backup run protect run_xyz
openship backup run protect run_xyz --release

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

# Prepare, then apply with the returned token:
openship backup run restore run_xyz
openship backup restore apply rst_123 --token <confirmationToken>

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
# The CLI's --follow flag consumes these streams:
openship backup run get run_xyz --follow
openship backup restore get rst_123 --follow

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 https://your-host/api/webhooks/backup \
  -H "Authorization: Bearer $POLICY_WEBHOOK_TOKEN"

Errors you might see

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.

On this page