API REST para agentes

Os mesmos recursos do conector MCP, em HTTP simples, para Claude Code, scripts e outros agentes.

Autenticação e formato

Base: https://www.foundergrowth.app/api/v1. Toda chamada leva Authorization: Bearer fg_… (token de Configurações → Integrações). Limite: 60 chamadas por minuto por conta.

Sucesso: { "ok": true, "data": … }. Erro: { "error": "mensagem" } com 400 (entrada inválida), 401 (token), 404, 409 (estado não permite), 422 (texto recusado pelo filtro de voz) ou 429 (limite, com Retry-After).

Endpoints

GET /status

O que está esperando: drafts por status, drafts que o founder pediu para reescrever, ideias novas e quantas faltam, artigos não lidos, conexões.

Retorna: { drafts, drafts_needing_rewrite, ideas_new, ideas_needed, unread_articles, connections, timezone, language }

GET /voice

Voice DNA compilado, sinais profundos e treinamento, em texto pronto para usar como instrução.

Retorna: { profile: string }

POST /voice

Grava o Voice DNA a partir dos posts reais do founder, analisados com a especificação que GET /voice devolve enquanto a voz não existe. Recusa sobrescrever um Voice DNA existente sem replace_existing: true, que exige o OK explícito do founder.

{ "analysis": { "personality_prompt": "…", "banned_words": [] }, "sample_posts": ["…", "…", "…"], "industry_sector": "fintech" }

Retorna: { voice_score, posts_analyzed, onboarding_step }

GET /training

Notas de treinamento do founder.

Retorna: { general, current_interests, content_modes, platforms: { linkedin, x, instagram } }

PATCH /training

Altera só as chaves enviadas; string vazia limpa; chave ausente fica como está. Cada mudança é registrada com o agente como autor.

{ "platforms": { "x": "Sem hashtag." } }

Retorna: { training, changed: string[] }

GET /ideas

Ideias abertas da caixa de entrada.

Query: status=new|used|dismissed|archived (repetível), origin=founder|agent|rss|llm|google_trends|x_trends, limit≤200

Retorna: Idea[]

POST /ideas

Propõe uma ideia na caixa de entrada do founder.

{ "title": "Preço por uso mata o self-serve?", "rationale": "Tema do RSS de ontem." }

Retorna: Idea

PATCH /ideas/:id

Muda o status de uma ideia.

{ "status": "archived" }

Retorna: Idea

GET /radar

Audience Radar: sinais datados dos últimos 14 dias (artigos dos feeds, Google/X Trends), sem duplicatas e com link.

Retorna: { lookback_days, signals, note }

POST /opportunities

Propõe uma oportunidade do Radar sustentada por sinais reais. Aparece em /ideias com a evidência; se o founder usar, vira ideia.

{ "title": "Fundadores travados no pricing", "summary": "…", "scores": { "relevance": 0.8, "timing": 0.7 }, "signal_ids": ["…"] }

Retorna: { id, signals }

GET /learnings

Aprendizados de voz propostos e decididos.

Query: status=review|rejected|implemented (repetível)

Retorna: Learning[]

POST /learnings

Propõe uma regra de voz. Fica esperando o founder aprovar; aprovada, é anexada ao treinamento do escopo.

{ "title": "Aberturas curtas", "body": "Abra com o número, sem frase de contexto.", "scope": "linkedin", "performance_item_ids": ["…"] }

Retorna: Learning

GET /performance

Posts publicados nos últimos 90 dias com maior e menor engajamento (métrica do X e manual), com texto e números. Precisa de 6 posts medidos; compare a forma e proponha regra em POST /learnings com performance_item_ids.

Retorna: { lookback_days, measured_posts, top, bottom, note }

GET /drafts/pending

Drafts esperando trabalho. Os com needs_rewrite=true trazem founder_direction e vêm primeiro.

Query: limit≤50

Retorna: PendingDraft[]

POST /drafts

Cria um draft ou um lote de até 6. Em lote, todo draft precisa de client_ref: um lote que falha no meio já gravou os anteriores, e o reenvio com as mesmas chaves não duplica. Sem horário e com a fila do founder ligada, sugere o próximo slot.

{ "drafts": [ { "platform": "linkedin", "text": "…", "rationale": "…", "client_ref": "run-42-li" } ] }

Retorna: { item_id, created, scheduled_for }[]

PATCH /drafts/:id

Reescreve um draft (ou um rejeitado, que volta para revisão). rationale é obrigatório. Draft de campanha só aceita nota.

{ "text": "…", "rationale": "Cortei a introdução, como pedido." }

Retorna: { item_id, status }

GET /drafts/:id/notes

Notas do draft, do founder e do agente, em ordem.

Retorna: Note[]

POST /drafts/:id/notes

Deixa uma nota no draft sem alterá-lo.

{ "body": "Mantive o número porque é a prova do argumento." }

Retorna: Note

Exemplo: o que trabalhar agora

curl -s https://www.foundergrowth.app/api/v1/drafts/pending \
  -H "Authorization: Bearer $FOUNDERGROWTH_TOKEN"