Manage Paperless-NGX documents via Telegram bot. Upload, search, download, and organize.
Project description
Manage Paperless-NGX documents entirely through Telegram.
A full-featured Telegram bot that integrates with Paperless-NGX, giving you complete document management from your phone or desktop -- no web UI required. Upload documents and photos, search your archive with full-text search, manage metadata, review your inbox, and download files, all within Telegram.
Features
- Document Upload -- Send any file or photo to the bot and it gets uploaded to Paperless-NGX automatically. Duplicates are detected and linked.
- Full-Text Search -- Search across all your documents with
/search. Results are paginated with inline keyboard navigation. - Metadata Management -- After uploading (or on any document), assign tags, correspondents, and document types through interactive inline keyboards.
- Inbox Review --
/inboxlists all documents tagged with your inbox tag. Mark them as reviewed with a single tap. - Document Download -- Download original files directly to Telegram (up to 50 MB).
- Recent Documents --
/recentshows the latest documents added to your archive. - System Statistics --
/statsdisplays document counts, tag usage, and storage information. - Health Endpoint -- Built-in
/healthHTTP endpoint for Docker health checks and monitoring. - User Authorization -- Restrict bot access to specific Telegram user IDs via allowlist.
- Non-Root Docker -- Runs as an unprivileged user inside the container.
Quick Start
Docker (Recommended)
docker run -d \
--name paperless-telegram-bot \
--restart unless-stopped \
-e TELEGRAM_BOT_TOKEN=your_bot_token \
-e PAPERLESS_URL=http://your-paperless:8000 \
-e PAPERLESS_TOKEN=your_api_token \
-e TELEGRAM_ALLOWED_USERS=123456789 \
drumsergio/paperless-telegram-bot:latest
Docker Compose
services:
paperless-telegram-bot:
image: drumsergio/paperless-telegram-bot:latest
container_name: paperless-telegram-bot
restart: unless-stopped
environment:
TELEGRAM_BOT_TOKEN: "${TELEGRAM_BOT_TOKEN}"
PAPERLESS_URL: "http://paperless:8000"
PAPERLESS_TOKEN: "${PAPERLESS_TOKEN}"
TELEGRAM_ALLOWED_USERS: "${TELEGRAM_ALLOWED_USERS}"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"]
interval: 30s
timeout: 5s
retries: 3
Manual Installation
git clone https://github.com/GeiserX/paperless-telegram-bot.git
cd paperless-telegram-bot
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # Edit with your values
python -m paperless_bot run
Configuration
All configuration is done through environment variables. Copy .env.example to .env for local development.
| Variable | Required | Default | Description |
|---|---|---|---|
TELEGRAM_BOT_TOKEN |
Yes | -- | Telegram Bot API token from @BotFather |
PAPERLESS_URL |
Yes | -- | Paperless-NGX instance URL (e.g. http://localhost:8000) |
PAPERLESS_TOKEN |
Yes | -- | Paperless-NGX API authentication token |
TELEGRAM_ALLOWED_USERS |
No | (open) | Comma-separated Telegram user IDs allowed to use the bot |
PAPERLESS_PUBLIC_URL |
No | PAPERLESS_URL |
User-facing URL for clickable document links |
MAX_SEARCH_RESULTS |
No | 10 |
Number of results per page in search, recent, and inbox |
REMOVE_INBOX_ON_DONE |
No | true |
Remove inbox tag when clicking "Done" in metadata flow |
INBOX_TAG |
No | (auto-detect) | Explicit inbox tag name. If unset, auto-detects via Paperless API |
LOG_LEVEL |
No | INFO |
Logging level (DEBUG, INFO, WARNING, ERROR) |
HEALTH_PORT |
No | 8080 |
Port for the /health HTTP endpoint |
Commands
| Command | Description |
|---|---|
/search <query> |
Full-text search across all documents |
/recent |
Show recently added documents |
/inbox |
List documents in the inbox with review actions |
/stats |
Display Paperless-NGX statistics |
/help |
Show available commands and usage |
In addition to commands, you can send any file or photo directly to the bot to upload it to Paperless-NGX. After upload, an interactive keyboard lets you assign tags, a correspondent, and a document type.
Architecture
paperless-telegram-bot
|-- src/paperless_bot/
| |-- __main__.py # Entry point, health server, CLI
| |-- config.py # Environment variable loading and validation
| |-- api/
| | +-- client.py # Async Paperless-NGX API client with caching
| +-- bot/
| |-- handlers.py # Command handlers, callback routing, upload flow
| +-- keyboards.py # Inline keyboard builders for metadata selection
+-- tests/ # pytest + respx test suite
Key design decisions:
- Async throughout -- Uses
python-telegram-botwithhttpxfor fully asynchronous I/O. - Metadata caching -- Tags, correspondents, and document types are cached in memory and refreshed on demand, minimizing API calls.
- Callback data encoding -- Telegram limits
callback_datato 64 bytes. All prefixes are kept short (meta:tags:,dl:,sp:, etc.) and long search queries are stored server-side per chat. - Inbox auto-detection -- The bot reads the
is_inbox_tagfield from the Paperless API rather than matching by name, so it works with any language or custom tag name. - Duplicate handling -- Upload failures containing "duplicate" are parsed to extract and link to the existing document.
Security
- User allowlist -- Set
TELEGRAM_ALLOWED_USERSto restrict access. When empty, the bot accepts messages from anyone (not recommended for production). - Non-root container -- The Docker image runs as an unprivileged
paperlessbotuser (UID 1000). - No secrets in code -- All credentials are loaded from environment variables. Never commit
.envfiles. - API token scoping -- The bot uses a single Paperless-NGX API token. Create a dedicated user/token with appropriate permissions.
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run linter and formatter
ruff check src/ && ruff format src/
# Run tests
python -m pytest tests/ -v
# Run tests with coverage
python -m pytest tests/ --cov=paperless_bot --cov-report=term-missing
More Telegram Tools
| Project | Description |
|---|---|
| Telegram-Archive | Automated incremental Telegram backups with local web viewer |
| AskePub | Telegram bot for ePub annotation with GPT-4 |
| telegram-delay-channel-cloner | Relay messages between channels with configurable delay |
| jellyfin-telegram-channel-sync | Sync Jellyfin access with Telegram channel membership |
| telegram-slskd-local-bot | Automated music discovery and download via Telegram |
Contributing
Contributions are welcome. Please:
- Fork the repository
- Create a feature branch (
feat/my-featureorfix/my-bug) - Follow the existing code style (enforced by
ruff) - Add tests for new functionality
- Submit a pull request
This project follows Conventional Commits and Semantic Versioning.
License
This project is licensed under the GNU General Public License v3.0.
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 paperless_telegram_bot-0.6.0.tar.gz.
File metadata
- Download URL: paperless_telegram_bot-0.6.0.tar.gz
- Upload date:
- Size: 22.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b78e017726574b280931e98e717516afc27565594a0579db1141f04ee956732
|
|
| MD5 |
9cdd742d191ceb3eafd62f16f281c55e
|
|
| BLAKE2b-256 |
771d0fb6e27a3db0f7a59b5ce259233cbde593a60e963cfa3bfa123e7cdaa4e9
|
File details
Details for the file paperless_telegram_bot-0.6.0-py3-none-any.whl.
File metadata
- Download URL: paperless_telegram_bot-0.6.0-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c536c874865a5e68d3361d43009d6bd9ff51a9a085a1b1c9f51fe535827a88f7
|
|
| MD5 |
311e3870566fc2bfb0b33b2042433df1
|
|
| BLAKE2b-256 |
c278aee8a69fbf7d77bf8be1d4d375c6acfb5e80b89d616f65ecd9c8dd3b50d9
|