API 레퍼런스

V1 LLM API

LLM 에이전트, 자동화 스크립트, 통합을 위한 읽기 전용 API예요. 노션 워크스페이스의 그래프 데이터에 접근해 검색, 노드 상세 정보 조회, 페이지 콘텐츠 조회, 그래프 탐색을 할 수 있어요.

개요

속성 값
기본 URL /v1/graph/
인증 서비스 토큰 (Authorization: Bearer ivg_*)
형식 JSON
요청 제한 버스트 제한 10초당 20회, 15분 구간당 600회
자체 설명형 명세 GET /v1/ (인증 불필요)

공통 매개변수

모든 엔드포인트에 workspace_id가 필요해요.

매개변수 유형 필수 여부 설명
workspace_id string (UUID) 필수 노션 워크스페이스 UUID. 토큰의 허용된 workspace_ids 목록에 포함되어 있어야 해요.

엔드포인트


GET /v1/graph/search/

워크스페이스 전체에서 제목으로 노드를 검색해요. Elasticsearch를 사용할 수 있으면 사용하고, 사용할 수 없으면 메모리 내 데이터 매칭으로 대체해요.

권한 범위: graph:search

매개변수:

매개변수 유형 필수 여부 기본값 설명
q string 필수 — 검색어 (최대 256자)
workspace_id string 필수 — 대상 워크스페이스 UUID
limit int 선택 20 페이지당 결과 수 (최대 50개)
type string 선택 all 필터: page, database 또는 user

요청 예시:

curl -H "Authorization: Bearer ivg_your_token" \
  "https://ivgraph.com/v1/graph/search?q=project&workspace_id=abc-123&limit=5"
import requests

resp = requests.get(
    "https://ivgraph.com/v1/graph/search",
    headers={"Authorization": "Bearer ivg_your_token"},
    params={"q": "project", "workspace_id": "abc-123", "limit": 5}
)
data = resp.json()
const resp = await fetch(
  "https://ivgraph.com/v1/graph/search?q=project&workspace_id=abc-123&limit=5",
  { headers: { Authorization: "Bearer ivg_your_token" } }
);
const data = await resp.json();

응답:

{
  "query": "project",
  "total": 3,
  "results": [
    {"id": "550e8400-e29b-41d4-a716-446655440001", "type": "page", "title": "Project Alpha", "score": 0.95},
    {"id": "550e8400-e29b-41d4-a716-446655440002", "type": "database", "title": "Projects Tracker", "score": 0.72},
    {"id": "550e8400-e29b-41d4-a716-446655440003", "type": "page", "title": "Project Notes", "score": 0.61}
  ]
}

오류:

상태 의미
400 q 또는 workspace_id 누락, 검색어 길이 초과 또는 허용되지 않는 문자 포함
401 서비스 토큰이 없거나 유효하지 않음
403 토큰에 graph:search 권한 범위가 없거나 워크스페이스가 허용 목록에 없음
404 이 워크스페이스에 동기화된 데이터가 없음
429 요청 제한 초과

GET /v1/graph/nodes/{node_id}/

단일 노드를 안전하게 제공할 수 있는 모든 필드와 함께 조회해요. 제목, 유형, URL, 아이콘, 연결 수, pagerank, 속성이 포함돼요.

권한 범위: graph:read

매개변수:

매개변수 유형 필수 여부 설명
node_id UUID 필수 노드 ID (URL 경로에 포함)
workspace_id string 필수 대상 워크스페이스 UUID

요청 예시:

curl -H "Authorization: Bearer ivg_your_token" \
  "https://ivgraph.com/v1/graph/nodes/550e8400-e29b-41d4-a716-446655440001/?workspace_id=abc-123"
import requests

node_id = "550e8400-e29b-41d4-a716-446655440001"
resp = requests.get(
    f"https://ivgraph.com/v1/graph/nodes/{node_id}/",
    headers={"Authorization": "Bearer ivg_your_token"},
    params={"workspace_id": "abc-123"}
)
node = resp.json()["node"]
const nodeId = "550e8400-e29b-41d4-a716-446655440001";
const resp = await fetch(
  `https://ivgraph.com/v1/graph/nodes/${nodeId}/?workspace_id=abc-123`,
  { headers: { Authorization: "Bearer ivg_your_token" } }
);
const { node } = await resp.json();

응답:

{
  "node": {
    "id": "550e8400-e29b-41d4-a716-446655440001",
    "type": "page",
    "title": "Project Alpha",
    "url": "https://www.notion.so/Project-Alpha-550e8400e29b41d4a716446655440001",
    "icon": {"type": "emoji", "emoji": "\ud83d\ude80"},
    "connections_in": 5,
    "connections_out": 12,
    "connections_total": 17,
    "pagerank": 0.42,
    "properties": {}
  }
}

