ウェブ検索 (Keenable)
コードから直接ウェブを検索し、ページを読み取れます。モデルと同じ API キーがそのまま使えます。呼び方は二通り。/v1/chat/completions から通常のモデルとして呼ぶ方法と、素の JSON を返す専用エンドポイントを使う方法です。
料金
1 リクエスト 0.005 ドル、つまり 1000 リクエストで 5 ドルです。
課金は呼び出し単位です。1 回の呼び出しが 1 リクエストで、結果が何件返ってきても変わりません。50 件見つけても 1 件しか見つからなくても料金は同じです。
失敗したリクエストは課金されません。検索側の障害でも、パラメータの誤りでも同じです。
| 内容 | 換算 |
|---|---|
| 1 件返した検索 | 1 リクエスト |
| 50 件返した検索 | 1 リクエスト |
| ページの読み取り | 1 リクエスト |
| あらゆる種類のエラー | 0 |
方法 1 — モデルとして
Cursor、Claude Code、OpenCode をはじめ、どの OpenAI 互換クライアントでも設定を一切変えずに動きます。モデルを選ぶだけです。
モデル:
| モデル | 何をするか |
|---|---|
keenable/search | ウェブを検索し、抜粋つきの出典一覧を返す |
keenable/read | ページを読み取り、本文を markdown で返す |
検索
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": "今日のビットコイン価格"}]
}'返ってくるのは通常のアシスタントメッセージで、その中に出典の一覧が入ります。タイトル、公開日、完全な URL、そして各件の抜粋です。
ページの読み取り
メッセージの最初の語が URL です。その後ろに、そのページで何を知りたいのかを書き足せます。
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://ja.wikipedia.org/wiki/東京都 人口"}]
}'指示を付けなければページ全体が markdown で返ります。付ければ、頼んだ部分だけが返ります。結果をさらにモデルへ渡す場合、こちらのほうが速く、お客様側のトークン消費も目に見えて少なくなります。
指示を付ける意味
Wikipedia の記事は数万文字あります。必要なのが数字ひとつなら、指示を添えることで時間も次の工程のトークンも節約できます。
Python
from openai import OpenAI
client = OpenAI(
api_key="あなたのキー",
base_url="https://nordrouter.com/v1",
)
found = client.chat.completions.create(
model="keenable/search",
messages=[{"role": "user", "content": "今週の AI ニュース"}],
)
print(found.choices[0].message.content)方法 2 — 専用エンドポイント
項目・日付・絞り込みつきの結果が必要で、文章では扱いにくい場合は JSON を使ってください。
POST /v1/search
curl https://nordrouter.com/v1/search \
-H "Authorization: Bearer $NORDROUTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "ニューラルネットワークのニュース",
"max_results": 5,
"published_after": "7d"
}'パラメータ:
| パラメータ | 型 | 既定値 | 何をするか |
|---|---|---|---|
query | 文字列 | 必須 | 何を検索するか |
site | 文字列 | — | このドメイン内だけを検索する(例: itmedia.co.jp) |
max_results | 数値 | 10 | 結果の件数、1 から 50 |
snippet_max_chars | 数値 | — | 抜粋の長さ、180 から 10000 文字 |
published_after | 文字列 | — | この時点より後に公開された記事 |
published_before | 文字列 | — | それより前に公開されたもの |
acquired_after | 文字列 | — | 索引に入ったのがこれより後のもの |
acquired_before | 文字列 | — | 索引に入ったのがこれより前のもの |
query_time | 文字列 | — | その時点の索引の状態で検索する |
日付は三通りの書き方を受け付けます。2026-08-01、完全な ISO 8601 のタイムスタンプ、または相対指定の 30min、12h、7d、3mo、1y です。
公開日と索引収録日は別物です
published_* は記事そのものの日付で絞り込み、acquired_* はページが索引に入った日付で絞り込みます。この違いは重要です。ページは公開日を変えないまま書き換えられることがあるからです。「この一日でウェブに何が現れたか」を知りたいときは acquired_after を使ってください。
レスポンス:
{
"query": "ニューラルネットワークのニュース",
"count": 5,
"results": [
{
"title": "記事の見出し",
"url": "https://example.com/article",
"description": "短い説明",
"snippet": "ページ本文からの抜粋…",
"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=価格表を抜き出して"パラメータ:
| パラメータ | 型 | 既定値 | 何をするか |
|---|---|---|---|
url | 文字列 | 必須 | ページの URL |
max_chars | 数値 | 50000 | 返す文字数 |
prompt | 文字列 | — | 具体的に何を抜き出すか、2000 文字まで |
live | true / false | false | 索引ではなくサイトから直接取得する |
レスポンス:
{
"url": "https://example.com/article",
"title": "見出し",
"description": "説明",
"author": "著者",
"content": "# ページ本文(markdown)…",
"published_at": 1787777084
}live が必要になるとき
索引からのほうが速く返りますが、索引にすべてが入っているわけではありません。ページが新しい場合やクローラーを拒否している場合は live=true を指定してください。サイトから直接読み取ります。料金は同じです。
制限
| 頻度 | キーごとに毎秒 2 リクエスト |
| 抜粋の長さ | 180 から 10000 文字 |
| 1 回あたりの結果件数 | 最大 50 件 |
| 読み取り時の指示の長さ | 2000 文字まで |
頻度を超えると Retry-After ヘッダー付きの 429 が返ります。1 秒おいて再試行してください。
エラー
| コード | 意味 | 対処 |
|---|---|---|
400 | query または url がない、あるいは URL に http:// がない | リクエストを直す |
401 | キーが受け付けられない | Authorization を確認する |
402 | 残高切れ | ダッシュボードから入金する |
429 | 頻度が高すぎる | 1 秒おいて再試行する |
502 | 検索が応答しなかった | 再試行する。課金はされていない |
503 | 検索が一時的に利用できない | こちらで対応中。課金はされていない |
よくある質問
結果が 0 件でも課金されますか。 はい。検索が実行され、正直に「見つかりませんでした」と答えたなら、仕事は行われています。無料になるのはエラーの場合だけです。
ストリーミングはできますか。 できませんし、必要もありません。結果は一括で、コンマ数秒で返ります。
トークンは数えられますか。 料金は呼び出し単位で、トークンは影響しません。それでもモデルの応答にはトークン数を載せています。クライアントライブラリが空の応答と誤認しないためです。
search/… 系のモデルとの違いは。 あちらは先に検索し、その結果を言語モデルが文章にして答えます。つまり二つの仕事に対して支払うことになります。こちらでは生の結果が返るので、その扱いはご自身で決められます。