Toda a documentação

API REST

Leia o histórico de mudanças item a item de qualquer página monitorada em JSON — valores antes/depois tipados, paginação por cursor, autenticação Bearer e spec OpenAPI 3.0 publicada.

A maioria dos monitores entrega um diff da página e deixa a interpretação com você. A BriefPanel resolve a página nos itens que se repetem nela — um anúncio, uma moeda, uma vaga, um plano — e registra cada mudança como uma atualização tipada: qual campo mudou, de quanto para quanto, e o quanto isso importa.

Esta API é o lado de leitura desse histórico: toda leitura é um GET, devolve JSON e pagina do mesmo jeito. Ela também tem uma escrita — retomar uma página pausada — para que um agente que pausou uma página consiga ligá-la de novo sem abrir o navegador.

URL base

https://actions.briefpanel.com/v1

Autenticação

Envie uma chave pessoal de API como token Bearer:

Authorization: Bearer YOUR_BRIEFPANEL_API_KEY

Crie uma chave em Configurações → API e integrações no app (https://app.briefpanel.com/integrations). As chaves começam com bp_mcp_ e a mesma chave vale para o servidor MCP — uma credencial para as duas superfícies.

As chaves carregam escopos: todo GET exige read e o endpoint de escrita exige write. Uma chave somente de leitura recebe 403 numa escrita.

Tokens de acesso OAuth (bp_oat_) não são aceitos aqui. Eles são vinculados ao público (audience) do recurso MCP, então autenticam apenas chamadas MCP.

Uma chave ausente ou inválida devolve 401 com o cabeçalho WWW-Authenticate. Um token OAuth de MCP válido também devolve 401, mas com uma mensagem própria: a credencial funciona no servidor MCP e esta API precisa de uma chave de API pessoal. Não há nada de errado com o token.

Início rápido

Liste o que você monitora. Se vierem linhas, sua chave está funcionando:

curl https://actions.briefpanel.com/v1/sources \
  -H "Authorization: Bearer YOUR_BRIEFPANEL_API_KEY"

Depois leia o que mudou. É este o endpoint que a maioria das integrações consulta:

curl "https://actions.briefpanel.com/v1/updates?importance=material&limit=50" \
  -H "Authorization: Bearer YOUR_BRIEFPANEL_API_KEY"

Uma resposta reduzida — o formato completo está no documento OpenAPI:

{
  "data": [
    {
      "id": "j57e...",
      "at": 1750000000000,
      "updateType": "modified",
      "importance": "material",
      "field": "price",
      "valueChange": {
        "type": "number",
        "previous": 149.9,
        "current": 129.9,
        "unit": "BRL"
      },
      "entry": { "id": "k17c...", "title": "Plano Pro", "kind": "pricing plan" },
      "source": { "id": "m92a...", "url": "https://example.com/pricing" }
    }
  ],
  "pagination": { "nextCursor": "eyJ...", "hasMore": true }
}

Endpoints

Endpoint Parâmetros de query Devolve
GET /v1/account — A conta por trás da sua chave, com o saldo de créditos que resta nela.
GET /v1/sources limit, cursor As páginas que você monitora, das mais recentes para as mais antigas, cada uma com seu status derivado e os tipos de item aprendidos para aquela página.
GET /v1/sources/{id}/entries limit, cursor Os itens atualmente resolvidos em uma página, ordenados pela atualização mais recente. Rascunhos de onboarding em andamento ficam de fora.
GET /v1/updates since, importance, limit, cursor Todas as mudanças item a item em todas as suas fontes, das mais recentes para as mais antigas. É o feed para consultar.
GET /v1/entries/{id}/updates field, importance, limit, cursor O fluxo completo de eventos de um item. Filtre por field para o histórico de um único campo — a leitura por trás de um gráfico de preço.
GET /v1/entries/{id}/changes limit, cursor Um cartão por coleta que mudou este item: contagens de diff, a variação de preço derivada e ponteiros para a evidência capturada.
GET /v1/changes/{id}/snapshot state, format O estado capturado da página por trás de uma mudança. Devolve bytes, não o envelope JSON.
POST /v1/sources/{id}/resume — Volta a monitorar uma página pausada. Exige o escopo write.

Um id que pertence a outra conta devolve 404, não 403 — a API não confirma a existência de um id que ela não vai servir.

Duas leituras existem só no servidor MCP por ora: as configurações graváveis de uma fonte (userPrompt, notificationsEnabled, updateSensitivity) e restringir o feed de atualizações a uma fonte. O GET /v1/sources traz saúde e cadência, e o GET /v1/updates é da conta inteira.

Retomar uma página pausada

POST /v1/sources/{id}/resume não recebe corpo e responde com o estado de monitoramento da página:

{
  "data": {
    "id": "m92a...",
    "status": "active",
    "alreadyActive": false,
    "nextFetchTime": 1789648163769
  }
}

As verificações voltam na monitoringFrequency da própria página e passam a gastar créditos de novo, um por página lida. Uma página pausada por mais tempo que a sua frequência já está vencida, então o nextFetchTime pode estar no passado.

Retomar uma página que já está sendo verificada é sucesso, não conflito: alreadyActive vem true, nada muda e nenhuma verificação extra é agendada — então repetir a chamada é seguro.

O status é o estado guardado da página, não uma previsão — o mesmo valor que o GET /v1/sources devolve. Ele só vem creditPaused para uma página que já estava pausada por falta de créditos. Retomar uma página pausada numa conta sem créditos devolve active, e o agendador a estaciona de novo como creditPaused na próxima verificação em que ela vencer. Para saber se as verificações vão mesmo acontecer, olhe o saldo de créditos, não este campo.

Retomar não redefine a base de comparação. A página continua sendo comparada com o estado em que estava quando foi pausada, então a primeira verificação depois de uma pausa longa pode relatar tudo o que mudou no intervalo. Isso é proposital: a alternativa adotaria essas mudanças em silêncio como o novo normal, e você nunca as veria. Os itens coletados antes da pausa ficam intactos e não são notificados de novo.

Paginação

Toda coleção aceita limit e cursor e responde com um objeto pagination:

{ "pagination": { "nextCursor": "eyJ...", "hasMore": true } }

Passe nextCursor de volta como cursor para pegar a próxima página, e siga até hasMore ser false.

Um cursor pertence à requisição que o emitiu: o mesmo endpoint, a mesma conta e os mesmos filtros. Mantenha os filtros iguais de uma página para a outra; o limit é o único parâmetro que você pode mudar. Um cursor enviado com since, sourceId ou field diferentes, com importance diferente em GET /v1/updates (sem sourceId), ou de outra conta, responde 400 invalid_request. Repetir a mesma requisição nunca resolve. Remova o cursor para recomeçar da primeira página, por exemplo quando uma consulta avança o since.

Trate hasMore como o único sinal de fim da coleção. Uma página pode voltar vazia, ou menor que o seu limit, e ainda haver mais para ler — parar em uma página curta trunca sua sincronização em silêncio.

Consultando o feed

GET /v1/updates vem das mudanças mais recentes para as mais antigas. Leia o at do item mais novo e devolva esse valor como since na próxima consulta para receber só o que mudou desde então:

curl "https://actions.briefpanel.com/v1/updates?since=1750000000000" \
  -H "Authorization: Bearer YOUR_BRIEFPANEL_API_KEY"

since aceita milissegundos desde a época (o formato que at devolve) ou um instante ISO-8601. importance aceita critical, material ou minor.

Cada item carrega o entry e o source de origem embutidos, então uma atualização já é acionável sem uma segunda chamada.

Webhooks de saída

Se você não quiser consultar o feed, adicione um endereço HTTPS público controlado pelo seu sistema em Configurações → API e integrações → Webhooks de saída. Esse endereço não é uma rota da API BriefPanel: o BriefPanel envia um POST HTTP a ele sempre que registra um novo evento de item content.update.

O corpo reutiliza os campos canônicos de atualização de GET /v1/updates, incluindo updateType, importance, os contextos de fonte e item e o par field mais valueChange tipado. O envelope do webhook também carrega o id estável do evento e occurredAt.

Cada requisição inclui:

Cabeçalho Significado
BriefPanel-Event-Id Id estável de content_updates, igual em todas as tentativas. Use-o como chave de idempotência.
BriefPanel-Timestamp Horário da tentativa de entrega em segundos Unix. Use-o para rejeitar requisições assinadas antigas.
BriefPanel-Signature v1=<HMAC-SHA256 em hexadecimal> de <event-id>.<timestamp>.<corpo-bruto>, usando o segredo mostrado uma única vez ao criar o endpoint.

Uma resposta 2xx conclui a entrega. Timeouts, falhas de rede/DNS, 408, 425, 429 e respostas 5xx recebem no máximo cinco tentativas, com intervalos exponenciais de 1, 2, 4 e 8 minutos. Outras respostas, inclusive redirects, falham imediatamente. A entrega é pelo menos uma vez; por isso, o receptor deve deduplicar pelo id do evento. Uma falha no receptor nunca desfaz o ingest nem bloqueia outro endpoint. O app mostra o último status e a quantidade de tentativas; registros de entrega concluídos expiram após 30 dias.

Tipos de item

Cada item carrega um kind — pricing plan, job posting, cryptocurrency. Os nomes são aprendidos por fonte, então compare apenas dentro de uma mesma fonte; o vocabulário de cada página é publicado como entryKinds na fonte, junto com hasPrice para você saber quando a ausência de um preço é significativa.

entryKinds só aparece depois que a fonte foi analisada.

Saúde da fonte

GET /v1/sources devolve um status derivado:

status Significado
active Sendo verificada normalmente.
autoPaused Pausada após falhas seguidas de coleta.
creditPaused Pausada por falta de créditos.
disabled Desligada por você.

lastFetchOutcome, lastFetchErrorReason, consecutiveFetchFailures e nextCheckTime trazem o detalhe por trás disso.

O nextCheckTime é quando a próxima verificação é esperada e não vem quando não há horário a informar, em vez de um horário que ninguém vai cumprir. São dois casos, e o status separa os dois: uma página autoPaused ou disabled não tem verificação alguma a caminho, enquanto uma página active que nunca foi verificada só passa a ter horário depois da primeira. As verificações são disparadas por um agendador que roda em intervalo fixo, então a checagem acontece naquele horário ou depois dele, e uma página com cadência mais rápida que o intervalo do agendador continua sendo lida no intervalo dele: o effectiveMonitoringFrequency é essa cadência, ao lado do monitoringFrequency que você guardou.

Créditos

GET /v1/account devolve o que resta na conta:

curl https://actions.briefpanel.com/v1/account \
  -H "Authorization: Bearer YOUR_BRIEFPANEL_API_KEY"
{ "data": { "credits": 420 } }

Cada verificação gasta um crédito por página lida — a página que você monitora, mais cada página de item que ela segue. No zero, as verificações param e toda fonte passa a reportar creditPaused.

É esta a leitura que responde "minhas páginas vão mesmo ser verificadas?". O status de uma fonte diz o que está guardado agora, não o que a próxima verificação vai decidir: uma fonte pode continuar como active em uma conta zerada e ser pausada como creditPaused na próxima verificação devida. O saldo é o que separa os dois casos com antecedência.

É uma leitura de um instante, como todo saldo: diz se as verificações podem rodar agora, não o que a próxima vai decidir. O mesmo número está no servidor MCP como get_credit_balance.

Evidência

GET /v1/changes/{id}/snapshot serve o estado bruto da página de onde a mudança veio, para você mostrar a origem de um valor em vez de pedir que confiem nele.

Snapshots são deduplicados entre contas e não têm dono próprio, então são endereçados pela mudança a que pertencem, e não por um id próprio. Pegue o changeId de um cartão da linha do tempo e verifique hasCurrentSnapshot / hasPreviousSnapshot antes de pedir um estado.

  • state — current (padrão) ou previous. previous devolve 404 na primeira mudança, que não tem estado anterior.
  • format — markdown (padrão), html ou screenshot. screenshot responde com um 302 para uma URL de imagem assinada e de vida curta.

Erros

Falhas devolvem um objeto de erro:

{ "error": { "code": "not_found", "message": "No source with that id." } }

Trate pelo code em vez do status HTTP — o conjunto é fixo, cada código responde com exatamente um status, e nem o conjunto nem essa correspondência mudam sob você. A message é escrita para humanos e pode ser reescrita; não faça parsing dela.

code HTTP Quando
invalid_request 400 Parâmetro inválido ou fora do intervalo.
unauthorized 401 Chave ausente, malformada ou revogada — ou um token OAuth de MCP, que esta superfície não aceita.
forbidden 403 A chave não tem o escopo que o endpoint exige.
not_found 404 Id inexistente, incluindo um que pertence a outra conta.
method_not_allowed 405 Um método que este endpoint não serve.
rate_limited 429 Requisições demais para esta chave.
internal 500 Um erro do nosso lado.

GET, o preflight OPTIONS e o POST do endpoint de escrita acima são os métodos que esta API serve. PUT, PATCH e DELETE respondem 405 method_not_allowed, e um POST em um caminho que só lê também — o cabeçalho Allow diz o que aquele caminho serve, no mesmo envelope de erro.

Limites de uso

As leituras são limitadas por chave de API, em uma janela fixa de 300 requisições por minuto. As escritas têm orçamento próprio, de 60 por minuto, então um laço de escrita nunca gasta a cota de quem está consultando o feed, nem o contrário.

Toda resposta contada pelo limite carrega a cota atual, então dá para ritmar o cliente em vez de descobrir o teto batendo nele:

Cabeçalho Significado
X-RateLimit-Limit Requisições permitidas por janela, no balde em que esta requisição foi contada.
X-RateLimit-Remaining Requisições restantes nesta janela, já descontando a que você fez.
X-RateLimit-Reset Segundos até a janela reiniciar — um intervalo, não um timestamp Unix.

Esses cabeçalhos acompanham uma resposta contada, o que inclui os erros que a requisição só alcançou depois de chegar a um handler: um 400 ou 404 traz a cota igual a um 200. Uma requisição recusada por chave inválida (401/403) é barrada antes da contagem, então não traz nenhuma.

Trate a ausência deles como desconhecido, nunca como zero. Eles também são omitidos se o nosso limitador estiver momentaneamente indisponível — nesse caso a requisição é servida sem ser contada.

Acima do limite você recebe 429 com o cabeçalho Retry-After, em segundos e sempre no mínimo um — respeite-o em vez de tentar de novo imediatamente.

OpenAPI

A especificação completa é servida como documento OpenAPI 3.0 vivo:

https://actions.briefpanel.com/v1/openapi.json

Importe no Postman, aponte um gerador de SDK para ela ou entregue a URL para um agente. Ela descreve cada endpoint, o esquema de autenticação, o contrato de paginação e todos os formatos de resposta.

É servida sem autenticação de propósito — uma ferramenta precisa conseguir ler a descrição da API antes de ter uma chave.

Dois caminhos de entrada, uma única chave de API. Leia o histórico tipado de cada item em qualquer página monitorada, ou entregue a mesma credencial a um agente.

Obter sua chave de API