{"id":13522609,"url":"https://github.com/perfectra1n/pytrilium","last_synced_at":"2026-01-16T06:54:56.398Z","repository":{"id":147108215,"uuid":"617781159","full_name":"perfectra1n/pytrilium","owner":"perfectra1n","description":"Python SDK (wrapper, whatever you want to call it) for interacting with Trilium's ETAPI.","archived":false,"fork":false,"pushed_at":"2025-02-03T19:30:43.000Z","size":129,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-24T11:16:02.630Z","etag":null,"topics":["api-client","api-client-python","client","interact","python","python-sdk","sdk","trilium","trilium-notes","wrapper","wrapper-library"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/perfectra1n.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-23T05:00:53.000Z","updated_at":"2025-02-03T19:30:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"d1c8791a-de11-4192-b2ac-554f8a6b8b8c","html_url":"https://github.com/perfectra1n/pytrilium","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfectra1n%2Fpytrilium","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfectra1n%2Fpytrilium/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfectra1n%2Fpytrilium/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/perfectra1n%2Fpytrilium/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/perfectra1n","download_url":"https://codeload.github.com/perfectra1n/pytrilium/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246552847,"owners_count":20795830,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","api-client-python","client","interact","python","python-sdk","sdk","trilium","trilium-notes","wrapper","wrapper-library"],"created_at":"2024-08-01T06:00:49.849Z","updated_at":"2026-01-16T06:54:56.387Z","avatar_url":"https://github.com/perfectra1n.png","language":"Python","funding_links":[],"categories":["🖥️ ETAPI"],"sub_categories":["🦾 ETAPI client"],"readme":"# Pytrilium\n\nPython SDK (wrapper, whatever you want to call it) for interacting with [Trilium's](https://github.com/zadam/trilium) ETAPI. The exact OpenAPI spec definition file that I'm trying to match can be found [here](https://github.com/zadam/trilium/blob/master/src/etapi/etapi.openapi.yaml).\n\nYou can use either your password or an ETAPI token to authenticate to the Trilium instance.\n\n\n\n## 🖥 Installation\n\n```bash\npip install pytrilium\n```\n\n## Examples\n\n### 🔐 Authenticating (via ETAPI token or password)\nToken:\n```python\nfrom pytrilium.PyTrilium import PyTrilium\n\npytrilium_client = PyTrilium(\"https://trilium.example.com\", token=\"TTDaTeG3sadffy2_eOtgqvZoI6xHvga/6vhz61ezke1RpoX47vPI93zs5qs=\")\n\nprint(pytrilium_client.get_note_content_by_id(\"MLDQ3EGWsU8e\"))\n```\n\nPassword:\n```python\nfrom pytrilium.PyTrilium import PyTrilium\n\npytrilium_client = PyTrilium(\"https://trilium.example.com\", password=\"thisisabadpassword1\")\n\nprint(pytrilium_client.get_note_content_by_id(\"MLDQ3EGWsU8e\"))\n```\n\n### 📒 Basic Use Case\n\nThis will just print out the contents of a note, as one large string. Trilium's API returns it in the HTML format.\n\n```python\nfrom pytrilium.PyTrilium import PyTrilium\n\npytrilium_client = PyTrilium(\"https://trilium.example.com\", token=\"TTDaTeG3sadffy2_eOtgqvZoI6xHvga/6vhz61ezke1RpoX47vPI93zs5qs=\")\n\nprint(pytrilium_client.get_note_content_by_id(\"MLDQ3EGWsU8e\"))\n```\n\nExport a note to a file\n\n```python\nfrom pytrilium.PyTrilium import PyTrilium\n\ntest_client = PyTrilium(\"https://trilium.example.com\", token=\"TTDaTeG3sadffy2_eOtgqvZoI6xHvga/6vhz61ezke1RpoX47vPI93zs5qs=\")\n\nprint(test_client.get_note_content_by_id(\"MLDQ3EGWsU8e\"))\n\ntest_client.export_note_by_id(\"MLDQ3EGWsU8e\", \"./test.zip\")\n```\n\n### 📎 Working with Attachments\n\nCreate and manage attachments:\n\n```python\nfrom pytrilium.PyTrilium import PyTrilium\n\npytrilium_client = PyTrilium(\"https://trilium.example.com\", token=\"TTDaTeG3sadffy2_eOtgqvZoI6xHvga/6vhz61ezke1RpoX47vPI93zs5qs=\")\n\n# Create an attachment\nattachment_data = '{\"role\": \"file\", \"mime\": \"image/png\", \"title\": \"my-image.png\"}'\nattachment = pytrilium_client.create_attachment(attachment_data)\nattachment_id = attachment['attachmentId']\n\n# Get attachment metadata\nattachment_info = pytrilium_client.get_attachment_by_id(attachment_id)\n\n# Get attachment content (binary data)\nattachment_content = pytrilium_client.get_attachment_content_by_id(attachment_id)\n\n# Update attachment content\nwith open(\"new-image.png\", \"rb\") as f:\n    new_content = f.read()\npytrilium_client.put_attachment_content_by_id(attachment_id, new_content)\n\n# Update attachment metadata\nupdate_data = '{\"title\": \"updated-image.png\"}'\npytrilium_client.patch_attachment_by_id(attachment_id, update_data)\n\n# Delete attachment\npytrilium_client.delete_attachment_by_id(attachment_id)\n```\n\n### 🧠 More Advanced\n\nIf I'm braindead or this just doesn't do what you want it to, you can still use the underlying `requests.Session` that I've set up so that you can still interact with the API. This way you can still make manual requests if you would like to, and do whatever you would like with them.\n\nTo print out a Note's content without using other helpers -\n\n```python\nfrom pytrilium.PyTrilium import PyTrilium\n\npytrilium_client = PyTrilium(\"https://trilium.example.com\", token=\"TTDaTeG3sadffy2_eOtgqvZoI6xHvga/6vhz61ezke1RpoX47vPI93zs5qs=\")\n\nresp = pytrilium_client.make_request('notes/\u003cnoteid\u003e/content')\nprint(resp.text)\n```\n\n## Currently implemented functions\n```\nattempt_basic_call\nauth_login\nauth_logout\nclean_url\ncreate_attachment\ncreate_note\ncreate_note_revision\ndelete_attachment_by_id\ndelete_attribute_by_id\ndelete_branch_by_id\ndelete_note_by_id\nexport_note_by_id\nget_app_info\nget_attachment_by_id\nget_attachment_content_by_id\nget_attribute_by_id\nget_branch_by_id\nget_days_note\nget_inbox_note\nget_months_note\nget_note_by_id\nget_note_content_by_id\nget_weeks_note\nget_year_note\nmake_request\nmake_requests_session\npatch_attachment_by_id\npatch_attribute_by_id\npatch_branch_by_id\npatch_note_by_id\npost_attribute\npost_branch\nprint_custom_functions\nput_attachment_content_by_id\nput_note_content_by_id\nrefresh_note_ordering\nsearch\nset_session_auth\nvalid_response_codes\n```\n\n## Development\n\n### Installing for Development\n\n```bash\ngit clone https://github.com/perfectra1n/pytrilium.git\ncd pytrilium\npip install -e \".[dev]\"\n```\n\n### Running Tests\n\n```bash\n# Format code\nblack pytrilium/\n\n# Check imports\nisort pytrilium/\n\n# Lint code  \nflake8 pytrilium/\n\n# Test imports\npython -c \"from pytrilium.PyTrilium import PyTrilium; print('✅ Import successful')\"\n```\n\n### Releasing\n\nSee [RELEASE.md](RELEASE.md) for the complete release process. Quick version:\n\n```bash\n# Update version and create tag\npython scripts/bump_version.py 1.3.2 --create-tag --push-tag\n\n# Push to trigger automated release\ngit push origin main\n```\n\n## Misc\nTo get a quick list of currently available paths from the OpenAPI spec (doesn't always mean what's in this package or not):\n\n```bash\ncurl https://raw.githubusercontent.com/zadam/trilium/master/src/etapi/etapi.openapi.yaml 2\u003e/dev/null | yq -e \".paths | keys\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperfectra1n%2Fpytrilium","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fperfectra1n%2Fpytrilium","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fperfectra1n%2Fpytrilium/lists"}