API Reference
Backups

Backups

List an environment's backups, look one up, obtain presigned download URLs for the database dump, filestore archive, and manifest, and restore a backup into its environment, all over your API key.

Base URL: https://api.oec.sh/api/public/v1


Backup Status Values

StatusMeaning
pendingQueued, has not started yet.
runningBackup is being created.
completedBackup finished and download URLs can be issued.
failedBackup failed (see error_message on the backup object).
cancelledBackup was cancelled.

Only completed backups can be downloaded or restored.


Backup Type Values

TypeMeaning
manualTriggered on demand from the dashboard or an admin action.
scheduledCreated by the environment's backup policy.
pre_deploySnapshot taken automatically before a deployment.

List Backups for an Environment

GET /environments/{env_id}/backups

Returns the environment's backups in reverse-chronological order.

Path Parameters

ParameterTypeDescription
env_idUUIDThe environment ID.

Query Parameters

ParameterTypeDescription
statusstringFilter by status (pending, running, completed, failed, cancelled).
backup_typestringFilter by type (manual, scheduled, pre_deploy).
pageintegerPage number, starts at 1. Default: 1.
page_sizeintegerResults per page. Min 1, max 100. Default: 20.

Response — 200 OK

{
  "items": [
    {
      "id": "9c2ad33c-7e5d-4d23-8f8c-9c3c5dc6c1f1",
      "environment_id": "5a296461-9222-40da-91f5-9e912890dc1b",
      "status": "completed",
      "backup_type": "scheduled",
      "database_size": 432198144,
      "filestore_size": 211345920,
      "total_size": 643544064,
      "compressed_size": 218657280,
      "started_at": "2026-05-22T18:00:00Z",
      "completed_at": "2026-05-22T18:04:32Z",
      "duration_seconds": 272,
      "expires_at": "2026-06-21T18:04:32Z",
      "is_verified": true,
      "verified_at": "2026-05-22T18:05:01Z",
      "notes": null,
      "created_at": "2026-05-22T18:00:00Z"
    }
  ],
  "total": 31,
  "page": 1,
  "page_size": 20,
  "total_pages": 2
}

Example

# All completed backups for an environment
curl "https://api.oec.sh/api/public/v1/environments/YOUR_ENV_ID/backups?status=completed" \
  -H "Authorization: Bearer YOUR_API_KEY"

Get Download URLs

GET /backups/{backup_id}/download

Returns presigned URLs for the database dump, filestore archive, and manifest. The backup must be in completed status.

URLs are time-limited. Choose a TTL between 5 minutes and 24 hours via the expires_in parameter. Treat the URLs as one-time tokens — anyone with the URL can download the file until it expires.

Path Parameters

ParameterTypeDescription
backup_idUUIDThe backup ID.

Query Parameters

ParameterTypeDescription
expires_inintegerURL validity in seconds. Min 300 (5 minutes), max 86400 (24 hours). Default: 3600 (1 hour).

Response — 200 OK

{
  "backup_id": "9c2ad33c-7e5d-4d23-8f8c-9c3c5dc6c1f1",
  "database_url": "https://storage.example.com/.../dump.sql?X-Amz-Signature=...",
  "filestore_url": "https://storage.example.com/.../filestore.tar.gz?X-Amz-Signature=...",
  "manifest_url": "https://storage.example.com/.../manifest.json?X-Amz-Signature=...",
  "expires_in": 3600,
  "expires_at": "2026-05-23T03:45:55Z",
  "use_streaming": false
}

When use_streaming is true, the storage provider cannot issue presigned URLs directly (e.g. some GCP configurations); the URLs returned will stream through the platform instead.

Errors

StatusReason
400Backup is not in completed status, so no downloadable files exist yet.
404Backup not found, or the API key's scope does not cover this backup's organization or project.

Example

# Get URLs valid for 24 hours
curl "https://api.oec.sh/api/public/v1/backups/YOUR_BACKUP_ID/download?expires_in=86400" \
  -H "Authorization: Bearer YOUR_API_KEY"
 
