O que Notion faz?
Interaja com o Notion de duas maneiras. O mesmo token de integração funciona para ambas — escolha de acordo com o que está disponível.
◆ ntn CLI — A CLI oficial do Notion. Sintaxe mais curta, upload de arquivos em uma linha, necessário para Workers. Apenas macOS + Linux a partir de maio de 2026 (suporte para Windows "em breve"). Padrão quando instalado.
◆ HTTP + curl — Funciona em todos os lugares, incluindo Windows. Fallback padrão quando o ntn não está instalado.
Configuração
1. Obtenha um token de integração (necessário para ambos os caminhos)
- Crie uma integração em https://notion.so/my-integrations
- Copie a chave da API (começa com
ntn_ousecret_) - Armazene em
~/.hermes/.env:NOTION_API_KEY=ntn_sua_chave_aqui - Compartilhe as páginas/bases de dados alvo com a integração no Notion: menu da página
...→Conectar a→ nome da sua integração. Sem isso, a API retorna 404 para essa página, mesmo que ela exista.
2. Instale o ntn (caminho preferido no macOS / Linux)
# Recomendado
curl -fsSL https://ntn.dev | bash
# Ou via npm (requer Node 22+, npm 10+)
npm install --global ntn
ntn --version # verificar
Pule o ntn login — use o token de integração diretamente. Isso funciona sem cabeçalho (headless), sem necessidade de navegador:
export NOTION_API_TOKEN=$NOTION_API_KEY # ntn lê NOTION_API_TOKEN
export NOTION_KEYRING=0 # não tenta usar o chaveiro do SO
Adicione essas exportações ao seu perfil de shell (ou a ~/.hermes/.env) para que toda sessão as herde.
3. Escolha o caminho em tempo de execução
if command -v ntn >/dev/null 2>&1; then
# usar ntn
else
# fallback para curl
fi
Usuários do Windows: pule a etapa 2 completamente até que o ntn nativo seja lançado — o Caminho B funciona bem. Se quiser a ergonomia da CLI agora, instale o ntn dentro do WSL2.
Conceitos Básicos da API
Notion-Version: 2025-09-03 é obrigatória em todas as requisições HTTP. O ntn lida com isso para você. Nesta versão, o que os usuários chamam de "bases de dados" (databases) são chamados de fontes de dados (data sources) na API.
Caminho A — CLI ntn (preferido, macOS / Linux)
Chamadas diretas à API (atalho para curl)
ntn api v1/users # GET
ntn api v1/pages parent[page_id]=abc123 \ # POST com corpo inline
properties[title][0][text][content]="Notas"
ntn api v1/pages/abc123 -X PATCH archived:=true # PATCH; := é para não-string (bool/num/null)
Notas de sintaxe:
chave=valor— campos stringchave[aninhado]=valor— campos de objeto aninhadoschave:=valor— atribuição tipada (booleanos, números, null, arrays)
Pesquisar
ntn api v1/search query="título da página"
Ler metadados da página
ntn api v1/pages/{page_id}
Ler página como Markdown (amigável para agente)
ntn api v1/pages/{page_id}/markdown
Ler conteúdo da página como blocos
ntn api v1/blocks/{page_id}/children
Criar página a partir de Markdown
ntn api v1/pages \
parent[page_id]=xxx \
properties[title][0][text][content]="Notas da reunião" \
markdown="# Pauta
- Roadmap Q3
- Contratação"
Atualizar página com Markdown
ntn api v1/pages/{page_id}/markdown -X PATCH \
markdown="## Atualização
O protótipo foi enviado."
Consultar uma base de dados (fonte de dados)
ntn api v1/data_sources/{data_source_id}/query -X POST \
filter[property]=Status filter[select][equals]=Ativo
Para consultas complexas com sorts, múltiplas cláusulas de filtro ou lógica composta, use pipe com JSON:
echo '{"filter": {"property": "Status", "select": {"equals": "Ativo"}}, "sorts": [{"property": "Data", "direction": "descending"}]}' | \
ntn api v1/data_sources/{data_source_id}/query -X POST --json -
Upload de arquivos (uma linha — maior ganho da CLI)
ntn files create < foto.png
ntn files create --external-url https://exemplo.com/foto.png
ntn files list
Compare com o fluxo HTTP de 3 etapas (criar upload → enviar bytes → referenciar).
Variáveis de ambiente úteis
| Variável | Efeito |
|---|---|
NOTION_API_TOKEN | Token de autenticação (substitui o chaveiro) — defina como seu token de integração |
NOTION_KEYRING=0 | Credenciais baseadas em arquivo em ~/.config/notion/auth.json em vez do chaveiro do SO |
NOTION_WORKSPACE_ID | Pula o prompt de seleção de workspace |
Caminho B — HTTP + curl (multiplataforma, padrão no Windows)
Todas as requisições seguem este padrão:
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"
No Windows, o curl incluído no Windows 10+ funciona diretamente. Usuários do PowerShell também podem usar Invoke-RestMethod.
Pesquisar
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": "título da página"}'
Ler metadados da página
curl -s "https://api.notion.com/v1/pages/{page_id}" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03"
Ler página como Markdown (amigável para agente)
Mais fácil de alimentar um modelo do que o JSON de blocos.
curl -s "https://api.notion.com/v1/pages/{page_id}/markdown" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03"
Ler conteúdo da página como blocos (quando precisar de estrutura)
curl -s "https://api.notion.com/v1/blocks/{page_id}/children" \
-H "Authorization: Bearer $NOTION_API_KEY" \
-H "Notion-Version: 2025-09-03"
Criar página a partir de Markdown
POST /v1/pages aceita um parâmetro de corpo markdown.
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": "Notas da reunião"}}]},
"markdown": "# Pauta\n\n- Roadmap Q3\n- Contratação\n\n## Decisões\n- MVP na sexta"
}'
Atualizar página com Markdown
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": "## Atualização\n\nO protótipo foi enviado."}'
Criar página em uma base de dados (propriedades tipadas)
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": {
"Nome": {"title": [{"text": {"content": "Novo Item"}}]},
"Status": {"select": {"name": "A fazer"}}
}
}'
Consultar uma base de dados (fonte de dados)
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": "Ativo"}},
"sorts": [{"property": "Data", "direction": "descending"}]
}'
Criar uma base de dados
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": "Minha Base de Dados"}}],
"properties": {
"Nome": {"title": {}},
"Status": {"select": {"options": [{"name": "A fazer"}, {"name": "Concluído"}]}},
"Data": {"date": {}}
}
}'
Atualizar propriedades da página
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": "Concluído"}}}}'
Anexar blocos a uma página
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": "Olá do Hermes!"}}]}}
]
}'
Upload de arquivos (fluxo de 3 etapas)
# 1. Criar upload
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": "foto.png", "content_type": "image/png"}'
# 2. Enviar bytes para a upload_url retornada acima
curl -s -X PUT "{upload_url}" --data-binary @foto.png
# 3. Referenciar {file_upload_id} no payload de uma página/bloco
Tipos de Propriedade
Formatos comuns de propriedade para itens de base de dados:
- Título:
{"title": [{"text": {"content": "..."}}]} - Texto rico:
{"rich_text": [{"text": {"content": "..."}}]} - Seleção:
{"select": {"name": "Opção"}} - Seleção múltipla:
{"multi_select": [{"name": "A"}, {"name": "B"}]} - Data:
{"date": {"start": "2026-01-15", "end": "2026-01-16"}} - Caixa de seleção:
{"checkbox": true} - Número:
{"number": 42} - URL:
{"url": "https://..."} - Email:
{"email": "[email protected]"} - Relação:
{"relation": [{"id": "page_id"}]}
Versão da API 2025-09-03 — Bases de Dados vs Fontes de Dados
- Bases de dados se tornaram fontes de dados. Use endpoints
/data_sources/para consultas e recuperação. - Dois IDs por base de dados:
database_idedata_source_id.database_idao criar páginas:parent: {"database_id": "..."}data_source_idao consultar:POST /v1/data_sources/{id}/query
- A pesquisa retorna bases de dados como
"object": "data_source"com o campodata_source_id.
Workers do Notion (avançado, requer ntn)
Workers são programas TypeScript que o Notion hospeda para você. Um worker pode expor qualquer combinação de:
- Sincronizações — puxar dados de APIs externas para uma base de dados do Notion em um agendamento (padrão 30 min).
- Ferramentas — aparecem como ferramentas chamáveis dentro dos Agentes Personalizados do Notion.
- Webhooks — receber eventos HTTP de serviços externos (GitHub, Stripe, etc.) e agir no Notion.
Plano / restrição de plataforma:
- A CLI funciona em todos os planos. Implantar Workers requer Business ou Enterprise.
ntné apenas macOS/Linux a partir de maio de 2026. Usuários do Windows precisam de WSL2 ou esperar pelo suporte nativo.- Gratuito até 11 de agosto de 2026; medido em créditos do Notion após.
Worker Mínimo
ntn workers new meu-worker # scaffold
cd meu-worker
# Editar src/index.ts
ntn workers deploy --name meu-worker
src/index.ts:
import { Worker } from "@notionhq/workers";
const worker = new Worker();
export default worker;
worker.tool("saudar", {
title: "Saudar um Usuário",
description: "Retorna uma saudação amigável",
inputSchema: { type: "object", properties: { nome: { type: "string" } }, required: ["nome"] },
execute: async ({ nome }) => `Olá, ${nome}!`,
});
Capacidade de Webhook
worker.webhook("onGithubPush", {
title: "Manipulador de Push do GitHub",
execute: async (events, { notion }) => {
for (const event of events) {
// event.body, event.rawBody (para verificação de assinatura), event.headers
console.log("entrega recebida", event.deliveryId);
}
},
});
Após implantar: ntn workers webhooks list mostra a URL que o Notion gera. Trate essa URL como um segredo — qualquer pessoa com ela pode enviar eventos a menos que você adicione verificação de assinatura.
Comandos do ciclo de vida do Worker
ntn workers deploy
ntn workers list
ntn workers exec <chave-capacidade> -d '{"nome": "mundo"}'
ntn workers sync trigger <chave> # executar uma sincronização agora
ntn workers sync pause <chave>
ntn workers env set GITHUB_WEBHOOK_SECRET=...
ntn workers runs list # invocações recentes
ntn workers runs logs <id-da-execução>
ntn workers webhooks list
Ao ser solicitado a construir um Worker, faça o scaffold com ntn workers new, escreva o código em src/index.ts, defina quaisquer segredos com ntn workers env set e implante. A documentação do Notion em https://developers.notion.com/workers cobre a superfície completa da API.
Markdown no Estilo Notion (usado pelos endpoints /markdown)
CommonMark padrão mais tags no estilo XML para blocos específicos do Notion. Use tabs para indentação.
Blocos além do CommonMark:
<callout icon="🎯" color="blue_bg">
Envie o MVP até **sexta-feira**.
</callout>
<details color="gray">
<summary>Título do expansível</summary>
Filhos indentados com um tab
</details>
<columns>
<column>Lado esquerdo</column>
<column>Lado direito</column>
</columns>
<table_of_contents color="gray"/>
Em linha:
- Menções:
<mention-user url="..."/>,<mention-page url="...">Título</mention-page>,<mention-date start="2026-05-15"/> - Sublinhado:
<span underline="true">texto</span> - Cor:
<span color="blue">texto</span>ou em nível de bloco{color="blue"}na primeira linha - Matemática: inline
$x^2$, bloco$$ ... $$ - Citações:
[^https://exemplo.com]
Cores: gray brown orange yellow green blue purple pink red, mais variantes *_bg para fundos.
Cabeçalhos 5/6 são reduzidos a H4. Múltiplas linhas > são renderizadas como blocos de citação separados — use <br> dentro de um único > para citações de várias linhas.
Escolhendo o Caminho Certo
| Tarefa | macOS / Linux | Windows |
|---|---|---|
| Ler/escrever páginas, pesquisar, consultar bases de dados | ntn api ... | curl |
| Ler uma página para um agente resumir | ntn api v1/pages/{id}/markdown | curl endpoint /markdown |
| Fazer upload de um arquivo | ntn files create < arquivo | Fluxo HTTP de 3 etapas |
| Exploração única da API | ntn api ... | curl |
| Construir uma sincronização / webhook / ferramenta de agente hospedada pelo Notion | ntn workers ... | WSL2 + ntn workers ... |
Notas
- IDs de página/base de dados são UUIDs (com ou sem hífens — ambos aceitos).
- Limite de taxa: ~3 requisições/segundo em média. A CLI não contorna isso.
- A API não pode definir filtros de visualização de base de dados — isso é apenas pela interface.
- Use
"is_inline": trueao criar fontes de dados para incorporá-las em uma página. - Sempre passe
-sao curl para suprimir barras de progresso (saída mais limpa para o agente). - Use pipe com JSON através do
jqao ler:... | jq '.results[0].properties'. - O Notion também oferece um servidor MCP agora (
Notion