apibackuper
A command-line tool to archive and backup REST APIs
Version: 2.0.0
This README describes version 2.0.0. See the changelog for release details and migration notes.
apibackuper downloads paginated REST APIs into local storage and exports the archive as JSON Lines, gzip, zstd, or Parquet. It is designed for repeatable, long-running backups rather than one-off HTTP requests.
Features
- GET and POST iterative APIs (page, skip/offset, or range pagination)
- Full, incremental, and update work modes, with resume from checkpoints
- ZIP, filesystem, or SQLite storage
- Export to JSON Lines, gzip, Zstandard, or Parquet
- YAML configuration (INI still loaded, but deprecated)
- Authentication: Basic, Bearer, API Key, OAuth2
- Rate limiting, retries, concurrency, and SSL controls
- Follow-up requests for related objects and associated file downloads
- Optional Python hooks for custom pipeline steps
Documentation
The full documentation site (Docusaurus) lives in docs/ and is
published at ruarxive.org/apibackuper.
| Section | What it covers |
|---|---|
| Getting started | Install, quick start, positioning |
| Cookbook | Task index by goal |
| CLI reference | Every command |
| Configuration | YAML sections and field reference |
| Examples | Working projects and templates |
| Troubleshooting | SSL, pagination, rate limits |
Source pages: docs/docs/. Changelog: CHANGELOG.md.
Installation
Using pip
pip install --upgrade pip setuptools
pip install apibackuper
Using pipx or uv
pipx install apibackuper
# or
uv tool install apibackuper
Parquet export and aria2 downloads:
pip install "apibackuper[recommended]"
Requirements
- Python 3.10 or greater
Install from source
python -m pip install --upgrade pip setuptools wheel
python -m pip install .
Quick start
apibackuper create etrust
cd etrust
# save apibackuper.yaml with your API settings (and params.json for POST APIs)
apibackuper validate-config
apibackuper run full --dry-run
apibackuper estimate full
apibackuper run full
apibackuper export etrust.jsonl
A worked POST API example is in the
quick start.
Starter YAML files are in examples/templates/.
create currently writes a minimal apibackuper.cfg; save your complete
configuration as apibackuper.yaml, which takes precedence over that INI file.
The API-related create flags are accepted for compatibility but do not populate
the configuration. Follow the create reference.
Commands
apibackuper create <name>
apibackuper detect [--url URL] [--write-config]
apibackuper estimate full
apibackuper run full [--resume]
apibackuper run continue
apibackuper update [--resume]
apibackuper follow full|continue
apibackuper getfiles
apibackuper export output.jsonl
apibackuper info [--json]
apibackuper validate-config
run full --dry-run (alias --profile), update --dry-run, and
follow full --dry-run print a JSON plan without making HTTP requests.
estimate full contacts the API to measure a sample response.
getfiles currently reads ZIP backups. Its downloaded files can be stored in
ZIP or filesystem storage; see file configuration.
apibackuper --help
apibackuper run --help
Backup safety and recovery
A fresh apibackuper run full writes to a staging path ending in .partial
(for example, storage.zip.partial). It replaces the previous complete archive
only after every required page has been saved successfully. A failed full backup
keeps the previous archive and retains its staging data and checkpoint for recovery:
apibackuper run full --resume
Resume reuses saved pages and starts at the first unresolved page. Checkpoints advance only through pages that have been saved durably. Failed or incomplete backup runs exit with a nonzero status and preserve the last successful backup state, so an update cannot advance its timestamp or change key past missing data.
Each apibackuper update retains its pages under a unique
runs/<id>/page_N.json generation. Use apibackuper update --resume to continue an
interrupted update within the same generation. Export reads the original pages
and every retained generation: it represents the retained archive history, and
does not deduplicate objects into a current snapshot. An object returned in several
updates can therefore appear several times in the export.
Existing archives with flat page_N.json members remain readable. Legacy
checkpoints without next_page are also accepted; resume safely replays their
last recorded page.
For ZIP storage, saved pages may also live in a .journal sidecar directory
until they are compacted into the archive. Keep storage.zip.partial.journal
beside storage.zip.partial, or storage.zip.journal beside storage.zip,
along with the checkpoint and state files, until recovery is complete. Resume
can finish an interrupted publication from saved data without downloading again.
run continue (alias run incremental) fills pages from the first missing
page in the published archive. To recover a staged full backup, use
run full --resume. See the recovery guide.
Contributing
See the development docs.
Migration notes
Python support
The minimum supported Python version is now 3.10, declared by
requires-python in the package metadata. This is a breaking compatibility
change for Python 3.8 and 3.9 users; upgrade Python before installing this version.
CI covers Python 3.10–3.13 on Ubuntu and macOS.
Storage backends (since v1.0.15)
The legacy FileStorage, ZipFileStorage, and FilesystemStorage API
in apibackuper.storage is deprecated. New code should use the unified
StorageBackend implementations from apibackuper.storage.backends:
| Legacy class | Replacement |
|---|---|
FileStorage |
StorageBackend (base class) |
ZipFileStorage |
ZipStorageBackend |
FilesystemStorage |
FilesystemStorageBackend |
The legacy concrete classes still work but emit DeprecationWarning on
instantiation. Importing alone is silent. Mapping the legacy API to the new
backend API:
# Before (deprecated)
from apibackuper.storage import ZipFileStorage
storage = ZipFileStorage("pages.zip", mode="w")
storage.exists("page_1.json") # -> bool
storage.store("page_1.json", b'{"id": 1}')
storage.close()
# After (preferred)
from apibackuper.storage import ZipStorageBackend
storage = ZipStorageBackend("pages.zip", mode="w")
"page_1.json" in storage.list_objects("page") # -> bool
storage.save_page("page_1.json", b'{"id": 1}')
storage.close()
YAML configuration
The INI config format is deprecated; YAML is the canonical format. A
YAML config supports ${VAR} and ${VAR:-default} placeholders for
sensitive credentials (see SECURITY.md).
License
MIT License — see LICENSE.
Links
Metadata
Release files for apibackuper 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| apibackuper-2.0.0.tar.gz | 134.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| apibackuper-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 213.0 kB
Release files / apibackuper-2.0.0.tar.gz
| Download URL | apibackuper-2.0.0.tar.gz |
|---|---|
| Size | 134.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
af3a565ca4d4b551ba7cc02e726b8504bd21c58e6a1371fd86cdeea58bf6a17c
|
|
BLAKE2b-256 checksum How to use checksums |
34a58c2f83969388cee588aff2d08c60f61930df3a99ec42ac241c7df05e2e3a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / apibackuper-2.0.0-py3-none-any.whl
| Download URL | apibackuper-2.0.0-py3-none-any.whl |
|---|---|
| Size | 79.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
56bb75c13ebff60d5a393757c81af382f5cc290080d4d6bbaa82f95ca70911b0
|
|
BLAKE2b-256 checksum How to use checksums |
ee48c2ff3aee23a61c63ad0391785a502e6744b253990b5439a2b94a84b55cf9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Security for apibackuper 2.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.