Wyszukiwanie w sieci (Keenable)
Szukanie w internecie i czytanie stron prosto z kodu — tym samym kluczem, którego używasz do modeli. Działa na dwa sposoby: jako zwykły model przez /v1/chat/completions albo przez własne endpointy zwracające czysty JSON.
Ile to kosztuje
0,005 $ za zapytanie — czyli 5 $ za 1000 zapytań.
Cena jest za wywołanie: jedno wywołanie to jedno zapytanie, niezależnie od tego, ile wyników wróci. Znalezienie 50 źródeł kosztuje tyle samo, co znalezienie jednego.
Za nieudane zapytania nie pobieramy opłaty — ani za awarię wyszukiwania, ani za błędne parametry.
| co | liczy się jako |
|---|---|
| wyszukiwanie z 1 wynikiem | 1 zapytanie |
| wyszukiwanie z 50 wynikami | 1 zapytanie |
| odczytanie strony | 1 zapytanie |
| błąd dowolnego rodzaju | 0 |
Sposób 1 — jako model
Działa w Cursorze, Claude Code, OpenCode i dowolnym kliencie OpenAI bez żadnych zmian: wystarczy wybrać model.
Modele:
| model | co robi |
|---|---|
keenable/search | szuka w sieci i zwraca listę źródeł z fragmentami |
keenable/read | czyta stronę i zwraca jej tekst w markdownie |
Wyszukiwanie
curl https://nordrouter.com/v1/chat/completions \
-H "Authorization: Bearer $NORDROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "keenable/search",
"messages": [{"role": "user", "content": "kurs bitcoina dzisiaj"}]
}'W odpowiedzi dostaniesz zwykłą wiadomość asystenta z listą źródeł: tytuł, data publikacji, pełny adres i fragment przy każdym.
Czytanie strony
Pierwsze słowo wiadomości to adres. Dalej możesz dopisać, co dokładnie cię na tej stronie interesuje.
curl https://nordrouter.com/v1/chat/completions \
-H "Authorization: Bearer $NORDROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "keenable/read",
"messages": [{"role": "user", "content": "https://pl.wikipedia.org/wiki/Tokio liczba mieszkańców"}]
}'Bez wskazówki dostaniesz całą stronę w markdownie. Ze wskazówką — tylko to, o co poprosiłeś: jest szybciej i wyraźnie taniej w tokenach po twojej stronie, gdy wynik idzie dalej do modelu.
Po co wskazówka
Hasło w Wikipedii to dziesiątki tysięcy znaków. Jeśli potrzebujesz jednej liczby, wskazówka oszczędzi ci czas i tokeny następnego kroku.
Python
from openai import OpenAI
client = OpenAI(
api_key="twój-klucz",
base_url="https://nordrouter.com/v1",
)
found = client.chat.completions.create(
model="keenable/search",
messages=[{"role": "user", "content": "wiadomości o SI z tego tygodnia"}],
)
print(found.choices[0].message.content)Sposób 2 — własne endpointy
Jeśli potrzebujesz wyników z polami, datami i filtrami zamiast ciągłego tekstu, weź JSON.
POST /v1/search
curl https://nordrouter.com/v1/search \
-H "Authorization: Bearer $NORDROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "wiadomości o sieciach neuronowych",
"max_results": 5,
"published_after": "7d"
}'Parametry:
| parametr | typ | domyślnie | co robi |
|---|---|---|---|
query | tekst | wymagany | czego szukać |
site | tekst | — | szukać tylko w tej domenie, na przykład wyborcza.pl |
max_results | liczba | 10 | ile wyników, od 1 do 50 |
snippet_max_chars | liczba | — | długość fragmentu, od 180 do 10 000 znaków |
published_after | tekst | — | materiały opublikowane po tym momencie |
published_before | tekst | — | opublikowane wcześniej |
acquired_after | tekst | — | które trafiły do indeksu później |
acquired_before | tekst | — | które trafiły do indeksu wcześniej |
query_time | tekst | — | szukać w indeksie takim, jaki był w tym momencie |
Daty przyjmujemy w trzech postaciach: 2026-08-01, pełny znacznik czasu ISO 8601 albo względnie — 30min, 12h, 7d, 3mo, 1y.
Publikacja i indeks to nie to samo
published_* filtruje po dacie samego materiału, acquired_* — po dacie, kiedy strona trafiła do indeksu. Różnica ma znaczenie: stronę można przepisać, nie ruszając daty publikacji. Jeśli chcesz wiedzieć, „co pojawiło się w sieci w ciągu doby", weź acquired_after.
Odpowiedź:
{
"query": "wiadomości o sieciach neuronowych",
"count": 5,
"results": [
{
"title": "Tytuł artykułu",
"url": "https://example.com/article",
"description": "Krótki opis",
"snippet": "Fragment tekstu strony…",
"published_at": "2026-08-25T10:30:00Z",
"acquired_at": "2026-08-25T11:02:00Z"
}
]
}GET /v1/fetch
curl -G https://nordrouter.com/v1/fetch \
-H "Authorization: Bearer $NORDROUTER_KEY" \
--data-urlencode "url=https://example.com/article" \
--data-urlencode "prompt=wyciągnij tabelę cen"Parametry:
| parametr | typ | domyślnie | co robi |
|---|---|---|---|
url | tekst | wymagany | adres strony |
max_chars | liczba | 50 000 | ile znaków zwrócić |
prompt | tekst | — | co dokładnie wyciągnąć, do 2000 znaków |
live | true / false | false | pobrać prosto ze strony zamiast z indeksu |
Odpowiedź:
{
"url": "https://example.com/article",
"title": "Tytuł",
"description": "Opis",
"author": "Autor",
"content": "# Tekst strony w markdownie…",
"published_at": 1787777084
}Kiedy potrzebny jest live
Z indeksu strona przychodzi szybciej, ale indeks nie zawiera wszystkiego. Jeśli strona jest świeża albo zamknięta dla robotów, ustaw live=true — wtedy zostanie odczytana wprost z witryny. Kosztuje tyle samo.
Ograniczenia
| tempo | 2 zapytania na sekundę na klucz |
| długość fragmentu | od 180 do 10 000 znaków |
| wyników na wywołanie | do 50 |
| długość wskazówki przy czytaniu | do 2000 znaków |
Przekroczenie tempa zwróci 429 z nagłówkiem Retry-After — powtórz po sekundzie.
Błędy
| kod | co znaczy | co zrobić |
|---|---|---|
400 | brakuje query albo url, lub adres bez http:// | popraw zapytanie |
401 | klucz nieprzyjęty | sprawdź Authorization |
402 | saldo wyczerpane | doładuj w panelu |
429 | zbyt często | powtórz po sekundzie |
502 | wyszukiwanie nie odpowiedziało | powtórz; nic nie pobrano |
503 | wyszukiwanie chwilowo niedostępne | już się tym zajmujemy; nic nie pobrano |
Częste pytania
Czy pusty wynik jest płatny? Tak, jeśli wyszukiwanie zadziałało i uczciwie odpowiedziało „nic nie znaleziono" — praca została wykonana. Bezpłatne są tylko błędy.
Czy da się strumieniować? Nie i nie ma potrzeby: wyniki przychodzą jednym kawałkiem w ułamku sekundy.
Czy liczone są tokeny? Cena jest za wywołanie, tokeny na nią nie wpływają. Mimo to pokazujemy je w odpowiedzi modelu, żeby biblioteki klienckie nie uznały jej za pustą.
Czym to się różni od modeli search/…? Tamte najpierw szukają, a potem odpowiadają modelem językowym — płacisz za dwie prace. Tutaj dostajesz surowe wyniki i sam decydujesz, co z nimi zrobić.