오류:

상태 의미
400 node_id 형식이 유효하지 않거나 workspace_id가 누락됨
401 서비스 토큰이 없거나 유효하지 않음
403 토큰에 graph:read 권한 범위가 없거나 허용되지 않은 워크스페이스임
404 노드를 찾을 수 없거나 워크스페이스에 동기화된 데이터가 없음
429 요청 제한 초과

GET /v1/graph/content/{page_id}/

페이지 콘텐츠를 마크다운과 일반 텍스트로 조회해요. 콘텐츠는 Airbyte를 통해 동기화된 노션 블록에서 추출해요.

권한 범위: graph:read

매개변수:

매개변수 유형 필수 여부 설명
page_id UUID 필수 페이지 ID (URL 경로에 포함)
workspace_id string 필수 대상 워크스페이스 UUID

요청 예시:

curl -H "Authorization: Bearer ivg_your_token" \
  "https://ivgraph.com/v1/graph/content/550e8400-e29b-41d4-a716-446655440001/?workspace_id=abc-123"
import requests

page_id = "550e8400-e29b-41d4-a716-446655440001"
resp = requests.get(
    f"https://ivgraph.com/v1/graph/content/{page_id}/",
    headers={"Authorization": "Bearer ivg_your_token"},
    params={"workspace_id": "abc-123"}
)
content = resp.json()
print(content["markdown"])
const pageId = "550e8400-e29b-41d4-a716-446655440001";
const resp = await fetch(
  `https://ivgraph.com/v1/graph/content/${pageId}/?workspace_id=abc-123`,
  { headers: { Authorization: "Bearer ivg_your_token" } }
);
const { markdown, plain_text } = await resp.json();

응답:

{
  "page_id": "550e8400-e29b-41d4-a716-446655440001",
  "title": "Project Alpha",
  "markdown": "# Project Alpha\n\nThis is the main project page.\n\n## Goals\n\n- Launch beta by Q2\n- Reach 100 users",
  "plain_text": "Project Alpha\nThis is the main project page.\nGoals\nLaunch beta by Q2\nReach 100 users",
  "has_content": true
}

오류:

상태 의미
400 page_id 형식이 유효하지 않거나 workspace_id가 누락됨
401 서비스 토큰이 없거나 유효하지 않음
403 토큰에 graph:read 권한 범위가 없거나 허용되지 않은 워크스페이스임
404 페이지를 찾을 수 없거나 워크스페이스에 동기화된 데이터가 없음
429 요청 제한 초과

GET /v1/graph/neighbors/{node_id}/

BFS 탐색으로 지정된 깊이까지 이웃 노드와 간선을 반환해요. 특정 노드 주변의 그래프 구조를 살펴볼 때 유용해요.

권한 범위: graph:neighbors

매개변수:

매개변수 유형 필수 여부 기본값 설명
node_id UUID 필수 — 시작 노드 ID (URL 경로에 포함)
workspace_id string 필수 — 대상 워크스페이스 UUID
depth int 선택 1 탐색 깊이 (최대 3)
limit int 선택 20 반환할 이웃 노드의 최대 수 (최대 50개)
direction string 선택 both 간선 방향: in, out 또는 both

요청 예시:

curl -H "Authorization: Bearer ivg_your_token" \
  "https://ivgraph.com/v1/graph/neighbors/550e8400-e29b-41d4-a716-446655440001/?workspace_id=abc-123&depth=2&limit=10"
import requests

node_id = "550e8400-e29b-41d4-a716-446655440001"
resp = requests.get(
    f"https://ivgraph.com/v1/graph/neighbors/{node_id}/",
    headers={"Authorization": "Bearer ivg_your_token"},
    params={"workspace_id": "abc-123", "depth": 2, "limit": 10}
)
data = resp.json()
print(f"Found {data['total']} neighbors")
const nodeId = "550e8400-e29b-41d4-a716-446655440001";
const resp = await fetch(
  `https://ivgraph.com/v1/graph/neighbors/${nodeId}/?workspace_id=abc-123&depth=2&limit=10`,
  { headers: { Authorization: "Bearer ivg_your_token" } }
);
const { neighbors, edges, total } = await resp.json();

응답:

