API & MCP · v1

Documentação

Automatize a publicação nas redes sociais e conecte agentes de IA ao BSN Social. Use a API REST v1 ou o servidor MCP — a mesma fonte da verdade por trás dos dois.

Introdução

A API pública do BSN Social permite que sistemas externos e agentes de IA operem a sua conta programaticamente: listar suas marcas, ver as contas de rede social conectadas e criar/agendar publicações em uma ou várias redes de uma só vez (fan-out).

Todo acesso é feito com uma API key (prefixo bsn_), escopada à sua organização. A mesma lógica está exposta de duas formas:

  • REST v1 — endpoints HTTP JSON convencionais em /api/public/v1/*, ideais para integrar com back-ends, automações e ferramentas de no-code.
  • MCP (Model Context Protocol) — um endpoint JSON-RPC em /api/mcp que expõe as mesmas operações como tools para agentes de IA (Claude Desktop, Cursor e outros clientes MCP).

Quickstart

Do zero ao primeiro post agendado em três passos:

  1. Gere uma API key no painel, em Minha conta → API & MCP (endereço /api). Ela começa com bsn_ e aparece uma única vez. Só o dono ou um administrador da organização gera chaves.
  2. Descubra sua marca — chame GET /brands e anote o id (ex.: brd_123) da marca onde vai publicar.
  3. Agende um post — faça um POST /posts com o brandId, as networks e a caption.
curl
# 1) suas marcas → pegue o brandId
curl https://api-social.bsnsolution.com.br/api/public/v1/brands \
  -H "Authorization: Bearer bsn_sua_chave_aqui"

# 2) agende um post em duas redes de uma vez
curl -X POST https://api-social.bsnsolution.com.br/api/public/v1/posts \
  -H "Authorization: Bearer bsn_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -d '{
    "brandId": "brd_123",
    "caption": "Meu primeiro post via API 🚀",
    "mediaUrls": ["https://cdn.exemplo.com/arte.png"],
    "networks": ["INSTAGRAM", "FACEBOOK"],
    "scheduledAt": "2027-01-15T13:00:00Z"
  }'

Prefere um agente de IA em vez de HTTP? Pule para o MCP — as mesmas operações, expostas como tools para o Claude, o Cursor e afins.

Autenticação

Todas as requisições exigem o header Authorization com o token no esquema Bearer:

header
Authorization: Bearer bsn_sua_chave_aqui

Como gerar a chave

  1. No painel, abra Minha conta (menu do seu perfil) e clique em Abrir API & MCP (endereço /api).
  2. Dê um nome à chave e clique em Gerar chave (só dono ou administrador da organização).
  3. O token cru (bsn_<...>) é exibido uma única vez — copie e guarde num cofre. Depois disso o painel só mostra o prefixo (ex.: bsn_ab12cd3…), nunca o token completo.

Você pode revogar uma chave a qualquer momento pelo painel; requests com uma chave revogada passam a receber 401.

Escopo e plano ativo. Cada chave só enxerga os dados da organização dona dela. A API exige um plano ativo com a API incluída: sem chave você recebe 401; com a conta bloqueada, sem plano ou com um plano sem API, 402. Há ainda um limite de requisições por organização — ao excedê-lo a resposta é 429 com o header Retry-After. Como referência, trabalhe abaixo de ~120 requisições/min. Veja a tabela de erros.

Base URL

Todos os caminhos abaixo são relativos a esta base:

base url
https://api-social.bsnsolution.com.br

Ex.: a lista de marcas fica em https://api-social.bsnsolution.com.br/api/public/v1/brands.

Referência REST v1

Prefixo /api/public/v1. Respostas em application/json. Os exemplos curl abaixo já incluem o header de autenticação.

GET/api/public/v1/brands

Lista as marcas (brands) da organização da chave.

Resposta 200

json
{
  "brands": [
    {
      "id": "brd_123",
      "name": "Minha Marca",
      "handle": "minhamarca",
      "activeNetworks": ["INSTAGRAM", "FACEBOOK"]
    }
  ]
}

activeNetworks são as redes que a marca usa (escolhidas no painel, na marca). É uma preferência da marca, não garante conta conectada: para saber em quais redes dá para publicar agora, veja as contas com status: "active" em GET /integrations.

Exemplo

curl
curl https://api-social.bsnsolution.com.br/api/public/v1/brands \
  -H "Authorization: Bearer bsn_sua_chave_aqui"
GET/api/public/v1/integrations

Lista as contas de rede social conectadas (integrations) da organização. Nunca retorna tokens ou segredos.

Resposta 200

json
{
  "integrations": [
    {
      "id": "int_456",
      "brandId": "brd_123",
      "brandName": "Minha Marca",
      "network": "INSTAGRAM",
      "externalAccountId": "17841400000000000",
      "displayName": "@minhamarca",
      "status": "active"
    }
  ]
}

status vem em minúsculas: active (pronta para publicar), expired (o acesso venceu — reconecte a conta no painel) ou revoked (a permissão foi retirada na rede).

Exemplo

curl
curl https://api-social.bsnsolution.com.br/api/public/v1/integrations \
  -H "Authorization: Bearer bsn_sua_chave_aqui"
POST/api/public/v1/posts

Cria post(s) via fan-out: um mesmo conteúdo é distribuído para N redes. Todos os posts gerados compartilham o mesmo groupId. Se scheduledAt for informado, os posts entram como SCHEDULED. Sem ele, ficam PENDING_APPROVAL (aguardando aprovação no painel) e, ao serem aprovados, já saem agendados no melhor horário livre de cada rede — não é preciso agendar depois. Se faltar a imagem que a rede exige ou a conta conectada, a aprovação vale mas o post fica sem horário, com o motivo no painel.

Corpo (JSON)

CampoTipoObrigatórioDescrição
brandIdstringSimID da marca (deve pertencer à organização da chave).
networksstring[]Sim (≥ 1)Redes-alvo (repetidas contam uma vez). Disponíveis hoje: INSTAGRAM (Instagram), FACEBOOK (Facebook).
captionstringNãoTexto/legenda do post.
mediaUrlsstring[]NãoURLs (http/https) das mídias. Default: lista vazia.
scheduledAtstring (ISO-8601)NãoData/hora do agendamento, no futuro, com fuso: Z (UTC) ou deslocamento (ex.: 2027-01-15T10:00:00-03:00 para horário de Brasília). Sem ela, o post fica pendente de aprovação e é agendado no melhor horário quando for aprovado. Com ela, cada rede precisa ter a conta conectada na marca e, nas redes que só publicam com imagem ou vídeo (ex.: Instagram e TikTok), mediaUrls não pode ser vazio.

Repetir com segurança (Idempotency-Key)

Envie o header Idempotency-Key com um valor único por pedido (ex.: um UUID). Se a conexão cair e você repetir o mesmo pedido com a mesma chave em até 24 horas, a resposta é a mesma (201 com o header Idempotent-Replayed: true; no MCP, o resultado traz "replayed": true) e nenhum post é criado de novo nem descontado do plano. A mesma chave com outro conteúdo responde 422 (IDEMPOTENCY_KEY_REUSED).

Resposta 201

json
{
  "groupId": "a1b2c3d4-0000-0000-0000-000000000000",
  "posts": [
    { "id": "pst_1", "network": "INSTAGRAM", "state": "SCHEDULED" },
    { "id": "pst_2", "network": "FACEBOOK",  "state": "SCHEDULED" }
  ],
  "postsCharged": 1
}

posts traz um item por rede, mas o pedido conta 1 post do plano (postsCharged): 1 conteúdo é 1 post, mesmo publicado em várias redes da marca.

Exemplo

curl
curl -X POST https://api-social.bsnsolution.com.br/api/public/v1/posts \
  -H "Authorization: Bearer bsn_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ID-UNICO-DO-PEDIDO" \
  -d '{
    "brandId": "brd_123",
    "caption": "Lançamento de hoje 🚀",
    "mediaUrls": ["https://cdn.exemplo.com/arte.png"],
    "scheduledAt": "2027-01-15T13:00:00Z",
    "networks": ["INSTAGRAM", "FACEBOOK"]
  }'
GET/api/public/v1/posts

Lista os posts da organização (mais recentes primeiro).

Parâmetros de query

ParâmetroTipoDescrição
brandIdstringFiltra por marca (opcional; deve ser da organização).
limitnumberMáximo de posts (1–200, default 50).

Resposta 200

json
{
  "posts": [
    {
      "id": "pst_1",
      "brandId": "brd_123",
      "network": "INSTAGRAM",
      "state": "SCHEDULED",
      "caption": "Lançamento de hoje 🚀",
      "scheduledAt": "2027-01-15T13:00:00.000Z",
      "createdAt": "2026-07-14T18:20:00.000Z"
    }
  ]
}

Exemplo

curl
curl "https://api-social.bsnsolution.com.br/api/public/v1/posts?brandId=brd_123&limit=20" \
  -H "Authorization: Bearer bsn_sua_chave_aqui"

Formatos

A API não tem campo de formato: ele é decidido pelas mediaUrls que você envia.

Você enviaSai como
1 imagemPost de feed (imagem única).
2 ou mais mídiasNo Instagram, carrossel (imagens e vídeos); no Facebook, um post com várias fotos (só imagens). Cada rede tem o seu limite por post: Instagram e Facebook 10, Pinterest 5, X 4 e Google Meu Negócio 1. Acima do limite de qualquer rede escolhida, o pedido é recusado (TOO_MANY_MEDIA) e nada é criado nem descontado do plano.
1 vídeo (.mp4 ou .mov)No Instagram vira Reel (o Instagram publica todo vídeo de feed como Reel). No Facebook, vídeo ainda não é publicado pela API: envie imagens.
Nenhuma mídiaSó texto onde a rede aceita (Facebook). No Instagram não sai sem imagem ou vídeo: agendado é recusado (NEEDS_MEDIA); sem horário, o post fica em aprovação marcado como “precisa de imagem”.

Story e Reel explícitos (escolher “Story” ou forçar um Reel) ainda não estão disponíveis pela API nem pelo MCP — use o painel para isso.

Erros

Erros retornam um JSON com o campo error (e, quando aplicável, issues com o detalhe da validação). Códigos:

StatusQuandoCorpo
400Corpo/parâmetros inválidos.{ "error": "Corpo inválido", "issues": [...] }
400Rede indisponível (NETWORK_UNAVAILABLE), horário no passado (PAST_SCHEDULE) ou Idempotency-Key inválida (INVALID_IDEMPOTENCY_KEY). Nada é criado.{ "error": "Esse horário já passou…", "code": "PAST_SCHEDULE" }
401Chave ausente, inválida ou revogada.{ "error": "API key inválida ou revogada" }
404Marca não encontrada nesta organização.{ "error": "Marca não encontrada nesta organização" }
422Mais mídias do que alguma das redes publica por post (TOO_MANY_MEDIA), ou post agendado que não sairia: falta imagem/vídeo na rede que exige (NEEDS_MEDIA), a marca não tem a conta da rede conectada (NO_ACCOUNT) ou a Idempotency-Key já foi usada com outro conteúdo (IDEMPOTENCY_KEY_REUSED). Nada é criado nem descontado do plano.{ "error": "…", "code": "NO_ACCOUNT" }
402A API não está no seu plano (FEATURE_DISABLED), a conta não tem plano ativo (NO_SUBSCRIPTION) ou está bloqueada, por exemplo por pagamento pendente (BLOCKED). Faça upgrade ou regularize o plano.{ "error": "…", "code": "FEATURE_DISABLED", "reason": "LIMIT" }
429Limite do plano no mês (LIMIT_REACHED): acabaram os posts do mês (1 post = 1 conteúdo, mesmo publicado em várias redes) ou outro limite do plano. Nada é criado. Volta no próximo mês ou com upgrade.{ "error": "Você chegou ao limite de 40 posts do mês…", "code": "LIMIT_REACHED", "reason": "LIMIT", "limit": 40, "used": 40 }
429Limite de requisições excedido (120 por minuto). Veja o header Retry-After.{ "error": "Limite de requisições excedido" }

No 429 com Retry-After (excesso de requisições), espere esses segundos antes de repetir. No 429 com code: "LIMIT_REACHED" não adianta repetir: o limite do plano só volta no próximo mês ou com upgrade.

MCP (Model Context Protocol)

O MCP é um protocolo aberto que permite a agentes de IA descobrir e chamar ferramentas externas. O BSN Social expõe um servidor MCP em /api/mcp (JSON-RPC 2.0 sobre HTTP), com as mesmas operações da API REST — assim um agente pode listar suas marcas e agendar posts conversando em linguagem natural.

Como conectar

Claude Code — um comando no terminal:

terminal
claude mcp add --transport http bsn-social https://api-social.bsnsolution.com.br/api/mcp \
  --header "Authorization: Bearer bsn_sua_chave_aqui"

Cursor (e outros clientes que aceitam servidor HTTP com headers) — no mcp.json:

json
{
  "mcpServers": {
    "bsn-social": {
      "url": "https://api-social.bsnsolution.com.br/api/mcp",
      "headers": {
        "Authorization": "Bearer bsn_sua_chave_aqui"
      }
    }
  }
}

Claude Desktop — use a ponte mcp-remote (precisa do Node.js instalado) no claude_desktop_config.json. O token vai numa variável de ambiente, sem espaços dentro dos args (no Windows o Claude Desktop quebra argumentos com espaço):

json
{
  "mcpServers": {
    "bsn-social": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api-social.bsnsolution.com.br/api/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer bsn_sua_chave_aqui"
      }
    }
  }
}

O servidor declara protocolVersion 2024-11-05 e capacidade de tools. É stateless (sem SSE/server-push e sem sessão persistida): cada chamada é resolvida no próprio POST, dentro do escopo da chave.

Tools disponíveis

ToolDescriçãoParâmetros
list_brandsLista as marcas da organização (id, nome, @handle, redes ativas).—
list_integrationsLista as contas conectadas (sem segredos/tokens).—
schedule_postCria/agenda um post em uma ou mais redes (fan-out).brandId*, networks*, caption, mediaUrls, scheduledAt, idempotencyKey
list_postsLista os posts da organização (mais recentes primeiro).brandId, limit (1–200, default 50)

* obrigatório.

Exemplo: chamar schedule_post

Requisição JSON-RPC (tools/call) para o endpoint MCP:

curl
curl -X POST https://api-social.bsnsolution.com.br/api/mcp \
  -H "Authorization: Bearer bsn_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "schedule_post",
      "arguments": {
        "brandId": "brd_123",
        "caption": "Publicado por um agente de IA 🤖",
        "mediaUrls": ["https://cdn.exemplo.com/arte.png"],
        "networks": ["INSTAGRAM", "FACEBOOK"],
        "scheduledAt": "2027-01-15T13:00:00Z",
        "idempotencyKey": "ID-UNICO-DO-PEDIDO"
      }
    }
  }'

Resposta

O resultado vem no formato MCP (content[] com um bloco text contendo o JSON serializado) — o mesmo corpo da REST, com postsCharged (posts do plano consumidos: 1 por conteúdo) e, quando o pedido repetiu uma idempotencyKey já usada, "replayed": true (nada foi criado nem cobrado de novo):

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"groupId\": \"a1b2c3d4-...\",\n  \"posts\": [\n    { \"id\": \"pst_1\", \"network\": \"INSTAGRAM\", \"state\": \"SCHEDULED\" },\n    { \"id\": \"pst_2\", \"network\": \"FACEBOOK\", \"state\": \"SCHEDULED\" }\n  ],\n  \"postsCharged\": 1\n}"
      }
    ]
  }
}

Para o agente descobrir as tools, use o método tools/list; o handshake inicial é o método initialize.

Erros no MCP

  • Antes do JSON-RPC (status HTTP): chave ausente ou revogada → 401; plano sem API, sem plano ativo ou conta bloqueada → 402 com { error, code }; excesso de requisições (120/min por organização) → 429 com Retry-After. Nesses casos não há resposta JSON-RPC.
  • Recusa da tool (HTTP 200): quando o schedule_post recusa o pedido (mesmas regras da REST: horário no passado, rede indisponível, falta de mídia ou de conta, limite de posts do mês), o resultado vem com isError: true, a explicação em content e { error, code } em structuredContent. Nada é criado nem cobrado.
  • Erro JSON-RPC: método desconhecido (-32601), parâmetro faltando (-32602) ou falha interna (-32000).

Suporte

Gere e gerencie suas chaves no painel, em Minha conta → API & MCP. Se uma chamada falhar, confira o código e a mensagem de erro nas seções acima — elas explicam o motivo de cada resposta. Ainda com dúvida? Abra um chamado em Ajuda e suporte, no painel, ou escreva para contato@bsnsolution.com.br.

Documentação da API e MCP · BSN Social