All apps · 0 apps
paperless-telegram-bot
Docker app from geiserx's Repository
Overview
Features health check endpoint, user whitelisting, and auto-detection of inbox tags.
Requires a running Paperless-NGX instance and a Telegram bot token.
More info: https://github.com/GeiserX/paperless-telegram-bot
Readme
View on GitHub
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
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.
Related Projects
| Project | Description |
|---|---|
| Telegram-Archive | Automated, incremental Telegram backups with a local web viewer |
| telegram-delay-channel-cloner | Telegram bot that relays messages between channels with configurable delay |
| telegram-slskd-local-bot | Automated music discovery and download via Telegram bot with Soulseek |
| AskePub | Telegram bot for ePub annotation with GPT-4 |
| jellyfin-telegram-channel-sync | Sync Jellyfin access with Telegram channel membership |
| telegram-archive-mcp | MCP Server for Telegram-Archive |
| n8n-nodes-telegram-archive | n8n community node for Telegram-Archive |
License
This project is licensed under the GNU General Public License v3.0.
Install paperless-telegram-bot on Unraid in a few clicks.
Find paperless-telegram-bot in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
Requirements
Categories
Download Statistics
Related apps
Explore more like this
Explore allDetails
drumsergio/paperless-telegram-bot:latestRuntime arguments
- Network
bridge- Privileged
- false
Template configuration
Health check endpoint port
- Target
- 8080
- Default
- 8080
Telegram bot token from @BotFather
- Target
- TELEGRAM_BOT_TOKEN
Paperless-NGX instance URL
- Target
- PAPERLESS_URL
- Default
- http://paperless:8000
Paperless-NGX API authentication token
- Target
- PAPERLESS_TOKEN
Comma-separated Telegram user IDs (empty = open access)
- Target
- TELEGRAM_ALLOWED_USERS
User-facing Paperless URL for clickable links (defaults to PAPERLESS_URL)
- Target
- PAPERLESS_PUBLIC_URL
Maximum search results to display
- Target
- MAX_SEARCH_RESULTS
- Default
- 10