API LLM V1
API en lecture seule pour les agents LLM, les scripts d’automatisation et les intégrations. Donne accès aux données du graphe de l’espace de travail Notion : recherche, détails des nœuds, contenu des pages et parcours du graphe.
Présentation
| Propriété | Valeur |
|---|---|
| URL de base | /v1/graph/ |
| Authentification | Jeton de service (Authorization: Bearer ivg_*) |
| Format | JSON |
| Limites de débit | 20 requêtes par rafale de 10s, 600 requêtes par fenêtre de 15min |
| Spécification autodescriptive | GET /v1/ (sans authentification) |
Paramètres communs
Tous les points de terminaison nécessitent workspace_id :
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
| workspace_id | string (UUID) | oui | UUID de l’espace de travail Notion. Doit figurer parmi les workspace_ids autorisés par le jeton. |
Points de terminaison
GET /v1/graph/search/
Recherche les nœuds par titre dans l’ensemble d’un espace de travail. Utilise Elasticsearch s’il est disponible, sinon effectue la recherche en mémoire.
Portée : graph:search
Paramètres :
| Paramètre | Type | Obligatoire | Valeur par défaut | Description |
|---|---|---|---|---|
| q | string | oui | — | Requête de recherche (256 caractères max.) |
| workspace_id | string | oui | — | UUID de l’espace de travail cible |
| limit | int | non | 20 | Résultats par page (50 max.) |
| type | string | non | all | Filtre : page, database ou user |
Exemple de requête :
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();
Réponse :
{
"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}
]
}
Erreurs :
| Statut | Signification |
|---|---|
| 400 | q ou workspace_id manquant, requête trop longue ou caractères non autorisés |
| 401 | Jeton de service manquant ou invalide |
| 403 | Le jeton ne dispose pas de la portée graph:search ou l’espace de travail ne figure pas dans la liste des espaces autorisés |
| 404 | Aucune donnée synchronisée pour cet espace de travail |
| 429 | Limite de débit dépassée |
GET /v1/graph/nodes/{node_id}/
Récupère un seul nœud avec tous les champs pouvant être exposés sans risque : titre, type, URL, icône, nombres de connexions, pagerank et propriétés.
Portée : graph:read
Paramètres :
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
| node_id | UUID | oui | Identifiant du nœud (dans le chemin de l’URL) |
| workspace_id | string | oui | UUID de l’espace de travail cible |
Exemple de requête :
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();
Réponse :
{
"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": {}
}
}
Erreurs :
| Statut | Signification |
|---|---|
| 400 | Format de node_id invalide ou workspace_id manquant |
| 401 | Jeton de service manquant ou invalide |
| 403 | Le jeton ne dispose pas de la portée graph:read ou l’espace de travail n’est pas autorisé |
| 404 | Nœud introuvable ou aucune donnée synchronisée pour l’espace de travail |
| 429 | Limite de débit dépassée |
GET /v1/graph/content/{page_id}/
Récupère le contenu d’une page au format Markdown et en texte brut. Le contenu est extrait des blocs Notion synchronisés via Airbyte.
Portée : graph:read
Paramètres :
| Paramètre | Type | Obligatoire | Description |
|---|---|---|---|
| page_id | UUID | oui | Identifiant de la page (dans le chemin de l’URL) |
| workspace_id | string | oui | UUID de l’espace de travail cible |
Exemple de requête :
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();
Réponse :
{
"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
}
Erreurs :
| Statut | Signification |
|---|---|
| 400 | Format de page_id invalide ou workspace_id manquant |
| 401 | Jeton de service manquant ou invalide |
| 403 | Le jeton ne dispose pas de la portée graph:read ou l’espace de travail n’est pas autorisé |
| 404 | Page introuvable ou aucune donnée synchronisée pour l’espace de travail |
| 429 | Limite de débit dépassée |
GET /v1/graph/neighbors/{node_id}/
Parcours en largeur (BFS) qui renvoie les voisins et les arêtes jusqu’à une profondeur donnée. Utile pour explorer la structure locale du graphe autour d’un nœud.
Portée : graph:neighbors
Paramètres :
| Paramètre | Type | Obligatoire | Valeur par défaut | Description |
|---|---|---|---|---|
| node_id | UUID | oui | — | Identifiant du nœud de départ (dans le chemin de l’URL) |
| workspace_id | string | oui | — | UUID de l’espace de travail cible |
| depth | int | non | 1 | Profondeur du parcours (3 max.) |
| limit | int | non | 20 | Nombre maximal de voisins à renvoyer (50 max.) |
| direction | string | non | both | Sens des arêtes : in, out ou both |
Exemple de requête :
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();
Réponse :
{
"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"}
]
}
Erreurs :
| Statut | Signification |
|---|---|
| 400 | Format de node_id invalide ou workspace_id manquant |
| 401 | Jeton de service manquant ou invalide |
| 403 | Le jeton ne dispose pas de la portée graph:neighbors ou l’espace de travail n’est pas autorisé |
| 404 | Nœud introuvable ou aucune donnée synchronisée pour l’espace de travail |
| 429 | Limite de débit dépassée |
POST /v1/graph/traverse/
Trouve le chemin le plus court entre deux nœuds à l’aide d’un parcours en largeur (BFS). Renvoie le chemin sous forme de liste ordonnée de nœuds, ou null si aucun chemin n’existe dans la limite de la profondeur maximale.
Portée : graph:neighbors
Corps de la requête (JSON) :
| Paramètre | Type | Obligatoire | Valeur par défaut | Description |
|---|---|---|---|---|
| start_id | UUID | oui | — | Nœud de départ |
| target_id | UUID | oui | — | Nœud cible |
| workspace_id | string | oui | — | UUID de l’espace de travail cible |
| max_depth | int | non | 3 | Profondeur maximale du parcours (3 max.) |
Exemple de requête :
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();
Réponse (chemin trouvé) :
{
"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"}
]
}
Réponse (aucun chemin) :
{
"start": "550e8400-e29b-41d4-a716-446655440001",
"target": "550e8400-e29b-41d4-a716-446655440099",
"path_length": null,
"path": []
}
Erreurs :
| Statut | Signification |
|---|---|
| 400 | start_id/target_id/workspace_id manquant ou invalide |
| 401 | Jeton de service manquant ou invalide |
| 403 | Le jeton ne dispose pas de la portée graph:neighbors ou l’espace de travail n’est pas autorisé |
| 404 | Nœud de départ ou nœud cible introuvable, ou aucune donnée synchronisée |
| 429 | Limite de débit dépassée |
Spécification autodescriptive
GET /v1/ renvoie la spécification complète de l’API au format JSON. Aucune authentification requise.
curl "https://ivgraph.com/v1/"
La réponse est un document JSON exploitable par machine qui contient tous les points de terminaison, paramètres, schémas de réponse, limites de débit et portées. Les agents LLM peuvent ainsi découvrir l’API par programmation.