https://github.com/thiswillbeyourgithub/karakeep_python_api
Community-driven Python client & CLI for the Karakeep API.
https://github.com/thiswillbeyourgithub/karakeep_python_api
Last synced: 6 days ago
JSON representation
Community-driven Python client & CLI for the Karakeep API.
- Host: GitHub
- URL: https://github.com/thiswillbeyourgithub/karakeep_python_api
- Owner: thiswillbeyourgithub
- License: gpl-3.0
- Created: 2025-05-05T14:03:06.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2025-11-30T00:46:12.000Z (3 months ago)
- Last Synced: 2025-12-02T04:29:04.066Z (3 months ago)
- Language: Python
- Size: 365 KB
- Stars: 23
- Watchers: 1
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Karakeep Python API Client
[](https://badge.fury.io/py/karakeep-python-api)
A community-developed Python client for the [Karakeep](https://karakeep.app/) API.
**Disclaimer:** This is an unofficial, community-driven project. The developers of Karakeep were not consulted during its creation. Use at your own discretion.
## Table of Contents
- [Overview](#overview)
- [Current Status & Caveats](#current-status--caveats)
- [API Method Coverage](#api-method-coverage)
- [Installation](#installation)
- [Usage](#usage)
- [Environment Variables](#environment-variables)
- [Command Line Interface (CLI)](#command-line-interface-cli)
- [Python Library](#python-library)
- [Community Scripts](#community-scripts)
- [Development](#development)
## Overview
This library provides a Python interface (both a class and a command-line tool) to interact with a Karakeep instance's API. The author also developed [freshrss_to_karakeep](https://github.com/thiswillbeyourgithub/freshrss_to_karakeep), a Python script that periodically sends FreshRSS "favourite" articles to Karakeep (a bookmarking and read-it-later app, see [Karakeep on GitHub](https://github.com/karakeep-app/karakeep)).
The development process involved:
1. Starting with the official Karakeep OpenAPI specification: [karakeep-openapi-spec.json](https://github.com/karakeep-app/karakeep/blob/main/packages/open-api/karakeep-openapi-spec.json).
2. Generating Pydantic data models from the specification using [datamodel-code-generator](https://koxudaxi.github.io/datamodel-code-generator/).
3. Using [aider.chat](https://aider.chat), an AI pair programming tool, to write the `KarakeepAPI` client class, the Click-based CLI, and the initial Pytest suite.
## Current Status & Caveats
* **Experimental Methods:** The included Pytest suite currently only covers a subset of the available API methods (primarily 'get all' endpoints and client initialization). Methods *not* explicitly tested should be considered **experimental**.
* **Ongoing Development:** The author intends to improve and validate methods as they are needed for personal use cases. Contributions and bug reports are welcome!
* **Updating process**: I have local scripts that downloads the latest OpenAPI specs from karakeep's repo. I then visually inspect the diff, stage a few changes into git, then run `aider --read karakeep_python_api/openapi_reference.json karakeep_python_api/karakeep_api.py karakeep_python_api/datatypes.py --message "As you can see from the git diff output, there was a small update to the openapi reference json file. Please update the python code to match this new update. Here is the git output: $(git --no-pager diff --staged) "`.
## API Method Coverage
The following table lists the public methods available in the `KarakeepAPI` class.
* The "Pytest" column indicates whether the Python library method is covered by the automated test suite (`tests/test_karakeep_api.py`).
* The "CLI" column indicates whether the corresponding CLI command for that method is tested within the Pytest suite (typically via `subprocess`).
Methods or CLI commands marked with ❌ should be used with caution as their behavior has not been automatically verified within the test suite.
| Method Name | Pytest | CLI | Remarks |
| -------------------------------- | :----: | :--: | -------------------------------------------- |
| `get_all_bookmarks` | ✅ | ✅ | Tested with pagination. |
| `create_a_new_bookmark` | ✅ | ❌ | Pytest for `type="link"` via fixture and `type="asset"` via PDF test. CLI not directly tested. |
| `search_bookmarks` | ✅ | ✅ | Seems to be nondeterministic and fails if using more than 3 words |
| `get_a_single_bookmark` | ✅ | ❌ | |
| `delete_a_bookmark` | ✅ | ❌ | |
| `update_a_bookmark` | ✅ | ✅ | Tested for title updates. |
| `summarize_a_bookmark` | ❌ | ❌ | |
| `attach_tags_to_a_bookmark` | ✅ | ❌ | |
| `detach_tags_from_a_bookmark` | ✅ | ❌ | |
| `get_highlights_of_a_bookmark` | ❌ | ❌ | Works from the CLI; not yet added to Pytest. |
| `attach_asset` | ❌ | ❌ | |
| `replace_asset` | ❌ | ❌ | |
| `detach_asset` | ❌ | ❌ | |
| `get_all_lists` | ✅ | ✅ | |
| `create_a_new_list` | ✅ | ❌ | |
| `get_a_single_list` | ✅ | ❌ | |
| `delete_a_list` | ✅ | ❌ | |
| `update_a_list` | ❌ | ❌ | |
| `get_bookmarks_in_the_list` | ❌ | ❌ | |
| `add_a_bookmark_to_a_list` | ❌ | ❌ | |
| `remove_a_bookmark_from_a_list` | ❌ | ❌ | |
| `get_all_tags` | ✅ | ✅ | |
| `create_a_new_tag` | ❌ | ❌ | |
| `get_a_single_tag` | ✅ | ❌ | |
| `delete_a_tag` | ✅ | ❌ | |
| `update_a_tag` | ✅ | ❌ | No output validation due to [server bug](https://github.com/karakeep-app/karakeep/issues/1365). |
| `get_bookmarks_with_the_tag` | ❌ | ❌ | |
| `get_all_highlights` | ✅ | ✅ | Tested with pagination. |
| `create_a_new_highlight` | ❌ | ❌ | |
| `get_a_single_highlight` | ❌ | ❌ | |
| `delete_a_highlight` | ❌ | ❌ | Works from the CLI; not yet added to Pytest. |
| `update_a_highlight` | ❌ | ❌ | |
| `upload_a_new_asset` | ✅ | ❌ | Tested in PDF asset lifecycle test. |
| `get_a_single_asset` | ✅ | ❌ | Tested in PDF asset lifecycle test. |
| `get_current_user_info` | ✅ | ❌ | Pytest: Tested indirectly during client init. CLI not directly tested. |
| `get_current_user_stats` | ✅ | ✅ | |
| `update_user` | ❌ | ❌ | |
| `get_all_backups` | ✅ | ✅ | Tested in backup lifecycle test. |
| `trigger_a_new_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
| `get_a_single_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
| `delete_a_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
| `download_a_backup` | ✅ | ❌ | Tested in backup lifecycle test. |
## Installation
It is recommended to use `uv` for faster installation:
```bash
uv pip install karakeep-python-api
```
Alternatively, use standard `pip`:
```bash
pip install karakeep-python-api
```
## Usage
This package can be used as a Python library or as a command-line interface (CLI).
### Environment Variables
The client can be configured using the following environment variables:
* `KARAKEEP_PYTHON_API_ENDPOINT`: **Required**. The full URL of your Karakeep API, including the `/api/v1/` path (e.g., `https://karakeep.domain.com/api/v1/` or `https://try.karakeep.app/api/v1/`).
* `KARAKEEP_PYTHON_API_KEY`: **Required**. Your Karakeep API key (Bearer token).
* `KARAKEEP_PYTHON_API_VERIFY_SSL`: Set to `false` to disable SSL certificate verification (default: `true`).
* `KARAKEEP_PYTHON_API_VERBOSE`: Set to `true` to enable verbose debug logging for the client and CLI (default: `false`).
* `KARAKEEP_PYTHON_API_DISABLE_RESPONSE_VALIDATION`: Set to `true` to disable Pydantic validation of API responses. The client will return raw dictionary/list data instead of Pydantic models (default: `false`).
* `KARAKEEP_PYTHON_API_ENSURE_ASCII`: Set to `true` to escape non-ASCII characters in the JSON output (default: `false`, which means Unicode characters are kept).
### Command Line Interface (CLI)
The CLI dynamically generates commands based on the API methods. You need to provide your API key and endpoint either via environment variables (recommended) or command-line options.
**Basic Structure:**
```bash
python -m karakeep_python_api [GLOBAL_OPTIONS] [COMMAND_OPTIONS]
```
**Getting Help:**
```bash
# General help and list of commands
python -m karakeep_python_api --help
# Help for a specific command
python -m karakeep_python_api get-all-bookmarks --help
```
**Examples:**
```bash
# List all tags (requires env vars set)
python -m karakeep_python_api get-all-tags
# Get the first page of bookmarks with a limit, overriding env vars if needed
# Note: The /api/v1/ path will be automatically appended if not present
python -m karakeep_python_api --base-url https://karakeep.domain.com/api/v1/ --api-key YOUR_API_KEY get-all-bookmarks --limit 10
# Get all lists and pipe the JSON output to jq to extract the first list
python -m karakeep_python_api get-all-lists | jq '.[0]'
# Create a new bookmark from a link (body provided as JSON string)
python -m karakeep_python_api create-a-new-bookmark --data '{"type": "link", "url": "https://example.com"}'
# Get all tags and ensure ASCII output (e.g., for compatibility with systems that don't handle Unicode well)
python -m karakeep_python_api --ascii get-all-tags
# Dump the raw OpenAPI spec used by the client
python -m karakeep_python_api --dump-openapi-specification
```
### Python Library
Import the `KarakeepAPI` class and instantiate it.
```python
import os
from karakeep_python_api import KarakeepAPI, APIError, AuthenticationError, datatypes
# Ensure required environment variables are set
# Example: os.environ["KARAKEEP_PYTHON_API_ENDPOINT"] = "https://karakeep.domain.com/api/v1/"
# Example: os.environ["KARAKEEP_PYTHON_API_KEY"] = "your_secret_api_key"
try:
# Initialize the client (reads from env vars by default)
client = KarakeepAPI(
# Optionally override env vars:
# api_endpoint="https://karakeep.domain.com/api/v1/",
# api_key="another_key",
# verbose=True,
# disable_response_validation=False
)
# Example: Get all lists
all_lists = client.get_all_lists()
if all_lists:
print(f"Retrieved {len(all_lists)} lists.")
# Access list properties (uses Pydantic models by default)
print(f"First list name: {all_lists[0].name}")
print(f"First list ID: {all_lists[0].id}")
else:
print("No lists found.")
# Example: Get first page of bookmarks
bookmarks_page = client.get_all_bookmarks(limit=5)
print(f"\nRetrieved {len(bookmarks_page.bookmarks)} bookmarks.")
if bookmarks_page.bookmarks:
print(f"First bookmark title: {bookmarks_page.bookmarks[0].title}")
if bookmarks_page.nextCursor:
print(f"Next page cursor: {bookmarks_page.nextCursor}")
except AuthenticationError as e:
print(f"Authentication failed: {e}")
except APIError as e:
print(f"An API error occurred: {e}")
except ValueError as e:
# Handles missing API key/endpoint during initialization
print(f"Configuration error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
```
## Community Scripts
Community Scripts are a bunch of scripts made to solve specific issues. They are made by the community so don't hesitate to submit yours or open an issue if you have a bug. They also serve as example of how to use the API.
They can be found in the [./community_scripts](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts) folder. Don't hesitate to submit yours, the contribution guidelines are in the community_scripts directory README.md file.
| Community Script | Description |
|----------------|--------------------------------------------------------------------------------------------------------------|
| [Karakeep-Time-Tagger](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/karakeep-time-tagger) | Automatically adds time-to-read tags (`0-5m`, `5-10m`, etc.) to bookmarks based on content length analysis. Includes systemd service and timer files for automated periodic execution. |
| [Karakeep-List-To-Tag](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/karakeep-list-to-tag) | Converts a Karakeep list into tags by adding a specified tag to all bookmarks within that list. |
| [Omnivore2Karakeep-Highlights](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/omnivore2karakeep-highlights) | Imports highlights from Omnivore export data to Karakeep, with intelligent position detection and bookmark matching. Supports dry-run mode for testing. |
| [Omnivore2Karakeep-Archived](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/omnivore2karakeep-archived) | (Should not be needed anymore) Fixes the archived status of bookmarks imported from Omnivore by reading export data and updating Karakeep accordingly. |
| [pocket2karakeep-archived](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/pocket2karakeep-archived) by [@youenchene](https://github.com/youenchene) | (Should not be needed anymore) Fixes the archived status of bookmarks imported from Pocket by reading export data and updating Karakeep accordingly. |
| [Karakeep-Archive-Before-Date](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/karakeep-archive-before-date) by [@youenchene](https://github.com/youenchene) | Allow you to archive all not archived post before a given date |
| [Freshrss-To-Karakeep](https://github.com/thiswillbeyourgithub/freshrss_to_karakeep) | Syncs some links from Freshrss to Karakeep |
| [Karanki (WIP)](https://github.com/thiswillbeyourgithub/Karanki) | Bidirectional sync between anki notes and highlights |
| [Karakeep-remove-ai-tags](https://github.com/thiswillbeyourgithub/karakeep_python_api/tree/main/community_scripts/karakeep-remove-ai-tags) by [@youenchene](https://github.com/youenchene) | Remove all tags attached by AI and not human attached |
## Development
1. Clone the repository.
2. Create a virtual environment and activate it.
3. Install dependencies, including development tools (using `uv` recommended):
```bash
uv pip install -e ".[dev]"
```
4. Set the required environment variables (`KARAKEEP_PYTHON_API_ENDPOINT`, `KARAKEEP_PYTHON_API_KEY`) for running tests against a live instance.
5. Run tests:
```bash
pytest
```
---
*This README was generated with assistance from [aider.chat](https://aider.chat).*