aiolinkding is a Python3, async library that interfaces with linkding
instances. It is intended to be a reasonably light wrapper around the linkding API
(meaning that instead of drowning the user in custom objects/etc., it focuses on
returning JSON straight from the API).
- Installation
- Python Versions
- Usage
- Contributing
pip install aiolinkdingaiolinkding is currently supported on:
- Python 3.11
- Python 3.12
- Python 3.13
It's easy to create an API client for a linkding instance. All you need are two parameters:
- A URL to a linkding instance
- A linkding API token
import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
asyncio.run(main())import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Get all bookmarks:
bookmarks = await client.bookmarks.async_get_all()
# >>> { "count": 100, "next": null, "previous": null, "results": [...] }
asyncio.run(main())client.bookmarks.async_get_all() takes three optional parameters:
query: a string query to filter the returned bookmarkslimit: the maximum number of results that should be returnedoffset: the index from which to return results (e.g.,5starts at the fifth bookmark)
import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Get all archived bookmarks:
bookmarks = await client.bookmarks.async_get_archived()
# >>> { "count": 100, "next": null, "previous": null, "results": [...] }
asyncio.run(main())client.bookmarks.async_get_archived() takes three optional parameters:
query: a string query to filter the returned bookmarkslimit: the maximum number of results that should be returnedoffset: the index from which to return results (e.g.,5starts at the fifth bookmark)
import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Get a single bookmark:
bookmark = await client.bookmarks.async_get_single(37)
# >>> { "id": 37, "url": "https://example.com", "title": "Example title", ... }
asyncio.run(main())import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Create a new bookmark:
created_bookmark = await client.bookmarks.async_create(
"https://example.com",
title="Example title",
description="Example description",
tag_names=[
"tag1",
"tag2",
],
)
# >>> { "id": 37, "url": "https://example.com", "title": "Example title", ... }
asyncio.run(main())client.bookmarks.async_create() takes four optional parameters:
title: the bookmark's titledescription: the bookmark's descriptionnotes: Markdown notes to add to the bookmarktag_names: the tags to assign to the bookmark (represented as a list of strings)is_archived: whether the newly-created bookmark should automatically be archivedunread: whether the newly-created bookmark should be marked as unreadshared: whether the newly-created bookmark should be shareable with other linkding users
import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Update an existing bookmark:
updated_bookmark = await client.bookmarks.async_update(
37,
url="https://different-example.com",
title="Different example title",
description="Different example description",
tag_names=[
"tag1",
"tag2",
],
)
# >>> { "id": 37, "url": "https://different-example.com", ... }
asyncio.run(main())client.bookmarks.async_update() takes four optional parameters (inclusion of any parameter
will change that value for the existing bookmark):
url: the bookmark's URLtitle: the bookmark's titledescription: the bookmark's descriptionnotes: Markdown notes to add to the bookmarktag_names: the tags to assign to the bookmark (represented as a list of strings)unread: whether the bookmark should be marked as unreadshared: whether the bookmark should be shareable with other linkding users
import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Archive a bookmark by ID:
await client.bookmarks.async_archive(37)
# ...and unarchive it:
await client.bookmarks.async_unarchive(37)
asyncio.run(main())import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Delete a bookmark by ID:
await client.bookmarks.async_delete(37)
asyncio.run(main())import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Get all tags:
tags = await client.tags.async_get_all()
# >>> { "count": 100, "next": null, "previous": null, "results": [...] }
asyncio.run(main())client.tags.async_get_all() takes two optional parameters:
limit: the maximum number of results that should be returnedoffset: the index from which to return results (e.g.,5starts at the fifth bookmark)
import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Get a single tag:
tag = await client.tags.async_get_single(22)
# >>> { "id": 22, "name": "example-tag", ... }
asyncio.run(main())import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Create a new tag:
created_tag = await client.tags.async_create("example-tag")
# >>> { "id": 22, "name": "example-tag", ... }
asyncio.run(main())import asyncio
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
client = await async_get_client("http://127.0.0.1:8000", "token_abcde12345")
# Get all tags:
tags = await client.user.async_get_profile()
# >>> { "theme": "auto", "bookmark_date_display": "relative", ... }
asyncio.run(main())By default, the library creates a new connection to linkding with each coroutine. If you
are calling a large number of coroutines (or merely want to squeeze out every second of
runtime savings possible), an aiohttp ClientSession can be used for
connection pooling:
import asyncio
from aiohttp import async_get_clientSession
from aiolinkding import async_get_client
async def main() -> None:
"""Use aiolinkding for fun and profit."""
async with ClientSession() as session:
client = await async_get_client(
"http://127.0.0.1:8000", "token_abcde12345", session=session
)
# Get to work...
asyncio.run(main())Thanks to all of our contributors so far!
- Check for open features/bugs or initiate a discussion on one.
- Fork the repository.
- (optional, but highly recommended) Create a virtual environment:
python3 -m venv .venv - (optional, but highly recommended) Enter the virtual environment:
source ./.venv/bin/activate - Install the dev environment:
script/setup - Code your new feature or bug fix on a new branch.
- Write tests that cover your new functionality.
- Run tests and ensure 100% code coverage:
poetry run pytest --cov aiolinkding tests - Update
README.mdwith any new documentation. - Submit a pull request!