Pular para o conteúdo

Começo rápido

Este guia vai de uma credencial nova até uma página de reuniões. São duas requisições.

Você precisa de um client ID e um client secret, emitidos pela Salesbud para a sua empresa. A credencial não é self-service: peça ao seu contato na Salesbud, que também confirma se a feature API_ACCESS está ligada.

O secret aparece uma única vez, na criação. Guarde num gerenciador de segredos — não dá para lê-lo depois, só rotacionar.

  1. Obtenha um token de acesso

    Os tokens são emitidos por OAuth 2.0 client credentials. Envie a credencial como campos form-encoded:

    Terminal window
    curl -X POST https://api.salesbud.com.br/oauth/token \
    -d 'grant_type=client_credentials' \
    -d "client_id=$SALESBUD_CLIENT_ID" \
    -d "client_secret=$SALESBUD_CLIENT_SECRET"

    O endpoint aceita apenas application/x-www-form-urlencoded. Mandar JSON devolve 415 UNSUPPORTED_MEDIA_TYPE.

    200 OK
    {
    "access_token": "eyJhbGciOiJSUzI1NiIs...",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "meetings.read calls.read"
    }
  2. Confirme o que o token pode fazer

    GET /v1/context informa a empresa, os escopos e o limite de requisições em vigor para aquele token. É o jeito mais rápido de separar problema de configuração de bug de integração.

    Terminal window
    curl https://api.salesbud.com.br/v1/context \
    -H "Authorization: Bearer $SALESBUD_ACCESS_TOKEN"
  3. Leia uma página de reuniões

    Terminal window
    curl "https://api.salesbud.com.br/v1/meetings?meeting_after=2026-01-01T00:00:00Z&limit=50" \
    -H "Authorization: Bearer $SALESBUD_ACCESS_TOKEN"

    Só voltam reuniões da sua empresa que terminaram o processamento. Veja Reuniões e ligações para entender o que é “terminou” e por que os registros de VoIP ficam em /v1/calls.

  4. Percorra o resto do histórico

    Devolva o next_cursor sem alterar, mantendo todos os filtros idênticos, e itere pelo has_more — nunca pelo tamanho de data.

    let cursor = null;
    do {
    const url = new URL("https://api.salesbud.com.br/v1/meetings");
    url.searchParams.set("meeting_after", "2026-01-01T00:00:00Z");
    url.searchParams.set("limit", "50");
    if (cursor) url.searchParams.set("cursor", cursor);
    const page = await fetch(url, {
    headers: { Authorization: `Bearer ${accessToken}` },
    }).then((r) => r.json());
    for (const meeting of page.data) await handle(meeting);
    cursor = page.pagination.next_cursor;
    } while (cursor);

    Uma página pode voltar curta — até vazia — com has_more em true. Isso é esperado: o serviço limita quanto varre por requisição. A Paginação explica as garantias.

Não existe refresh token. Client credentials é um fluxo máquina-a-máquina, sem usuário para reconsentir, então a RFC 6749 §4.4.3 diz para não emitir um. Quando o token expira, chame /oauth/token de novo com a mesma credencial.

Na prática: guarde o token por um pouco menos que o expires_in e reemita também em 401 INVALID_ACCESS_TOKEN, não só por relógio — uma credencial pode ser revogada antes de o prazo acabar.

Se o consumidor é um agente e não um serviço, dá para pular o cliente HTTP: o servidor MCP expõe estas mesmas operações como tools para Claude Desktop, Claude Code e Cursor, e cuida da renovação de token e dos retries. A credencial acima continua sendo necessária.

RespostaO que significa
415 UNSUPPORTED_MEDIA_TYPEO pedido de token foi enviado como JSON. Use form encoding.
401 INVALID_CLIENTClient ID ou secret errado, ou credencial revogada.
403 API_ACCESS_DISABLEDA empresa não tem a feature API_ACCESS. Repetir não resolve.
403 INSUFFICIENT_SCOPEFalta um escopo que a rota exige — calls.read para ligações, e transcriptions.read somado ao escopo da coleção para transcrição.
404 RESOURCE_NOT_FOUNDO id não existe, é de outra empresa, ou é da outra coleção.