Was macht Notion?
Sprich auf zwei Arten mit Notion. Derselbe Integrationstoken funktioniert für beide – wähle nach Verfügbarkeit.
◆ ntn CLI — Offizielles CLI von Notion. Kürzere Syntax, einzeilige Datei-Uploads, wird für Workers benötigt. macOS + Linux nur Stand Mai 2026 (Windows-Support "kommt bald"). Standard, wenn installiert.
◆ HTTP + curl — funktioniert überall, inklusive Windows. Standard-Fallback, wenn ntn nicht installiert ist.
Einrichtung
1. Einen Integrationstoken holen (für beide Pfade erforderlich)
- Erstelle eine Integration unter https://notion.so/my-integrations
- Kopiere den API-Key (beginnt mit
ntn_odersecret_) - Speichere ihn in
~/.hermes/.env:NOTION_API_KEY=ntn_dein_key_hier - Teile die Zielseiten/Datenbanken mit der Integration in Notion: Seitenmenü
...→Verknüpfen mit→ dein Integrationsname. Ohne dies gibt die API 404 für diese Seite zurück, obwohl sie existiert.
2. ntn installieren (bevorzugter Pfad unter macOS / Linux)
# Empfohlen
curl -fsSL https://ntn.dev | bash
# Oder via npm (benötigt Node 22+, npm 10+)
npm install –global ntn
ntn --version # überprüfen
Überspringe ntn login – verwende stattdessen den Integrationstoken. Dies funktioniert headless, kein Browser nötig:
export NOTION_API_TOKEN=$NOTION_API_KEY # ntn liest NOTION_API_TOKEN
export NOTION_KEYRING=0 # nicht versuchen, die OS-Keychain zu verwenden
Füge diese Exporte zu deinem Shell-Profil (oder zu ~/.hermes/.env) hinzu, damit jede Sitzung sie erbt.
3. Zur Laufzeit den Pfad wählen
if command -v ntn >/dev/null 2>&1; then
# ntn verwenden
else
# auf curl zurückfallen
fi
Windows-Benutzer: Überspringe Schritt 2 vollständig, bis das native ntn erscheint – Pfad B funktioniert einwandfrei. Wenn du jetzt CLI-Komfort möchtest, installiere ntn in WSL2.
API-Grundlagen
Notion-Version: 2025-09-03 ist bei allen HTTP-Anfragen erforderlich. ntn erledigt dies für dich. In dieser Version werden die von Benutzern sogenannten Datenbanken in der API als Data Sources bezeichnet.
Pfad A – ntn CLI (bevorzugt, macOS / Linux)
Rohe API-Aufrufe (Kurzform für curl)
ntn api v1/users # GET
ntn api v1/pages parent[page_id]=abc123 \ # POST mit Inline-Body
properties[title][0][text][content]="Notizen"
ntn api v1/pages/abc123 -X PATCH archived:=true # PATCH; := bedeutet Nicht-String (bool/num/null)
Syntax-Hinweise:
key=value— Zeichenfolgenfelderkey[nested]=value— verschachtelte Objektfelderkey:=value— typisierte Zuweisung (Booleans, Zahlen, null, Arrays)
Suche
ntn api v1/search query="Seitentitel"
Seiten-Metadaten lesen
ntn api v1/pages/{page_id}
Seite als Markdown lesen (agentenfreundlich)
ntn api v1/pages/{page_id}/markdown
Seiteninhalt als Blöcke lesen
ntn api v1/blocks/{page_id}/children
Seite aus Markdown erstellen
ntn api v1/pages \
parent[page_id]=xxx \
properties[title][0][text][content]="Notizen vom Meeting" \
markdown="# Tagesordnung
- Q3-Roadmap
- Einstellung"
Seite mit Markdown patchen
ntn api v1/pages/{page_id}/markdown -X PATCH \
markdown="## Update
Prototyp ausgeliefert."
Eine Datenbank (Data Source) abfragen
ntn api v1/data_sources/{data_source_id}/query -X POST \
filter[property]=Status filter[select][equals]=Aktiv
Für komplexe Abfragen mit sorts, mehreren Filterklauseln oder zusammengesetzter Logik JSON einlesen:
echo '{"filter": {"property": "Status", "select": {"equals": "Aktiv"}}, "sorts": [{"property": "Datum", "direction": "descending"}]}' | \
ntn api v1/data_sources/{data_source_id}/query -X POST --json -
Datei-Uploads (Einzeiler – größter CLI-Vorteil)
ntn files create < photo.png
ntn files create –external-url https://example.com/photo.png
ntn files list
Vergleiche mit dem 3-Schritte-HTTP-Flow (Upload erstellen → PUT-Bytes → Referenz).
Nützliche Umgebungsvariablen
| Variable | Effekt |
|---|---|
NOTION_API_TOKEN | Auth-Token (überschreibt Keychain) – setze dies auf deinen Integrationstoken |
NOTION_KEYRING=0 | Dateibasierte Anmeldedaten in ~/.config/notion/auth.json anstelle der OS-Keychain |
NOTION_WORKSPACE_ID | Überspringe die Workspace-Auswahlaufforderung |
Pfad B – HTTP + curl (plattformübergreifend, Standard unter Windows)
Alle Anfragen folgen diesem Muster:
curl -s -X GET "https://api.notion.com/v1/..." \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json"
Unter Windows funktioniert das mitgelieferte curl (Windows 10+) sofort. PowerShell-Benutzer können auch Invoke-RestMethod verwenden.
Suche
curl -s -X POST "https://api.notion.com/v1/search" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{"query": "Seitentitel"}'
Seiten-Metadaten lesen
curl -s "https://api.notion.com/v1/pages/{page_id}" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03"
Seite als Markdown lesen (agentenfreundlich)
Einfacher einem Modell zu füttern als Block-JSON.
curl -s "https://api.notion.com/v1/pages/{page_id}/markdown" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03"
Seiteninhalt als Blöcke lesen (wenn du Struktur brauchst)
curl -s "https://api.notion.com/v1/blocks/{page_id}/children" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03"
Seite aus Markdown erstellen
POST /v1/pages akzeptiert einen markdown-Body-Parameter.
curl -s -X POST "https://api.notion.com/v1/pages" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{
"parent": {"page_id": "xxx"},
"properties": {"title": [{"text": {"content": "Notizen vom Meeting"}}]},
"markdown": "# Tagesordnung\n\n- Q3-Roadmap\n- Einstellung\n\n## Entscheidungen\n- MVP am Freitag ausliefern"
}'
Seite mit Markdown patchen
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}/markdown" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{"markdown": "## Update\n\nPrototyp ausgeliefert."}'
Seite in einer Datenbank erstellen (typisierte Eigenschaften)
curl -s -X POST "https://api.notion.com/v1/pages" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{
"parent": {"database_id": "xxx"},
"properties": {
"Name": {"title": [{"text": {"content": "Neues Element"}}]},
"Status": {"select": {"name": "Zu erledigen"}}
}
}'
Eine Datenbank (Data Source) abfragen
curl -s -X POST "https://api.notion.com/v1/data_sources/{data_source_id}/query" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{
"filter": {"property": "Status", "select": {"equals": "Aktiv"}},
"sorts": [{"property": "Datum", "direction": "descending"}]
}'
Eine Datenbank erstellen
curl -s -X POST "https://api.notion.com/v1/data_sources" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{
"parent": {"page_id": "xxx"},
"title": [{"text": {"content": "Meine Datenbank"}}],
"properties": {
"Name": {"title": {}},
"Status": {"select": {"options": [{"name": "Zu erledigen"}, {"name": "Erledigt"}]}},
"Datum": {"date": {}}
}
}'
Seiten-Eigenschaften aktualisieren
curl -s -X PATCH "https://api.notion.com/v1/pages/{page_id}" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{"properties": {"Status": {"select": {"name": "Erledigt"}}}}'
Blöcke an eine Seite anhängen
curl -s -X PATCH "https://api.notion.com/v1/blocks/{page_id}/children" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{
"children": [
{"object": "block", "type": "paragraph", "paragraph": {"rich_text": [{"text": {"content": "Hallo von Hermes!"}}]}}
]
}'
Datei-Uploads (3-Schritte-Flow)
# 1. Upload erstellen
curl -s -X POST "https://api.notion.com/v1/file_uploads" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03" \
-H "Content-Type: application/json" \
-d '{"filename": "photo.png", "content_type": "image/png"}'
# 2. PUT-Bytes an die oben zurückgegebene upload_url senden
curl -s -X PUT "{upload_url}" --data-binary @photo.png
# 3. {file_upload_id} in einer Seiten-/Block-Payload referenzieren
Eigenschaftstypen
Gängige Eigenschaftsformate für Datenbankeinträge:
- Titel:
{"title": [{"text": {"content": "..."}}]} - Rich-Text:
{"rich_text": [{"text": {"content": "..."}}]} - Auswahl:
{"select": {"name": "Option"}} - Mehrfachauswahl:
{"multi_select": [{"name": "A"}, {"name": "B"}]} - Datum:
{"date": {"start": "2026-01-15", "end": "2026-01-16"}} - Kontrollkästchen:
{"checkbox": true} - Zahl:
{"number": 42} - URL:
{"url": "https://..."} - E-Mail:
{"email": "[email protected]"} - Relation:
{"relation": [{"id": "page_id"}]}
API-Version 2025-09-03 – Datenbanken vs. Data Sources
- Datenbanken wurden zu Data Sources. Verwende
/data_sources/-Endpunkte für Abfragen und Abrufe. - Zwei IDs pro Datenbank:
database_idunddata_source_id.database_idbeim Erstellen von Seiten:parent: {"database_id": "..."}data_source_idbeim Abfragen:POST /v1/data_sources/{id}/query
- Die Suche gibt Datenbanken als
"object": "data_source"mit dem Felddata_source_idzurück.
Notion Workers (fortgeschritten, erfordert ntn)
Worker sind TypeScript-Programme, die Notion für dich hostet. Ein Worker kann jede Kombination von Folgendem bereitstellen:
- Syncs – Daten aus externen APIs in eine Notion-Datenbank ziehen (Standard 30 Min.).
- Tools – erscheinen als aufrufbare Werkzeuge innerhalb von Notions Custom Agents.
- Webhooks – HTTP-Ereignisse von externen Diensten (GitHub, Stripe etc.) empfangen und in Notion handeln.
Plan-/Plattform-Beschränkungen:
- CLI funktioniert auf allen Plänen. Das Bereitstellen von Workern erfordert Business oder Enterprise.
ntnist Stand Mai 2026 nur für macOS/Linux verfügbar. Windows-Benutzer benötigen WSL2 oder müssen auf native Unterstützung warten.- Bis zum 11. August 2026 kostenlos; danach verbrauchsabhängig abgerechnet mit Notion-Credits.
Minimaler Worker
ntn workers new my-worker # Gerüst erstellen
cd my-worker
# src/index.ts bearbeiten
ntn workers deploy --name my-worker
src/index.ts:
import { Worker } from "@notionhq/workers";
const worker = new Worker();
export default worker;
worker.tool("greet", {
title: "Einen Benutzer begrüßen",
description: "Gibt eine freundliche Begrüßung zurück",
inputSchema: { type: "object", properties: { name: { type: "string" } }, required: ["name"] },
execute: async ({ name }) => `Hallo, ${name}!`,
});
Webhook-Funktionalität
worker.webhook("onGithubPush", {
title: "GitHub Push Handler",
execute: async (events, { notion }) => {
for (const event of events) {
// event.body, event.rawBody (zur Signaturprüfung), event.headers
console.log("Zustellung erhalten", event.deliveryId);
}
},
});
Nach dem Deployment: ntn workers webhooks list zeigt die von Notion generierte URL. Behandle diese URL als geheim – jeder, der sie hat, kann Ereignisse POSTen, es sei denn, du fügst eine Signaturprüfung hinzu.
Worker-Lebenszyklus-Befehle
ntn workers deploy
ntn workers list
ntn workers exec <capability-key> -d '{"name": "welt"}'
ntn workers sync trigger <key> # Sync jetzt ausführen
ntn workers sync pause <key>
ntn workers env set GITHUB_WEBHOOK_SECRET=...
ntn workers runs list # Letzte Aufrufe
ntn workers runs logs <run-id>
ntn workers webhooks list
Wenn du gebeten wirst, einen Worker zu erstellen, richte das Grundgerüst mit ntn workers new ein, schreibe den Code in src/index.ts, setze alle Geheimnisse mit ntn workers env set und stelle bereit. Die Notion-Dokumentation unter https://developers.notion.com/workers deckt die vollständige API-Oberfläche ab.
Notion-Flavored Markdown (verwendet von /markdown-Endpunkten)
Standard CommonMark plus XML-ähnliche Tags für Notion-spezifische Blöcke. Verwende Tabs für Einrückungen.
Blöcke, die über CommonMark hinausgehen:
<callout icon="🎯" color="blue_bg">
Liefere den MVP bis **Freitag** aus.
</callout>
<details color="gray">
<summary>Umschalt-Titel</summary>
Untergeordnete Elemente um einen Tab eingerückt
</details>
<columns>
<column>Linke Seite</column>
<column>Rechte Seite</column>
</columns>
<table_of_contents color="gray"/>
Inline:
- Erwähnungen:
<mention-user url="..."/>,<mention-page url="...">Titel</mention-page>,<mention-date start="2026-05-15"/> - Unterstreichung:
<span underline="true">Text</span> - Farbe:
<span color="blue">Text</span>oder blockweise{color="blue"}in der ersten Zeile - Mathematik: Inline
$x^2$, Block$$ ... $$ - Zitate:
[^https://example.com]
Farben: gray brown orange yellow green blue purple pink red, plus *_bg-Varianten für Hintergründe.
Die Überschriften 5/6 werden auf H4 reduziert. Mehrere >-Zeilen werden als separate Zitatblöcke gerendert – verwende <br> innerhalb eines einzelnen > für mehrzeilige Zitate.
Den richtigen Pfad wählen
| Aufgabe | macOS / Linux | Windows |
|---|---|---|
| Seiten lesen/schreiben, suchen, Datenbanken abfragen | ntn api ... | curl |
| Eine Seite lesen, damit ein Agent sie zusammenfassen kann | ntn api v1/pages/{id}/markdown | curl /markdown-Endpunkt |
| Eine Datei hochladen | ntn files create < datei | 3-Schritte-HTTP-Flow |
| Einmalige API-Erkundung | ntn api ... | curl |
| Einen von Notion gehosteten Sync/Webhook/Agenten-Tool erstellen | ntn workers ... | WSL2 + ntn workers ... |
Hinweise
- Seiten-/Datenbank-IDs sind UUIDs (mit oder ohne Bindestriche – beides wird akzeptiert).
- Ratenlimit: ~3 Anfragen/Sekunde im Durchschnitt. Das CLI umgeht dies nicht.
- Die API kann keine Datenbank-Ansichtsfilter setzen – das ist nur über die UI möglich.
- Verwende
"is_inline": truebeim Erstellen von Data Sources, um sie in eine Seite einzubetten. - Gib immer
-san curl weiter, um Fortschrittsbalken zu unterdrücken (sauberere Agentenausgabe). - Leite JSON durch
jqbeim Lesen:... | jq '.results[0].properties'. - Notion bietet jetzt auch einen MCP-Server an (`Notion
…
[gekürzt für die Übersetzung]