Integrações & API
Guia de Operação & Boas Práticas
Documentação completa de integração do Espaço Ágil via REST, autenticação por Bearer Token e catálogo OpenAPI.
Integrações
& API
Como puxar dados do Espaço Ágil de fora da aplicação — de um script ou de outro sistema — sem sessão de usuário logado.
Uma chave, 10 endpoints
Tudo em /api/v1, autenticado pelo mesmo header X-Api-Key. Nada de OAuth, nada de sessão.
Cobertura é parcial
Só a Base de Conhecimento e o Prompt Hub têm superfície pública. O resto (Squad, Retrospectiva, Daily Flow, Sprint Planner, Radar de Saúde, Brainstorming, Showcase, Jolt Hub, DevTools) existe apenas na API interna, autenticada por sessão — uma API key não abre nada neles.
- 1Vá em Admin → API Keys e clique em criar. Só quem tem acesso ao painel administrativo consegue.
- 2Dê um nome que identifique o consumidor ("bot do Slack", "script de backup") — é o que aparece na lista depois.
- 3Copie a chave
ask_…na hora. Ela é mostrada uma única vez: o Firestore guarda o documento com o próprio SHA-256 como id, não a chave. - 4Vazou ou não usa mais? Revogue na mesma tela — a chave para de funcionar na chamada seguinte.
A chave vai em todas as chamadas no header X-Api-Key. Cada uso atualiza lastUsedAt, e documento criado pela API guarda o prefixo do hash da chave em authorId — dá pra saber qual consumidor escreveu o quê.
https://espacoagil.com.br/api/v1 em produção, http://localhost:3000/api/v1 em dev.Base de Conhecimento
Listar, buscar, baixar e criar documentos da KB de fora da aplicação.
| Rota | O que faz | Parâmetros |
|---|---|---|
GET/api/v1/knowledge/docs | Lista documentos publicados, com busca e filtros.→ { docs[], page, pageSize, total, totalPages } — cada doc traz contentPreview de 240 caracteres, sem o conteúdo inteiro | q (título/conteúdo), category, tag, page (1-based, padrão 1), pageSize (padrão 20, máx 100) |
GET/api/v1/knowledge/docs/{id} | Documento completo, com o conteúdo convertido.→ documento + content no formato pedido | format = html (padrão) | md | txt |
GET/api/v1/knowledge/docs/{id}/download | Mesma coisa, mas como arquivo para download.→ corpo do arquivo + Content-Disposition: attachment com o título em slug | format = md (padrão) | html | txt |
POST/api/v1/knowledge/docs | Cria um documento novo já publicado.→ 201 com o documento salvo | body { title (obrigatório), content, category, tags: string[] | "a,b,c" } |
- A listagem nunca devolve o conteúdo inteiro — só o contentPreview. Para o texto completo, chame GET /docs/{id}.
- Documentos em lixeira (status trash/deleted) ficam fora de qualquer resposta, inclusive no acesso direto por id.
- Documento criado pela API fica com authorId "api:<8 primeiros caracteres do hash da chave>", então dá pra rastrear qual chave escreveu o quê.
- A busca por q é feita em memória, depois de ler a collection inteira: com uma KB muito grande a resposta fica lenta.
Prompt Hub
Consultar prompts/coleções públicas e publicar/atualizar skills de agentes por REST ou MCP.
| Rota | O que faz | Parâmetros |
|---|---|---|
GET/api/v1/prompt-hub/items | Lista prompts públicos.→ { items[], page, pageSize, total, totalPages } | q (título/descrição/conteúdo), authorId, tag, page (1-based), pageSize (máx 100) |
GET/api/v1/prompt-hub/items/{id} | Um prompt público completo.→ o prompt inteiro; 404 se for privado | — |
GET/api/v1/prompt-hub/collections | Lista coleções públicas (trilhas de prompts).→ { collections[], page, pageSize, total, totalPages } | ownerId, page (1-based), pageSize (máx 100) |
GET/api/v1/prompt-hub/collections/{id} | Uma coleção com os prompts embutidos.→ a coleção + items[] já resolvidos (só os públicos) | — |
POST/api/v1/prompt-hub/items | Importa ou cria uma skill/prompt (com suporte a SKILL.md e frontmatter YAML).→ o prompt/skill criado com id | title (ou name no frontmatter), content, description?, tags?, visibility? |
- Leitura só enxerga registros com visibility="public" — mesmo recorte que a regra do Firestore aplica a quem não tem sessão.
- Escrita habilitada via POST /api/v1/prompt-hub/items para ingestão automatizada de skills por IAs ou scripts externos.
- Suporta extração automática de metadados do YAML frontmatter (name, description) e blocos com quebra de linha (>-).
- Numa coleção, itens que ficaram privados depois de adicionados simplesmente somem do items[] — a coleção volta menor, sem erro.
Scrum Poker
Buscar estimativas de rodadas de planning poker já feitas, por texto livre.
| Rota | O que faz | Parâmetros |
|---|---|---|
GET/api/v1/poker/rounds | Busca estimativas de rodadas já feitas, por texto livre (tópico ou nota da rodada).→ { rounds[], page, pageSize, total, totalPages } — cada round traz topic, issueId, devPoints, qaPoints, timestamp, roomId | q (opcional; vazio lista as mais recentes), page (1-based, padrão 1), pageSize (máx 100) |
- Collection-group query em rooms/*/rounds (firestore.rules aberto pra isso, mesmo padrão de knowledge_kb/prompt_hub) — sem custar índice composto, filtro/ordenação são em memória.
- Sem campo estruturado de squad/projeto no Poker — a busca é textual sobre topic/note. O nome do serviço/projeto normalmente está dentro do texto da tarefa, não numa chave separada.
- votes/stats/rolePoints (voto individual por participante) nunca são repassados — só topic/issueId/devPoints/qaPoints/timestamp/roomId saem da rota.
- devPoints/qaPoints são pontos de estimativa por papel (dev = "codificação", qa = "teste"), não uma unidade de tempo fixa — depende do deck da sessão.
Buscar documentos — a request mínima
curl -s "https://espacoagil.com.br/api/v1/knowledge/docs?q=onboarding&page=1&pageSize=20" \ -H "X-Api-Key: ask_SUA_CHAVE_AQUI"
Trazer o conteúdo inteiro — o padrão em duas etapas
A listagem devolve só um contentPreview de 240 caracteres. Para o texto completo é preciso um segundo GET no id — de propósito, pra listar 50 documentos não trafegar megabytes.
const BASE = 'https://espacoagil.com.br';
const KEY = process.env.AGILE_SPACE_API_KEY;
// 1. acha os documentos
const lista = await fetch(
`${BASE}/api/v1/knowledge/docs?q=onboarding&pageSize=50`,
{ headers: { 'X-Api-Key': KEY } },
).then(r => r.json());
// 2. a listagem só traz contentPreview — o texto inteiro vem do detalhe
const documentos = await Promise.all(
lista.docs.map(d =>
fetch(`${BASE}/api/v1/knowledge/docs/${d.id}?format=md`, {
headers: { 'X-Api-Key': KEY },
}).then(r => r.json()),
),
);
console.log(documentos.map(d => d.content));Criar um documento
curl -X POST "https://espacoagil.com.br/api/v1/knowledge/docs" \
-H "X-Api-Key: ask_SUA_CHAVE_AQUI" \
-H "Content-Type: application/json" \
-d '{
"title": "Runbook de deploy",
"content": "<p>Passo a passo...</p>",
"category": "Operacao",
"tags": ["deploy", "runbook"]
}'Subir uma skill para o Prompt Hub (SKILL.md com frontmatter)
curl -X POST "https://espacoagil.com.br/api/v1/prompt-hub/items" \
-H "X-Api-Key: ask_SUA_CHAVE_AQUI" \
-H "Content-Type: application/json" \
-d '{
"content": "---\nname: map-delphi-project\ndescription: Diagnóstico arquitetural de projetos Delphi\n---\n# Guia de Mapeamento Delphi...",
"type": "skill",
"visibility": "public"
}'Erros
401Header X-Api-Key ausente, inválido ou de uma chave revogada.404Documento/prompt inexistente, privado ou na lixeira — a resposta é a mesma nos três casos, de propósito.400POST sem title, ou corpo que não é JSON válido.429Passou de 60 leituras ou 20 escritas por minuto naquela chave.500Falha ao falar com o Firestore.
O rate limit é contado em memória, por processo — com mais de uma réplica em produção o limite efetivo é por réplica, não global.