# Then download with the returned URL (no auth header needed — the URL is presigned)
curl -o dump.sql "<database_url from response>"

Get a Backup

GET /backups/{backup_id}

Returns one backup, in the same shape as an item of the backup list. Works with a read-only key.

Path Parameters

ParameterTypeDescription
backup_idUUIDThe backup ID.

Response: 200 OK

The same object as one entry of items in List Backups for an Environment.

Errors

StatusReason
404Backup not found, or the API key's scope does not cover this backup's organization or project.

Example

curl "https://api.oec.sh/api/public/v1/backups/YOUR_BACKUP_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

Restore a Backup

POST /backups/{backup_id}/restore

Restores a completed backup into the environment it was taken from. Requires a full-access key.

⚠️

A restore overwrites the environment's current database and files with the contents of the backup. Anything written since the backup was taken is replaced. To confirm, send the header X-Confirm-Restore: true; without it the request is refused with 400.

What happens:

  • A safety backup of the environment's current data is taken first whenever the environment has data to back up, so the restore can be undone by restoring that backup. If the safety backup fails, the restore is aborted and the environment's data is left unchanged. (The failure message may mention skipping the safety backup; only the dashboard offers that.)
  • The database and the filestore are both restored. The environment restarts during the restore.
  • The restore runs in the background. Poll poll_url (the same task endpoint as actions) until it reaches a final status.

Only the backup's own environment can be the target. To restore into another environment, a new environment or another server, use the dashboard.

The environment must be running, stopped, paused or error (restoring a backup is a way to recover an environment in error).

Path Parameters

ParameterTypeDescription
backup_idUUIDThe backup to restore.

Headers

HeaderRequiredDescription
X-Confirm-RestoreYesMust be exactly true.
Idempotency-KeyNoUnique string to deduplicate retries. A retry with the same key within 24 hours returns the first response instead of starting a second restore. A retry sent while the first request is still being processed gets 409 concurrent_action; retry after a few seconds to receive the first response.

Response: 202 Accepted

{
  "task_id": "a1b2c3d4-...",
  "status": "queued",
  "environment_id": "5a296461-9222-40da-91f5-9e912890dc1b",
  "backup_id": "9c2ad33c-7e5d-4d23-8f8c-9c3c5dc6c1f1",
  "poll_url": "/api/public/v1/deployments/a1b2c3d4-..."
}

Errors

StatusError codeReason
400confirm_requiredThe X-Confirm-Restore: true header is missing.
400backup_not_completedThe backup is not in completed status.
400backup_files_missingThe backup's files are no longer in storage.
400restore_refusedThe restore was refused; the message says why.
402The organization's subscription is blocked.
403read_only_keyThe API key is read-only.
404not_foundBackup not found, or the API key's scope does not cover this backup's organization or project.
409environment_deletedThe environment the backup was taken from has been deleted.
409environment_not_restorableThe environment is being deployed or cloned, was never deployed, or has no server.
409concurrent_actionAnother action was queued for this environment in the last few seconds, or a retry arrived while the first request with the same Idempotency-Key was still being processed. Retry shortly.
409task_in_progressAnother task is queued or running for this environment; task_id names it.
409restore_in_progressA restore of this environment is already running.
503enqueue_failedThe restore could not be queued. Retry after the Retry-After delay.

Example

# Generate the key once and reuse it for every retry of this restore.
KEY=$(uuidgen)
 
curl -X POST "https://api.oec.sh/api/public/v1/backups/YOUR_BACKUP_ID/restore" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Confirm-Restore: true" \
  -H "Idempotency-Key: $KEY"

Common Pattern: Latest Backup for an Environment

# 1. Find the most recent completed backup
BACKUP_ID=$(curl -s "https://api.oec.sh/api/public/v1/environments/YOUR_ENV_ID/backups?status=completed&page_size=1" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  | jq -r '.items[0].id')
 
# 2. Get download URLs
curl "https://api.oec.sh/api/public/v1/backups/$BACKUP_ID/download?expires_in=3600" \
  -H "Authorization: Bearer YOUR_API_KEY"