Read-focused Telegram data proxy built with FastAPI and Telethon. It exposes structured JSON for chats, contacts, messages, search, and message context, plus raw media download endpoints for single files or all media attached to a message or album.
- FastAPI REST API with OpenAPI at
/openapi.json,/schema/openapi.json, and/schema/openapi.yaml - Long-lived Telethon session stored on a mounted volume for Docker and Ubuntu deployments
- Read-only v1 API for chats, contacts, self info, message retrieval, context, search, media manifests, streaming downloads, and ZIP bundles
- Telegram safety defaults: low
flood_sleep_threshold, serialized history-heavy reads, cached entity resolution, and one-session-owner deployment guidance - Local-only e2e harness for a personal Telegram account, plus unit/integration tests with 80% coverage enforcement
- Create Telegram API credentials at my.telegram.org.
- Create a local env file:
cp .env.example .env- Authenticate once and persist the session volume:
docker compose --profile auth run --rm telegram-auth- Start the API:
docker compose up -d telegram-proxyThe API will be available at http://localhost:4040 by default. Set PORT to change it; the app also still accepts APP_PORT for compatibility.
make install
make auth
make runThe auth CLI stores the Telethon SQLite session under TELEGRAM_SESSION_DIR/TELEGRAM_SESSION_NAME.session.
For local development, .env.example uses ./data/telegram so make auth writes to a project-local directory instead of a root-owned path.
Only one long-lived service instance should own a Telegram session for a given account. Running the same session from multiple hosts or containers risks AUTH_KEY_DUPLICATED, which invalidates the session.
GET /healthzGET /meGET /contactsGET /resolve?value=@usernameGET /chatsGET /chats/{chat_id}GET /chats/{chat_id}/messagesGET /chats/{chat_id}/messages/{message_id}GET /chats/{chat_id}/messages/{message_id}/contextGET /messages/searchGET /chats/{chat_id}/messages/{message_id}/mediaGET /chats/{chat_id}/messages/{message_id}/media/{media_id}GET /chats/{chat_id}/messages/{message_id}/media/bundle
GET /.../mediareturns a manifest of downloadable media items.include_album=truecollects sibling messages that share the same Telegramgrouped_id.GET /.../media/{media_id}streams a single file with binary headers.GET /.../media/bundlereturns a ZIP archive containing every file plusmanifest.json.
Install dependencies:
make installThis creates a local .venv automatically and installs all dependencies there, so it works with Homebrew-managed Python environments that block system-wide pip install.
Run tests:
make testRun local real-account e2e tests:
export TELEGRAM_E2E_ENV_FILE=/absolute/path/to/.env
export E2E_CHAT_ID=123
export E2E_TEXT_MESSAGE_ID=456
export E2E_MEDIA_MESSAGE_ID=789
make test-e2eInstall the git hook:
make pre-commit-installThe pre-commit hook runs pytest -m "not e2e" and enforces the configured 80% coverage threshold.
- Copy
.envto the server and keep it out of version control. - Run the auth profile once to create the persisted session volume.
- Keep the named Docker volume or bind-mount
/data/telegramso restarts do not require re-authentication. - Use
docker compose pull && docker compose up -d --buildfor upgrades.