웹 검색 (Keenable)
코드에서 바로 인터넷을 검색하고 웹페이지를 읽습니다. 모델에 쓰는 키를 그대로 사용합니다. 호출 방법은 두 가지입니다. /v1/chat/completions로 일반 모델처럼 부르거나, 순수 JSON을 돌려주는 전용 엔드포인트를 쓰면 됩니다.
요금
요청당 0.005달러, 즉 1000요청에 5달러입니다.
호출 단위로 과금합니다. 한 번의 호출이 한 건의 요청이며, 결과가 몇 개 돌아오든 같습니다. 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": "오늘 비트코인 시세"}]
}'평범한 어시스턴트 메시지가 돌아오며, 그 안에 출처 목록이 담깁니다. 제목, 게시일, 전체 주소, 그리고 각 항목의 발췌입니다.
페이지 읽기
메시지의 첫 단어가 주소입니다. 그 뒤에 그 페이지에서 무엇이 궁금한지 덧붙일 수 있습니다.
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://ko.wikipedia.org/wiki/도쿄도 인구수"}]
}'지시를 붙이지 않으면 페이지 전체가 markdown으로 돌아옵니다. 붙이면 요청한 부분만 돌아옵니다. 결과를 다시 모델에 넘길 때는 이쪽이 더 빠르고, 사용자 쪽 토큰도 눈에 띄게 적게 듭니다.
지시를 붙이는 이유
위키백과 문서는 수만 자에 이릅니다. 필요한 것이 숫자 하나라면, 지시 한 줄이 시간과 다음 단계의 토큰을 함께 아껴줍니다.
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 | 문자열 | — | 이 도메인 안에서만 검색 (예: naver.com) |
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 | 문자열 | 필수 | 페이지 주소 |
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자 |
| 호출당 결과 수 | 최대 50건 |
| 읽기 지시의 길이 | 2000자까지 |
속도를 넘기면 Retry-After 헤더가 붙은 429가 돌아옵니다. 1초 뒤에 다시 시도하십시오.
오류
| 코드 | 뜻 | 할 일 |
|---|---|---|
400 | query나 url이 없거나 주소에 http://가 없음 | 요청을 고치십시오 |
401 | 키가 받아들여지지 않음 | Authorization을 확인하십시오 |
402 | 잔액 소진 | 대시보드에서 충전하십시오 |
429 | 너무 잦음 | 1초 뒤에 다시 시도하십시오 |
502 | 검색이 응답하지 않음 | 다시 시도하십시오. 과금되지 않았습니다 |
503 | 검색을 일시적으로 쓸 수 없음 | 저희가 처리 중입니다. 과금되지 않았습니다 |
자주 묻는 질문
결과가 0건이어도 과금되나요? 예. 검색이 실행되어 「아무것도 찾지 못했다」고 정직하게 답했다면 일은 수행된 것입니다. 무료가 되는 것은 오류뿐입니다.
스트리밍이 되나요? 되지 않고, 필요하지도 않습니다. 결과는 한 번에, 1초도 안 되어 돌아옵니다.
토큰을 세나요? 요금은 호출 단위이며 토큰은 영향을 주지 않습니다. 그래도 모델 응답에는 토큰 수를 실어 보냅니다. 클라이언트 라이브러리가 빈 응답으로 오해하지 않도록 하기 위해서입니다.
search/… 모델들과 무엇이 다른가요? 그쪽은 먼저 검색한 뒤 찾은 내용을 언어 모델이 문장으로 답합니다. 즉 두 가지 작업에 대해 지불하게 됩니다. 여기서는 가공되지 않은 결과를 받고, 그것을 어떻게 쓸지는 직접 정합니다.