{
  "node_id": "550e8400-e29b-41d4-a716-446655440001",
  "depth": 2,
  "total": 4,
  "neighbors": [
    {"id": "550e8400-e29b-41d4-a716-446655440010", "type": "page", "title": "Sprint Planning"},
    {"id": "550e8400-e29b-41d4-a716-446655440011", "type": "database", "title": "Tasks"},
    {"id": "550e8400-e29b-41d4-a716-446655440012", "type": "page", "title": "Design Doc"},
    {"id": "550e8400-e29b-41d4-a716-446655440013", "type": "user", "title": "Alice"}
  ],
  "edges": [
    {"source": "550e8400-e29b-41d4-a716-446655440001", "target": "550e8400-e29b-41d4-a716-446655440010", "type": "reference"},
    {"source": "550e8400-e29b-41d4-a716-446655440001", "target": "550e8400-e29b-41d4-a716-446655440011", "type": "parent"},
    {"source": "550e8400-e29b-41d4-a716-446655440010", "target": "550e8400-e29b-41d4-a716-446655440012", "type": "mention"},
    {"source": "550e8400-e29b-41d4-a716-446655440012", "target": "550e8400-e29b-41d4-a716-446655440013", "type": "mention"}
  ]
}

오류:

상태 의미
400 node_id 형식이 유효하지 않거나 workspace_id가 누락됨
401 서비스 토큰이 없거나 유효하지 않음
403 토큰에 graph:neighbors 권한 범위가 없거나 허용되지 않은 워크스페이스임
404 노드를 찾을 수 없거나 워크스페이스에 동기화된 데이터가 없음
429 요청 제한 초과

POST /v1/graph/traverse/

BFS로 두 노드 사이의 최단 경로를 찾아요. 경로를 노드가 경로 순서대로 나열된 목록으로 반환하며, 최대 깊이 내에 경로가 없으면 null을 반환해요.

권한 범위: graph:neighbors

요청 본문 (JSON):

매개변수 유형 필수 여부 기본값 설명
start_id UUID 필수 — 시작 노드
target_id UUID 필수 — 대상 노드
workspace_id string 필수 — 대상 워크스페이스 UUID
max_depth int 선택 3 최대 탐색 깊이 (최대 3)

요청 예시:

curl -X POST "https://ivgraph.com/v1/graph/traverse/" \
  -H "Authorization: Bearer ivg_your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "start_id": "550e8400-e29b-41d4-a716-446655440001",
    "target_id": "550e8400-e29b-41d4-a716-446655440012",
    "workspace_id": "abc-123"
  }'
import requests

resp = requests.post(
    "https://ivgraph.com/v1/graph/traverse/",
    headers={
        "Authorization": "Bearer ivg_your_token",
        "Content-Type": "application/json"
    },
    json={
        "start_id": "550e8400-e29b-41d4-a716-446655440001",
        "target_id": "550e8400-e29b-41d4-a716-446655440012",
        "workspace_id": "abc-123"
    }
)
path = resp.json()["path"]
const resp = await fetch("https://ivgraph.com/v1/graph/traverse/", {
  method: "POST",
  headers: {
    Authorization: "Bearer ivg_your_token",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    start_id: "550e8400-e29b-41d4-a716-446655440001",
    target_id: "550e8400-e29b-41d4-a716-446655440012",
    workspace_id: "abc-123"
  })
});
const { path, path_length } = await resp.json();

응답 (경로를 찾은 경우):

{
  "start": "550e8400-e29b-41d4-a716-446655440001",
  "target": "550e8400-e29b-41d4-a716-446655440012",
  "path_length": 2,
  "path": [
    {"id": "550e8400-e29b-41d4-a716-446655440001", "type": "page", "title": "Project Alpha"},
    {"id": "550e8400-e29b-41d4-a716-446655440010", "type": "page", "title": "Sprint Planning"},
    {"id": "550e8400-e29b-41d4-a716-446655440012", "type": "page", "title": "Design Doc"}
  ]
}

응답 (경로가 없는 경우):

{
  "start": "550e8400-e29b-41d4-a716-446655440001",
  "target": "550e8400-e29b-41d4-a716-446655440099",
  "path_length": null,
  "path": []
}

오류:

상태 의미
400 start_id/target_id/workspace_id가 누락되었거나 유효하지 않음
401 서비스 토큰이 없거나 유효하지 않음
403 토큰에 graph:neighbors 권한 범위가 없거나 허용되지 않은 워크스페이스임
404 시작 노드 또는 대상 노드를 찾을 수 없거나 동기화된 데이터가 없음
429 요청 제한 초과

자체 설명형 명세

GET /v1/은 전체 API 명세를 JSON으로 반환해요. 인증은 필요하지 않아요.

curl "https://ivgraph.com/v1/"

모든 엔드포인트, 매개변수, 응답 스키마, 요청 제한, 권한 범위가 담긴 기계 판독 가능한 JSON을 반환해요. LLM 에이전트가 프로그래밍 방식으로 API를 파악할 때 유용해요.