Standalone tool to build a local, self-serving archive of SevDesk documents (invoices, credit notes, vouchers).
Project description
SevDesk Archiver
Standalone Python tool that builds a self-contained local archive of your SevDesk documents (invoices, credit notes, vouchers). Each document is stored as a PDF plus a JSON sidecar with the full SevDesk metadata, and the archive ships its own standalone HTML viewer — no database, no server required.
- Idempotent — re-running only fetches what is missing or changed
- Self-serving — the archive directory contains a static
index.htmlviewer and a standaloneserve.py(Python stdlib only) - Type-aware — invoices, credit notes, and vouchers with correct status/type labels (German)
- Resilient — exponential backoff on rate limits and transient network errors
- Integrity-checked — SHA-256
pdf_hashper document;verifycross-checks manifest, files, sidecars, and hashes - No DB — plain files on disk, easy to back up, inspect, or diff
Run it
No install needed — uvx fetches and runs the latest release in an ephemeral environment:
uvx sevdesk-archiver@latest --help
Or install persistently:
uv tool install sevdesk-archiver
sevdesk-archiver --help
Configure
Two things are needed for the archive command: a SevDesk API token and a target directory. Any of the following works:
1. Command-line arguments — highest precedence:
uvx sevdesk-archiver@latest archive \
--api-token "$SEVDESK_API_TOKEN" \
--target /path/to/archive
2. Environment variables — export once, run anywhere:
export SEVDESK_API_TOKEN=your_sevdesk_token
export ARCHIVE_TARGET=$HOME/Documents/sevdesk-archive
uvx sevdesk-archiver@latest archive
3. .env file in the working directory — auto-loaded on startup:
# .env
SEVDESK_API_TOKEN=your_sevdesk_token
ARCHIVE_TARGET=.
cd /path/to/archive && uvx sevdesk-archiver@latest archive
Get your SevDesk API token from https://my.sevdesk.de/admin/userManagement (Benutzer → API-Token).
One-line in-place refresh
Drop a .env (with ARCHIVE_TARGET=. and your token) into an archive directory, then refresh it with a single line from inside that directory:
cd /path/to/archive && uvx sevdesk-archiver@latest archive
Or as a cron / systemd-timer job:
cd /path/to/archive && uvx sevdesk-archiver@latest archive && uvx sevdesk-archiver@latest verify
Commands
# Build / refresh the archive (default range: 1st of previous month … today)
sevdesk-archiver archive
# Limit the date range
sevdesk-archiver archive --after 2026-01-01 --end 2026-03-31
# Include vouchers (incoming invoices)
sevdesk-archiver archive --vouchers
# See what would happen — no files written
sevdesk-archiver archive --dry-run
# Serve the archive over HTTP and open the browser (index.html needs http://)
sevdesk-archiver serve
# Deep integrity check: manifest ↔ files ↔ sidecars ↔ hashes
sevdesk-archiver verify
# Add SHA-256 pdf_hash to sidecars that lack it (existing archives)
sevdesk-archiver verify --backfill-hashes
--target <dir> overrides ARCHIVE_TARGET on any command.
Archive layout
$ARCHIVE_TARGET/
├── index.html # viewer (loads manifest.json via fetch)
├── manifest.json # summary of all entries
├── logo.png
├── serve.py # standalone HTTP server (stdlib only)
├── serve-archive.sh # wrapper: ./serve-archive.sh
└── files/
├── inv-20260115-RE-2026_0001-Mustermann_GmbH.pdf
├── inv-20260115-RE-2026_0001-Mustermann_GmbH.json
└── …
The files/ subdirectory is the authoritative store. manifest.json is regenerated on every run and is safe to delete — it'll be rebuilt from the sidecars. The index.html / serve.py helpers are copies of the shipped templates; you can re-run sevdesk-archiver archive at any time to refresh them.
Each sidecar carries the full SevDesk document, archive metadata, and a SHA-256 pdf_hash ("sha256:<hex>") so verify can catch silent corruption.
Once archived, the folder is self-contained. You can copy it anywhere (USB stick, S3, attached storage) and open it with:
cd /path/to/archive
./serve-archive.sh # or: python3 serve.py
No pip install, no sevdesk-archiver, no SevDesk API access required to browse — just Python 3's standard library.
Library use
from sevdesk_archiver import SevDeskClient, verify_archive
from sevdesk_archiver.archive import archive
client = SevDeskClient(api_token="...")
for event in archive(client, target_dir="/path/to/archive"):
print(event["message"])
report = verify_archive("/path/to/archive")
Development
uv sync
uv run pytest
uv run ruff check src tests
uv run mypy src
See CLAUDE.md for the release process and project conventions, and CHANGELOG.md for version history.
License
Apache-2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sevdesk_archiver-0.1.1.tar.gz.
File metadata
- Download URL: sevdesk_archiver-0.1.1.tar.gz
- Upload date:
- Size: 95.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce4f0ac5a642f70a548a5926ab3a1fa39100523cac5d82fc53609a5da9b4ec34
|
|
| MD5 |
711253eab16804b51076e03eb00f32b2
|
|
| BLAKE2b-256 |
b37178972422f0fc06b4dcb0c5d44b44afe6b086045caec2f7fae1ab65173fe5
|
Provenance
The following attestation bundles were made for sevdesk_archiver-0.1.1.tar.gz:
Publisher:
release.yaml on arjoma/sevdesk-archiver
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sevdesk_archiver-0.1.1.tar.gz -
Subject digest:
ce4f0ac5a642f70a548a5926ab3a1fa39100523cac5d82fc53609a5da9b4ec34 - Sigstore transparency entry: 1348947280
- Sigstore integration time:
-
Permalink:
arjoma/sevdesk-archiver@b62822613574832fbcac70a37d994777a6d63a4d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/arjoma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@b62822613574832fbcac70a37d994777a6d63a4d -
Trigger Event:
push
-
Statement type:
File details
Details for the file sevdesk_archiver-0.1.1-py3-none-any.whl.
File metadata
- Download URL: sevdesk_archiver-0.1.1-py3-none-any.whl
- Upload date:
- Size: 97.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63d48df5798db155098a11b3636c64495630959b30569b45725867704a9a2fb5
|
|
| MD5 |
9e999134bc2d287fa1d7fa576d5bc885
|
|
| BLAKE2b-256 |
b914a3b2af9cd893b18d65f355753151e8ebfb61a069ef30069c26fb26a1a5d4
|
Provenance
The following attestation bundles were made for sevdesk_archiver-0.1.1-py3-none-any.whl:
Publisher:
release.yaml on arjoma/sevdesk-archiver
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sevdesk_archiver-0.1.1-py3-none-any.whl -
Subject digest:
63d48df5798db155098a11b3636c64495630959b30569b45725867704a9a2fb5 - Sigstore transparency entry: 1348947429
- Sigstore integration time:
-
Permalink:
arjoma/sevdesk-archiver@b62822613574832fbcac70a37d994777a6d63a4d -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/arjoma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@b62822613574832fbcac70a37d994777a6d63a4d -
Trigger Event:
push
-
Statement type: