Backups
A zip of your content as data files, with credentials and personal fields left out.
5 min read
What a backup is
A backup is a single zip file with the content of one brand. It is made for safekeeping and for moving data around, so you can keep a copy outside ATLAS and download it whenever you need it.
Everything on this page is for admins. All calls are under https://api.atlascms.id/v1/manage and need a signed in session and the X-Brand-Id header.
There is no restore button
ATLAS does not restore a brand from a brand backup through the API or the dashboard. The archive is a readable copy of your data, not a one click rollback. To undo a mistake in content, use revisions and rollback on the entry. To recover a whole install, talk to the person who operates your ATLAS server, who has platform level database backups.
What is inside
| File | Content |
|---|---|
manifest.json | schema_version, atlas_version, brand, created_at, target, counts per table, exclusions and media_count. |
{table}.jsonl | One file per brand owned table (entries, revisions, terms, menus, settings, forms and so on), one JSON object per line. Soft deleted rows are included with deleted_at. |
entry_term.jsonl | The link between entries and terms, only for entries of this brand. |
media.jsonl | The list of your media files. The files themselves are not in the zip. |
Media files stay in your media storage. The archive lists them so you know what belongs to the brand.
What is left out
Backups never contain secrets or personal data:
- Anything stored encrypted or hashed, such as integration secrets, API token hashes, webhook secrets and invitation token hashes.
- Mail connection username, host and password.
- Personal fields of leads: submitted fields, UTM values, click ids, note, source page, referrer, IP hash, user agent, error and assignee.
manifest.json lists every excluded column per table, so you can check exactly what is missing.
Start a backup
/v1/manage/backupsQueues a backup and answers 202 with the run. You can start up to 10 a minute. While another backup is pending or running (and younger than 2 hours) the answer is 409 with "code": "backup_in_progress".
curl -s -X POST "https://api.atlascms.id/v1/manage/backups" \
-H "X-Brand-Id: $BRAND_ID" --cookie "$SESSION"{ "data": { "id": "01m5300000000000000000000b", "kind": "backup", "status": "pending",
"file_name": null, "file_size": null, "download": null, "created_at": "2026-10-21T14:42:20+00:00" } }The status moves from pending to running and then completed or failed. Progress is broadcast on brand.{id}.tools. A failed run carries a short error reason.
GET /v1/manage/backups lists the runs, 20 per page, newest first. GET /v1/manage/backups/{toolRun} shows one. A run id from another brand is a 404.
Download
A completed run carries a download object with a signed URL and its expires_at. The link lasts 5 minutes, and every read of the run mints a new one.
curl -s "https://api.atlascms.id/v1/manage/backups/$RUN_ID" \
-H "X-Brand-Id: $BRAND_ID" --cookie "$SESSION" \
| jq -r '.data.download.url' \
| xargs curl -s -o backup.zipThe download endpoint is GET /v1/backups/{id}/download. An unsigned or expired link is 403, a brand that is suspended is 403, and a backup that is no longer available is 410. Downloads are limited to 30 a minute and every download is written to the audit log.
Only the link expires. The archive stays until retention or you delete it with DELETE /v1/manage/backups/{toolRun} (204, which also removes the file).
Settings
GET /v1/manage/backups/settings and PUT /v1/manage/backups/settings read and change the schedule, retention and destination. Before the first save you get the defaults: schedule off, 02:00, keep the last 5, keep 30 days, target shared.
| Setting | Description |
|---|---|
schedule | off, daily or weekly. Weekly runs on Monday. |
run_at | HH:MM (00:00 to 23:59) in the brand's timezone. A run starts at or after this time. |
keep_last | Keep the newest N completed backups (1 to 100). |
keep_days | Remove backups older than N days (1 to 3650). |
target | shared, brand_storage or s3. |
endpoint, region, bucket, prefix, path_style | For s3. The endpoint must be a public HTTPS address on port 443. The prefix allows letters, digits, ., _, - and /. |
access_key_id, secret_access_key | For s3. Write only. |
{
"schedule": "daily",
"run_at": "02:30",
"keep_last": 7,
"keep_days": 30,
"target": "s3",
"endpoint": "https://s3.example.com",
"region": "auto",
"bucket": "my-atlas-backups",
"prefix": "atlas",
"path_style": true,
"access_key_id": "AKIA...",
"secret_access_key": "..."
}The response repeats the settings with has_access_key and has_secret flags. The keys themselves are never returned.
Where the file goes
| Target | Stored in |
|---|---|
shared | The platform media storage, under tools/{brand_id}/backups/. This is the default. |
brand_storage | The brand's own media storage configuration. The run fails with backup_failed if the brand has none. |
s3 | Your own bucket, at {prefix}/tools/{brand_id}/backups/{run}.zip. Keeping a copy in a bucket you control is the safest option. |
Each run remembers where it was written. If you change the target or bucket later, old backups can still be downloaded and deleted from where they are.
Test before you rely on it
POST /v1/manage/backups/settings/test (6 a minute) checks a destination without saving. Send the same fields as the settings, or leave them out to test the saved ones. The answer is { "data": { "ok", "reason", "at" } }. When ok is false, reason is one of credentials_missing, bucket_missing, storage_not_configured, endpoint_refused, auth_failed, bucket_not_found or unreachable.
Schedule and retention
The scheduler checks every minute. For each brand it starts at most one backup per window:
dailyruns once a day afterrun_at,weeklyonce a week after Mondayrun_at.- A brand with a pending, running, completed or failed backup in the current window is skipped.
- A run stuck for over 2 hours is marked
failedwith reasonstale. A failed run is retried at least an hour later, up to 3 failed attempts per window. - Retention runs after each successful backup and once a day.
keep_daysremoves completed and failed runs older than the limit,keep_lastkeeps the newest completed runs. Running and pending runs are never removed.
Size and timing
A backup streams each table through a temporary file and uploads the zip as a stream, so memory use stays flat even for large brands. Runs go to the long imports queue with a timeout of one hour. Because media files are not inside the zip, the size follows your text content, revisions and settings, not your image library. A large brand with years of revisions can still take a few minutes, so wait for completed before you download.
Security
- Only admins can start, list, download, change settings or delete. Editors and publishers get 403.
- Download links are signed and last 5 minutes.
- S3 credentials are encrypted, write only and never appear in a response, a log or an audit row. Audit rows (
backup.started,backup.downloaded,backup.deleted,backup.settings.updated) hold ids and setting names, never values. - Outbound calls to your bucket use the same guard as media storage: HTTPS, port 443, public addresses only.
- Treat the zip as sensitive. It holds all your content and the email addresses of pending invitations.
Was this page helpful?