Skip to main content

🔖 aiolinkding: a Python3, async library to the linkding REST API

CI PyPI Version License Code Coverage Maintainability

Buy Me A Coffee

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

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:

  1. A URL to a linkding instance
  2. 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 bookmarks
  • limit: the maximum number of results that should be returned
  • offset: the index from which to return results (e.g., 5 starts 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 bookmarks
  • limit: the maximum number of results that should be returned
  • offset: the index from which to return results (e.g., 5 starts 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 title
  • description: the bookmark's description
  • notes: Markdown notes to add to the bookmark
  • tag_names: the tags to assign to the bookmark (represented as a list of strings)
  • is_archived: whether the newly-created bookmark should automatically be archived
  • unread: whether the newly-created bookmark should be marked as unread
  • shared: 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 URL
  • title: the bookmark's title
  • description: the bookmark's description
  • notes: Markdown notes to add to the bookmark
  • tag_names: the tags to assign to the bookmark (represented as a list of strings)
  • unread: whether the bookmark should be marked as unread
  • shared: 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 returned
  • offset: the index from which to return results (e.g., 5 starts 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!

  1. Check for open features/bugs or initiate a discussion on one.
  2. Fork the repository.
  3. (optional, but highly recommended) Create a virtual environment: python3 -m venv .venv
  4. (optional, but highly recommended) Enter the virtual environment: source ./.venv/bin/activate
  5. Install the dev environment: script/setup
  6. Code your new feature or bug fix on a new branch.
  7. Write tests that cover your new functionality.
  8. Run tests and ensure 100% code coverage: poetry run pytest --cov aiolinkding tests
  9. Update README.md with any new documentation.
  10. 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)

Source distribution for aiolinkding 2025.2.0
File Size Uploaded
aiolinkding-2025.2.0.tar.gz 14.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aiolinkding 2025.2.0
File Interpreter ABI Platform
aiolinkding-2025.2.0-py3-none-any.whl Python 3 none any Details

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
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page