Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 73 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ benefit from Linkup services to the full extent. 📝

- ✅ **Simple and intuitive API client.**
- 🔍 **Support all Linkup entrypoints and parameters.**
- ⚡ **Supports synchronous and asynchronous requests.**
- 🔒 **Handles authentication and request management.**
- ⚡ **Support synchronous and asynchronous calls.**
- 🔒 **Handle authentication and request management.**

## 📦 Installation

Expand Down Expand Up @@ -90,9 +90,10 @@ The `search` function also supports three output types:
user-defined schema

```python
from linkup import LinkupClient, LinkupSourcedAnswer
from typing import Any

from linkup import LinkupClient, LinkupSourcedAnswer

client = LinkupClient() # API key can be read from the environment variable or passed as an argument
search_response: Any = client.search(
query="What are the 3 major events in the life of Abraham Lincoln?",
Expand All @@ -102,18 +103,22 @@ search_response: Any = client.search(
)
assert isinstance(search_response, LinkupSourcedAnswer)
print(search_response.model_dump())
# Response:
# {
# answer="The three major events in the life of Abraham Lincoln are: 1. ...",
# sources=[
# {
# "name": "HISTORY",
# "url": "https://www.history.com/topics/us-presidents/abraham-lincoln",
# "snippet": "Abraham Lincoln - Facts & Summary - HISTORY ..."
# },
# ...
# ]
# }
```

Which prints:

```bash
{
answer="The three major events in the life of Abraham Lincoln are: 1. ...",
sources=[
{
"name": "HISTORY",
"url": "https://www.history.com/topics/us-presidents/abraham-lincoln",
"snippet": "Abraham Lincoln - Facts & Summary - HISTORY ..."
},
...
]
}
```

Check the code or the
Expand All @@ -138,18 +143,65 @@ fetch_response: LinkupFetchResponse = client.fetch(
include_raw_html=True,
)
print(fetch_response.model_dump())
# Response:
# {
# markdown="Get started for free, no credit card required...",
# raw_html="<!DOCTYPE html><html lang=\"en\"><head>...</head><body>...</body></html>"
# }
```

Which prints:

```bash
{
markdown="Get started for free, no credit card required...",
raw_html="<!DOCTYPE html><html lang=\"en\"><head>...</head><body>...</body></html>"
}
```

Check the code or the
[official documentation](https://docs.linkup.so/pages/documentation/api-reference/endpoint/post-fetch)
for the detailed list of available parameters.

#### ⌛ Asynchronous Calls

All the Linkup main functions come with an asynchronous counterpart, with the same behavior and the
same name prefixed by `async_` (e.g. `async_search` for `search`). This should be favored in
production use cases to avoid blocking the main thread while waiting for the Linkup API to respond.
This makes possible to call the Linkup API several times concurrently for instance.

```python
import asyncio
from typing import Any

from linkup import LinkupClient, LinkupSourcedAnswer

async def main() -> None:
client = LinkupClient() # API key can be read from the environment variable or passed as an argument
search_response: Any = await client.async_search(
query="What are the 3 major events in the life of Abraham Lincoln?",
depth="deep", # "standard" or "deep"
output_type="sourcedAnswer", # "searchResults" or "sourcedAnswer" or "structured"
structured_output_schema=None, # must be filled if output_type is "structured"
)
assert isinstance(search_response, LinkupSourcedAnswer)
print(search_response.model_dump())

asyncio.run(main())
```

Which prints:

```bash
{
answer="The three major events in the life of Abraham Lincoln are: 1. ...",
sources=[
{
"name": "HISTORY",
"url": "https://www.history.com/topics/us-presidents/abraham-lincoln",
"snippet": "Abraham Lincoln - Facts & Summary - HISTORY ..."
},
...
]
}
```

#### 📚 More Examples

See the `examples/` directory for more examples and documentation, for instance on how to use Linkup
entrypoints using asynchronous functions.
entrypoints using asynchronous functions to call the Linkup API several times concurrenly.
8 changes: 6 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,14 @@ line-length = 100
target-version = "py39"

[tool.ruff.lint]
select = ["E", "F", "I", "S", "UP"]
extend-ignore = ["D107"]
pydocstyle = { convention = "google" }
select = ["D", "E", "F", "I", "S", "UP"]

[tool.ruff.lint.extend-per-file-ignores]
"tests/**/*_test.py" = ["S101"]
"examples/*.py" = ["D"]
"src/linkup/__init__.py" = ["D104"]
"tests/**/*test.py" = ["D", "S101"]

[build-system]
build-backend = "hatchling.build"
Expand Down
2 changes: 2 additions & 0 deletions src/linkup/client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Linkup client, the entrypoint for Linkup functions."""

import json
import os
from datetime import date
Expand Down
3 changes: 3 additions & 0 deletions src/linkup/errors.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""Linkup custom errors."""


class LinkupInvalidRequestError(Exception):
"""Invalid request error, raised when the Linkup API returns a 400 status code.

Expand Down
2 changes: 2 additions & 0 deletions src/linkup/types.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Input and output types for Linkup functions."""

from typing import Any, Literal, Optional, Union

from pydantic import BaseModel, ConfigDict, Field
Expand Down