🔖 aiolinkding: a Python3, async library to the linkding REST API
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
Installation
pip install aiolinkding
Python Versions
aiolinkding is currently supported on:
- Python 3.11
- Python 3.12
- Python 3.13
Usage
Creating a Client
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())
Working with Bookmarks
Getting All Bookmarks
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)
Getting Archived Bookmarks
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)
Getting a Single Bookmark by ID
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())
Creating a New 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")
# 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
Updating an Existing Bookmark by ID
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
Archiving/Unarchiving a 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")
# Archive a bookmark by ID:
await client.bookmarks.async_archive(37)
# ...and unarchive it:
await client.bookmarks.async_unarchive(37)
asyncio.run(main())
Deleting a 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")
# Delete a bookmark by ID:
await client.bookmarks.async_delete(37)
asyncio.run(main())
Working with Tags
Getting All Tags
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)
Getting a Single Tag by ID
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())
Creating a New Tag
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())
Working with User Data
Getting Profile Info
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())
Connection Pooling
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())
Contributing
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!
Metadata
Release files for aiolinkding 2025.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| aiolinkding-2025.2.0.tar.gz | 14.2 kB | Without provenance | Details for aiolinkding-2025.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| aiolinkding-2025.2.0-py3-none-any.whl | Python 3 | none | any | Details for aiolinkding-2025.2.0-py3-none-any.whl |
Total release size: 25.1 kB
Release files / aiolinkding-2025.2.0.tar.gz
| Download URL | aiolinkding-2025.2.0.tar.gz |
|---|---|
| Size | 14.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5ae3cfc0294d848b610b847bf34da41459a0d03208f8632cc09d1062875a4197
|
|
BLAKE2b-256 checksum How to use checksums |
926af170f403d62c3bc7a515ba2a6494ba69795dec549566515eb2b3843c0fd4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.5.26
|
Release files / aiolinkding-2025.2.0-py3-none-any.whl
| Download URL | aiolinkding-2025.2.0-py3-none-any.whl |
|---|---|
| Size | 10.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fec9c52ab6771d01d244ae375f34b2d18a8656b957ae253f9a4beb4766dbe95e
|
|
BLAKE2b-256 checksum How to use checksums |
d1418d7a408279cc2ba8bbd1d87b01b8ea98c9de6419bd643d868623d5e2b31b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.5.26
|
Security for aiolinkding 2025.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.