Sendly MCP

Envie e-mails transacionais, execute campanhas e gerencie contatos, listas e segmentos no Sendly. Servidor remoto com login via OAuth.

Servidor MCP hospedado

npx add-mcp 'https://app.sendly.now/api/mcp'

Instala no Claude Code, Codex, Cursor e outros

Documentação

Servidor MCP (/guides/mcp)

A Sendly executa um servidor remoto de Model Context Protocol. Aponte um cliente de IA compatível com MCP para ele, escolha o que ele pode fazer, e o agente pode trabalhar diretamente na sua conta Sendly — respondendo quais domínios estão verificados, organizando seus contatos, diagnosticando por que uma mensagem não chegou, criando e pausando suas automações, redigindo a próxima campanha e, se você autorizar, enviando-a.

Permissões que não podem ser desfeitas — enviar e-mails, revogar uma chave de API, remover um endereço da sua lista de supressão — **nunca são concedidas por padrão**. Elas aparecem desmarcadas na tela de consentimento, cada uma com uma frase simples indicando a consequência, e você mesmo as marca. Todo o resto é uma permissão que você pode revogar depois sem desconectar.

Endpoint [#endpoint]

https://app.sendly.now/api/mcp

O transporte é HTTP Streamable. A autorização é OAuth 2.1 com PKCE, ou uma chave secreta da Sendly.

A Sendly está listada no registro oficial de MCP como **now.sendly/sendly**. A listagem é apenas metadados — o endpoint acima, o transporte que ele usa e o cabeçalho opcional Authorization — porque a Sendly é um servidor remoto: não há nada para instalar e nenhum pacote para baixar. Um cliente que encontra a Sendly pelo registro conecta-se exatamente à URL que você colaria manualmente.

Conectar [#connect]

Claude Code [#claude-code]

A primeira chamada de ferramenta abre um navegador para a Sendly, onde você faz login e escolhe as permissões. Depois disso, a conexão persiste.

Configurando um agente diferente — Codex, Cursor, Windsurf, OpenCode ou VS Code/Copilot? Consulte Integre seu agente para o comando exato por cliente, ou cole o prompt de configuração do agente no próprio agente e deixe-o executar a configuração.

Claude (web e desktop) [#claude-web-and-desktop]

Adicione a Sendly como um conector personalizado nas configurações do seu Claude, usando a URL do endpoint acima. Conectores personalizados estão disponíveis nos planos pagos do Claude; a política do seu espaço de trabalho no Claude decide se os membros podem adicioná-los.

Qualquer outro cliente MCP [#any-other-mcp-client]

A Sendly funciona com qualquer cliente que fale HTTP Streamable e suporte o fluxo de código de autorização OAuth com PKCE. Dê ao cliente a URL do endpoint — não há aplicativo para pré-registrar. O cliente descobre tudo o que precisa e se registra automaticamente:

Documento de descobertaURL
Metadados de recurso protegido (RFC 9728)https://app.sendly.now/.well-known/oauth-protected-resource
Metadados do servidor de autorização (RFC 8414)https://app.sendly.now/.well-known/oauth-authorization-server

O emissor é https://app.sendly.now/api/auth. O registro dinâmico de clientes é aberto, então um cliente que nunca falou com a Sendly antes ainda pode se registrar e iniciar o fluxo sem supervisão. Aliases inseridos no caminho de ambos os documentos também são servidos, para que clientes que derivem a URL de metadados de qualquer forma a encontrem.

O endpoint MCP aceita um token de acesso OAuth **ou** uma chave secreta da Sendly (`sk_…`). OAuth é adequado para uma pessoa conectando um cliente desktop: você aprova permissões em uma tela de consentimento e gerencia a conexão em **Configurações → Aplicativos conectados**. Uma chave secreta é adequada para um agente headless ou de CI: as permissões da própria chave são o que o agente pode fazer, e você a gerencia em **Configurações → Chaves de API**. Chaves somente de envio (`pk_…`) e sessões de painel ainda são recusadas — uma chave `pk_` só pode enviar, e uma sessão é uma credencial de navegador que ninguém destinou a um agente.

Conectando com uma chave de API [#connecting-with-an-api-key]

Coloque a chave no cabeçalho Authorization e pule o fluxo OAuth completamente:

Uma conexão por chave difere de uma por OAuth em três aspectos que vale a pena conhecer:

  • Os escopos da própria chave são as permissões do agente. O que você marcou ao criar a chave é o que o agente recebe — não há segunda tela de consentimento. Com uma exceção documentada: algumas ferramentas precisam de uma pessoa conectada em vez de um projeto, porque as rotas por trás delas identificam um administrador do projeto a partir do usuário. Essas nunca são oferecidas a uma conexão por chave, independentemente do que você marcou — create_project, create_mailbox, delete_mailbox e todas as quatro ferramentas de chave de API. Use uma conexão OAuth para essas.
  • Está vinculada a um único projeto. O projeto da chave é o alvo de cada chamada, e um argumento projectId que discorda é recusado com PROJECT_FIXED em vez de ser ignorado silenciosamente. Para agir em outro projeto, use uma chave pertencente a ele.
  • É uma credencial de projeto, não pessoal. Ela não aparece em Configurações → Aplicativos conectados, porque não há uma linha de consentimento por trás dela. Você a revoga em Configurações → Chaves de API, e a revogação interrompe o agente na próxima chamada dele.
Uma chave criada antes de a Sendly ter permissões por capacidade carrega apenas a antiga configuração grosseira de `FULL` / somente envio. Seus escopos foram **inferidos** em vez de escolhidos, então neste endpoint essa chave não recebe nenhuma ferramenta por trás de uma das nove permissões que precisam de aprovação explícita — sem `send_email`, sem `send_campaign`, sem `update_workflow`, sem `remove_suppression` e assim por diante para o resto dessa lista. Isso não é um bug e não há caixa para remarcar: o reparo é **criar uma nova chave em Configurações → Chaves de API e marcar as permissões que você deseja**. Todo o resto que a chave sempre pôde fazer continua funcionando, aqui e na API REST, sem alterações.

Escolhendo o que um agente pode fazer [#choosing-what-an-agent-can-do]

Ambas as telas que pedem que você conceda capacidade — a tela de consentimento OAuth e o diálogo de chave de API — abrem em um preset nomeado e depois permitem que você marque caixas individuais. Um preset é apenas uma seleção inicial; nada é armazenado exceto a lista resultante de permissões.

PresetO que cobrePermissõesContém algo irreversível?
Somente leituraVer tudo neste projeto, não alterar nada.18Não
Acesso padrão* *(padrão)Gerenciar contatos, modelos, segmentos e rascunhos de campanha, e enviar e-mails de teste para você mesmo. Não pode enviar para mais ninguém.29Não
Envio e campanhasTudo no Acesso padrão, mais envio de e-mails e execução das suas automações.32Sim — 3
Acesso totalTudo, incluindo caixas de entrada, novos projetos e chaves de API.38Sim — todos os 9

O acesso padrão é o padrão, e é deliberadamente uma concessão capaz: um agente que gerencia seus contatos, segmentos, modelos e rascunhos de campanha, e que não pode colocar e-mails na caixa de entrada de ninguém. A maioria das pessoas quer isso e nada mais.

Uma concessão com nenhuma permissão marcada é válida. Isso significa que o cliente pode fazer você entrar e não aprender mais nada.

Conectando um agente somente leitura [#connecting-a-read-only-agent]

Somente leitura é o preset a usar quando um agente deve responder perguntas sobre um projeto e não alterar nada nele. Duas consequências valem a pena conhecer antes de escolhê-lo, e o servidor aplica ambas em vez de apenas documentá-las.

  • A lista de ferramentas é mais curta. As ferramentas são filtradas pelas permissões da conexão antes que o agente veja qualquer coisa, então uma conexão somente leitura nunca recebe send_campaign, create_contact ou edit_workflow. Ela não pode chamar o que não pode ver, e não gasta uma rodada descobrindo uma recusa.
  • diagnose_delivery é oferecida. A entregabilidade tem uma permissão de leitura própria, que é o que permite que a pergunta que as pessoas mais fazem a um agente — *por que este e-mail não chegou?* — seja respondida sem conceder uma única escrita.

Duas permissões estão deliberadamente fora dele. api-keys:read enumera suas credenciais, então não pertence a nenhum preset pré-marcado: um agente somente leitura pode ver seus contatos, mas não o que suas chaves podem fazer. E emails:test fica no Acesso padrão em vez disso, porque "somente leitura" é uma promessa sobre o mundo em vez de sobre nosso banco de dados — um preset que envia e-mails, mesmo para você, quebrou a promessa que seu nome faz.

Permissões que precisam de aprovação explícita [#permissions-that-need-explicit-approval]

Nove permissões podem produzir um efeito que nada no painel da Sendly desfaz. Elas aparecem desmarcadas, com o aviso abaixo mostrado ao lado da caixa:

PermissãoSobre o que você é avisado
emails:sendE-mails enviados desta forma chegam a caixas de entrada reais e não podem ser recuperados.
campaigns:sendIsso envia uma campanha para todo o seu público e não pode ser recuperado.
workflows:writeUm fluxo de trabalho ativado continua enviando sozinho, muito depois desta conversa.
suppression:writeRemover um endereço permite que a Sendly envie e-mails para alguém que pediu para você parar.
projects:writeNovos projetos contam para o seu plano e podem ser cobrados.
api-keys:readRevela quais chaves existem e o que cada uma pode fazer.
api-keys:writeUma chave criada aqui continua funcionando mesmo depois que você desconectar este aplicativo.
mailboxes:writeUma nova caixa de entrada começa a receber e-mails reais no seu domínio, e excluir uma apaga todas as mensagens que ela contém.
mailboxes:sendE-mails enviados desta forma chegam do seu próprio endereço de suporte e não podem ser recuperados.

Duas delas valem uma explicação, porque são as que as pessoas questionam. api-keys:read não muda nada — está na lista pelo que revela, já que um mapa de quais credenciais existem e o que cada uma pode fazer é um mapa da superfície de ataque da sua conta. E campaigns:write não está na lista: redigir uma campanha e enviá-la são permissões separadas agora, então um agente pode criar uma campanha para você sem poder enviá-la.

Modo de Código (padrão) [#code-mode-default]

Uma conexão vê exatamente duas ferramentas, não uma por operação: search_tools e execute_typescript. Toda capacidade na Superfície completa abaixo ainda existe por trás delas, acessível da mesma forma, sob as mesmas permissões — isso muda quantas ferramentas um cliente lista, não o que um agente pode fazer.

FerramentaO que faz
search_toolsEncontra as ferramentas que esta conexão pode alcançar e retorna cada uma como uma assinatura TypeScript declare function external_<name>(...), rotulada como [read-only] ou [write] com seu título e descrição. Um argumento opcional query restringe o resultado a uma correspondência de substring sem diferenciar maiúsculas de minúsculas contra o nome, título ou descrição de uma ferramenta — ele restringe o que a conexão já pode alcançar e nunca amplia. Omita-o para listar tudo o que é alcançável.
execute_typescriptExecuta um pequeno programa TypeScript, escrito pelo agente, em um sandbox isolado. O programa chama as funções external_* search_tools declaradas — elas já estão no escopo — e deve return seu resultado. await Promise.all([...]) executa chamadas independentes em uma única ida e volta em vez de várias.

Chamar external_<name>(...) de dentro do programa alcança o mesmo manipulador idêntico que uma chamada direta a essa ferramenta executaria: as mesmas verificações de autenticação, escopo, seleção de projeto, confirmação de envio em massa e auditoria, quer o agente a tenha chamado pelo nome ou por meio de execute_typescript. Orquestrar três chamadas em um programa custa uma ida e volta de MCP em vez de três; não faz nada que três chamadas de ferramenta separadas não poderiam fazer.

search_tools declara apenas as ferramentas que as permissões desta conexão alcançam. Qualquer outro nome de external_* simplesmente não está definido dentro do programa, então chamar um lança um ReferenceError em vez de uma recusa codificada.

Uma recusa dentro do programa — um projeto que ele não pode segmentar, uma conexão revogada, um envio em massa não confirmado, argumentos que não correspondem à declaração — aparece como um Error JavaScript lançado, não como uma forma de resultado separada: a mensagem lê <CODE>: <details>, por exemplo CONFIRMATION_REQUIRED: … ou INVALID_ARGUMENTS: …, usando os mesmos códigos de Solução de problemas abaixo. Quando a recusa carrega campos estruturados (requiredScope, upstreamCode, upstreamStatus), eles seguem os detalhes como JSON final, por exemplo TOOL_EXECUTION_FAILED: … {"upstreamCode":"CONFLICT","upstreamStatus":409}. O próprio try/catch do programa o vê como qualquer outra exceção, e a chamada de ferramenta externa não é marcada como erro — a chamada em si foi bem-sucedida; o código que o agente escreveu é o que falhou. Um programa que roda por aproximadamente 30 segundos, incluindo um loop infinito, é interrompido e a chamada ainda responde normalmente, relatando que não terminou em vez de travar.

Se um cliente não puder orquestrar um programa em sandbox, o Sendly pode servir a superfície de uma ferramenta por operação abaixo diretamente (MCP_TOOL_SURFACE=full) — uma alternância operacional, não algo que uma conexão solicita por si mesma.

Superfície completa [#full-surface]

A superfície de uma ferramenta por operação que execute_typescript orquestra acima, e que o Sendly também pode servir diretamente. Um agente só vê as ferramentas que sua concessão cobre aqui também: se você aprovar analytics:read e nada mais, view_analytics e list_projects são as únicas ferramentas abaixo que aparecem — as outras nunca são registradas, então o agente nem pode tentar usá-las.

Seus projetos [#your-projects]

FerramentaO que fazPermissão
list_projectsLista os projetos em que esta conexão pode atuar. Use-a para escolher o projectId para outras ferramentas.nenhuma
get_projectAs configurações do projeto ativo: nome, região de envio, modo de rastreamento de links, se está desativadoprojects:read
create_projectCria um novo projeto na sua conta. Somente conexões OAuth — uma chave de API não tem usuário para adicionar como membroprojects:write

Contatos e segmentos [#contacts-and-segments]

FerramentaO que fazPermissão
list_contactsLista contatos, opcionalmente filtrados por e-mail ou status de inscriçãocontacts:read
get_contactUm contato, com seus campos personalizadoscontacts:read
create_contactAdiciona um contatocontacts:write
update_contactEdita os campos ou o status de inscrição de um contatocontacts:write
delete_contactRemove um contatocontacts:write
list_segmentsLista segmentossegments:read
get_segmentUm segmento e sua condiçãosegments:read
list_segment_contactsQuem atualmente corresponde a um segmentosegments:read
create_segmentCria um segmentosegments:write
update_segmentEdita a condição de um segmentosegments:write
delete_segmentExclui um segmentosegments:write

Modelos e domínios de envio [#templates-and-sending-domains]

FerramentaO que fazPermissão
list_templatesLista modelos de e-mailtemplates:read
get_templateUm modelo, com seu corpotemplates:read
create_templateCria um modelotemplates:write
update_templateEdita um modelotemplates:write
check_domainStatus de verificação dos seus domínios de enviodomains:read
add_domainRegistra um domínio de envio e retorna os registros DNS a publicardomains:write
verify_domainVerifica novamente os registros DNS de um domínio e persiste o resultadodomains:write
start_domain_setupInicia a configuração guiada de DNS e retorna um link que você abre para publicar os registros no seu registradordomains:write

E-mail [#email]

FerramentaO que fazPermissão
list_emailsOs e-mails que você enviou, com status de entregaemails:read
get_emailUm e-mail e seus eventosemails:read
send_test_emailEnvia uma mensagem de teste do endereço de sandbox do projeto. Ela só pode alcançar o e-mail de conta verificado do próprio proprietário do projeto — qualquer outro destinatário é recusadoemails:test
send_emailEnvia um e-mail transacional. Alcança uma caixa de entrada real e não pode ser lembradoemails:send

send_test_email é como um agente prova que o envio funciona sem poder enviar e-mail para ninguém. Ele não aceita argumento from — o remetente é o endereço de sandbox do projeto, e a rota recusa um corpo que nomeie um — e há um limite diário para envios de sandbox. Ele é um membro do acesso Padrão, que é por isso que esse predefinido pode confirmar sua configuração de ponta a ponta enquanto ainda não consegue colocar e-mail na caixa de entrada de um estranho.

Campanhas [#campaigns]

FerramentaO que fazPermissão
list_campaignsLista campanhascampaigns:read
get_campaignUma campanhacampaigns:read
get_campaign_statsOs números de entrega e engajamento de uma campanhacampaigns:read
create_campaignCria um rascunho de campanhacampaigns:write
update_campaignEdita o conteúdo ou o público de um rascunho ou campanha agendadacampaigns:write
manage_campaignCancela, pausa ou retoma uma campanhacampaigns:write
delete_campaignExclui uma campanhacampaigns:write
send_campaignEnvia ou agenda uma campanha para todo o seu público. Não pode ser lembrada depois que o envio começacampaigns:send
Quando o projeto tem mais de **1.000 contatos**, a primeira chamada `send_campaign` é recusada com `CONFIRMATION_REQUIRED`, e a recusa diz ao agente para informar quantas pessoas a campanha alcança e o que ela diz, então chamar novamente com `confirm: true` somente se você concordar. Nada é enviado pela chamada recusada — a verificação é executada antes de o próprio API do Sendly ser tocado.

A proteção é no lado do servidor por um motivo. O Sendly pode pedir ao seu cliente para confirmar através do protocolo, mas este endpoint não mantém sessão, então essa solicitação não chega a ninguém; uma proteção cuja única aplicação vive no cliente não é uma proteção. Exigir uma segunda chamada carregando um argumento extra é algo que um servidor sem estado pode realmente aplicar. O limite é medido em relação aos contatos do projeto, e não ao público da campanha. A contagem de público é um número em cache que um job em segundo plano atualiza, então ela fica desatualizada exatamente quando importa — uma lista recém-construída ainda lendo zero. Todo público é um subconjunto dos contatos do projeto, então esse limite não pode estar errado na direção perigosa. Ele pede demais: um envio para um segmento de três pessoas dentro de um projeto grande ainda exige a confirmação, que é a forma certa de errar em uma pergunta cuja resposta não pode ser lembrada.

send_email não é coberto e não precisa ser. Ele aceita um destinatário, então enviar para mil pessoas através dele são mil chamadas visíveis, em vez da chamada única cujo raio de impacto o agente nunca precisou declarar.

Workflows [#workflows]

FerramentaO que fazPermissão
list_workflowsLista workflows de automaçãoworkflows:read
get_workflowUm workflow e seus passosworkflows:read
get_workflow_statusO estado atual de um workflow — habilitado ou não, o que o aciona, quantos passos tem — com como suas execuções foram: o total e a contagem agora em execução, aguardando, concluídas, com falha e canceladasworkflows:read
list_workflow_executionsAs execuções de um workflow, uma linha por contatoworkflows:read
create_workflowConstruir um workflow a partir de uma especificação: um gatilho, suas configurações e uma lista ordenada de passos. Ele começa desabilitado, a menos que você peça o contrário, para que possa revisá-lo antes de executarworkflows:write
edit_workflowAlterar o nome, a descrição, o estado habilitado ou o gatilho de um workflow e, opcionalmente, substituir toda a sequência de passos na mesma chamadaworkflows:write
clone_workflowCopiar um workflow, passos e tudo, como um novo rascunho. A cópia sempre começa desabilitada; o original não é modificadoworkflows:write
manage_workflowPausar ou retomar um workflow. Pausar interrompe novas execuções e cancela as que já estão em andamento, relatando quantas encerrouworkflows:write
update_workflowEditar apenas metadados: nome, descrição, evento de gatilho, estado habilitado, reentrada, limite por hora. Não pode criar ou substituir o grafo de passos — edit_workflow é a ferramenta que podeworkflows:write
delete_workflowExcluir um workflow e seu histórico de execuções. Recusado com 409 enquanto qualquer uma de suas execuções ainda estiver em andamentoworkflows:write

manage_workflow tem exatamente duas ações, pause e resume. Ler o estado de um workflow costumava ser uma terceira e agora é get_workflow_status, o que é um fato de permissões, e não uma organização: uma ferramenta declara uma permissão e deve conseguir alcançar tudo o que faz, pausar precisa de workflows:write, e ler as contagens de execução precisa apenas de workflows:read. Se fosse mantida como uma única ferramenta, a ação de leitura seria recusada exatamente para as conexões que receberam permissão de escrita sem leitura. Dividida, um agente que pode olhar, mas não tocar, ainda consegue responder "esta automação está em execução e quantos contatos estão dentro dela".

Definir `enabled` como false — por meio de `update_workflow` ou `edit_workflow` — impede que o workflow seja *acionado* novamente e deixa cada contato que já está no meio dele continuar percorrendo os passos. O próximo atraso ainda expira e o próximo e-mail ainda é enviado.

manage_workflow com pause faz ambos. Ele interrompe novas execuções e cancela as execuções já em andamento, e relata quantas cancelou, para que o agente possa distinguir "nada estava em execução" de "acabei de interromper quatrocentas jornadas". Cancelar é terminal: resume reabre o workflow para novas execuções, não coloca os contatos cancelados de volta onde estavam.

Esta é a borda prática do aviso em workflows:write: um workflow habilitado continua enviando por conta própria, muito depois da conversa que o habilitou.

Construindo os passos de um workflow [#building-a-workflows-steps]

create_workflow e edit_workflow aceitam uma lista linear de passos, que é o que quase toda automação é. O passo de gatilho é adicionado para você — não o inclua — e passar steps para edit_workflow substitui cada passo existente em vez de mesclar, por isso essa ferramenta é marcada como destrutiva.

Qualquer coisa com uma ramificação é um grafo, em vez de uma sequência, e grafos são lidos e escritos por inteiro em GET e PUT /api/v1/workflows/{id}/graph — workflows:read e workflows:write, respectivamente. Uma resposta de GET é aceita literalmente por PUT no mesmo caminho, então o ciclo é: leia o documento, altere um passo, envie tudo de volta.

{
  "workflow_id": "8f1c4d2e-5a7b-4a1e-9c3f-2b6d8e0a1f42",
  "version": 7,
  "steps": [
    {
      "id": "1b9f6a30-2c44-4f8e-9a01-77c2d1b5e903",
      "type": "TRIGGER",
      "name": "Signed up",
      "position": { "x": 0, "y": 0 },
      "config": { "eventName": "user.signup" },
      "template_id": null
    },
    {
      "id": "3d2e7c81-9b05-4a26-8f13-0c5a4e9d6712",
      "type": "DELAY",
      "name": "Wait a day",
      "position": { "x": 0, "y": 160 },
      "config": { "amount": 1, "unit": "days" },
      "template_id": null
    },
    {
      "id": "5a4b8e12-6d37-4c90-b2e5-1f8c3a70d954",
      "type": "SEND_EMAIL",
      "name": "Day 1: getting started",
      "position": { "x": 0, "y": 320 },
      "config": {},
      "template_id": "c7e1a904-3b62-4d58-8a17-9e05f2d6b481"
    }
  ],
  "transitions": [
    {
      "id": "9c0d5f73-1a86-42be-9d47-6b3e8a15c027",
      "from_step_id": "1b9f6a30-2c44-4f8e-9a01-77c2d1b5e903",
      "to_step_id": "3d2e7c81-9b05-4a26-8f13-0c5a4e9d6712",
      "condition": null,
      "priority": 0
    },
    {
      "id": "2e6a1b48-7f39-4c05-a8d2-53b90c7e6f18",
      "from_step_id": "3d2e7c81-9b05-4a26-8f13-0c5a4e9d6712",
      "to_step_id": "5a4b8e12-6d37-4c90-b2e5-1f8c3a70d954",
      "condition": null,
      "priority": 0
    }
  ]
}

Envie esse mesmo documento de volta para PUT para manter o workflow como está, ou altere-o primeiro. As regras que o documento segue:

  • Os ids dos passos são seus. Envie de volta um id que você leu para manter esse passo e seu histórico de execuções, um UUID novo para adicionar um passo e omita um passo inteiramente para excluí-lo junto com seu histórico.
  • Exatamente um passo é o TRIGGER — o único nó de entrada do grafo.
  • config é tipado por tipo de passo, entre os nove tipos TRIGGER, SEND_EMAIL, DELAY, WAIT_FOR_EVENT, CONDITION, EXIT, WEBHOOK, UPDATE_CONTACT e SEND_AT_OPTIMAL_TIME. Como o contrato discrimina em type, um SDK gerado restringe config a partir do tipo que você já conhece. Uma chave que o contrato não nomeia é repassada em vez de excluída; uma chave cujo valor está errado — unit: "fortnights", um alvo de webhook que não é uma URL — é rejeitada.
  • Cada aresta permanece dentro do documento. from_step_id e to_step_id devem nomear passos no mesmo payload, e um passo não pode apontar para si mesmo. priority ordena as arestas que saem de um passo, da menor para a maior. As arestas de um passo CONDITION carregam { "branch": "yes" } e { "branch": "no" }, ou o id da ramificação na forma de múltiplas ramificações.
  • No máximo 200 passos e 400 transições.
  • version avança em cada escrita estrutural, e cada escrita tira um instantâneo do grafo, então um número diferente entre duas leituras significa que alguém o editou no meio.
  • Uma escrita de grafo é recusada com 409 enquanto o workflow tiver execuções em andamento, porque esses contatos estão sobre os passos que estão sendo substituídos. POST /api/v1/workflows/{id}/pause os remove primeiro.

Para uma sequência linear, você não precisa desses endpoints: POST /api/v1/workflows e PATCH /api/v1/workflows/{id} ambos aceitam um sequence, que é exatamente o que create_workflow e edit_workflow enviam, então as duas credenciais constroem o mesmo grafo, em vez de grafos semelhantes.

POST /api/v1/workflows/{id}/clone — a rota por trás de clone_workflow — copia um workflow e todo o seu grafo no lado do servidor, a partir de uma leitura consistente. Isso não é o mesmo que ler um grafo e escrevê-lo em um novo workflow: uma cópia montada a partir de duas requisições pode capturar uma edição que ocorreu entre elas e materializar um workflow que nunca existiu.

Analytics e uso [#analytics-and-usage]

FerramentaO que fazPermissão
view_analyticsContagens de enviados, entregues, abertos e devolvidosanalytics:read
get_usageContagens de envios deste mês e de hoje contra seus limites aplicadosusage:read

Entregabilidade [#deliverability]

FerramentaO que fazPermissão
diagnose_deliveryPor que o e-mail de um dos seus domínios de envio não está chegando: o estado DKIM, SPF, DMARC e MX do domínio, os contadores recentes de devoluções e reclamações do projeto e — se você nomear um destinatário — se esse endereço está suprimidodeliverability:read

Cada sinal na resposta já era legível um endpoint por vez. O que nenhum endpoint fazia era dizer o que a combinação significa, que é a parte em que uma conversa de suporte realmente se apoia: "verificado, mas SPF falhando e 6% de devoluções" é um problema diferente de "não verificado", e distingui-los a partir de três payloads separados era um julgamento que o chamador tinha que fazer sem ajuda.

Então a resposta começa com findings — do pior para o melhor, cada um com um code estável, uma gravidade de blocking, degraded ou info, o que está errado e a correção. Um agente ramifica no código, nunca na redação. Os códigos são domain_not_registered, domain_not_verified, recipient_suppressed, spf_failing, dmarc_missing, custom_mail_from_failed, bounce_rate_critical, bounce_rate_elevated, complaint_rate_critical, complaint_rate_elevated, no_recent_sends, sample_too_small_for_rates e dns_never_checked.

Duas coisas para ler os sinais brutos. Os status de DNS são os resultados em cache do job de verificação do Sendly, em vez de uma consulta ao vivo, e identity.last_checked_at diz quando foram preenchidos. Os contadores de entrega são do projeto, em uma janela de 1 a 30 dias que tem como padrão 7, porque um registro de e-mail não armazena qual domínio o enviou.

Ele tem uma permissão própria, em vez de depender de domains:read, porque lê estado de DNS, contadores de entrega e supressão juntos, e uma chave concedida para "ver seus domínios de envio" não concordava com o último desses. Nada sob ele escreve qualquer coisa ou revela qualquer coisa que um membro do projeto já não possa ver no painel, então ele vem pré-marcado a partir de Somente leitura para cima.

Limpando uma lista [#cleaning-a-list]

FerramentaO que fazPermissão
validate_emailsVerifica até 50 endereços em uma única chamadavalidation:write
clean_listInicia uma execução em segundo plano sobre cada endereço de uma listavalidation:write
get_validation_runAté onde uma execução chegou e o que encontrouvalidation:read
list_validation_resultsUma página dos veredictos por endereço de uma execução, filtrável por veredictovalidation:read

Estas são cobradas por endereço verificado, por isso a permissão de escrita é uma caixa própria em vez de parte de contacts:write: um agente autorizado a gerenciar seus contatos não deve poder gastar seu dinheiro percorrendo sua lista. Ler uma execução concluída não custa nada e fica em Somente leitura.

Cada resposta traz um verdict, e é o campo para decidir. deliverable é seguro para enviar e-mail. undeliverable significa que o domínio não existe ou não publica registros MX. risky significa um provedor de caixa de e-mail descartável. unknown significa que o DNS não respondeu, então esse endereço não foi verificado — é um valor separado de undeliverable de propósito, porque um agente que mesclasse os dois removeria contatos ativos por causa de uma falha de rede.

Os outros campos descrevem o endereço em vez de julgá-lo. is_personal (um provedor gratuito para consumidores) e is_role_address (support@, info@) são informações de qualidade da lista, não problemas: clientes reais usam Gmail e empresas reais respondem em seu endereço de suporte. is_disposable é o único sinalizador que reduz um veredicto.

clean_list não limpa nada por si só. Ele valida e para — nenhuma assinatura é cancelada e nenhum contato é excluído. Agir sobre um resultado é uma chamada separada sob uma permissão diferente, o que impede que uma consulta de DNS que pode responder unknown de reduzir silenciosamente um público.

Listas de assinantes [#subscriber-lists]

FerramentaO que fazPermissão
list_listsAs listas de assinantes que este projeto mantém, com seus tamanhoslists:read
get_listUma lista, com seu tamanho e sua configuração de opt-in duplolists:read
create_listCriar uma lista vazialists:write
update_listRenomear uma lista ou alterar suas configuraçõeslists:write
delete_listExcluir uma lista e todos os membros nelalists:write

Uma lista é uma associação estática: pessoas que foram colocadas nela e permanecem até sair. Isso é o que a separa de um segmento, que é uma condição dinâmica sobre campos de contato, e de um tópico, que é uma decisão permanente sobre um assunto. member_count conta associações em todos os status — um convite pendente e um opt-out cancelado são ambos associações — então é o tamanho da tabela de associações, não o número de pessoas que um envio alcançaria.

Adicionar pessoas a uma lista não está nesta superfície. Assinar é onde o opt-in duplo começa: cria a associação como pendente e gera um token de confirmação cuja entrega é sua responsabilidade. Um agente colocando alguém em uma lista estaria afirmando um consentimento do qual não tem evidência, então as ferramentas param na própria lista.

delete_list exclui o registro de consentimento. As associações vão junto com a lista, e uma associação cancelada é a evidência de que alguém optou por sair — recriar a lista e reimportar os mesmos endereços não encontrará os opt-outs esperando. O e-mail já enviado não é afetado.

Tópicos e consentimento [#topics-and-consent]

FerramentaO que fazPermissão
list_topicsOs assuntos sobre os quais este projeto envia e-mail, e quantas pessoas responderam a cada umtopics:read
get_contact_topic_preferencesTudo o que um contato disse que quertopics:read
create_topicAdicionar um assunto ao qual as pessoas podem se inscrevertopics:write
update_topicRenomear, re-descrever, alterar o padrão ou aposentar um tópicotopics:write
set_topic_subscriptionRegistrar o que um contato quer sobre um tópicotopics:write

Um tópico é um assunto sobre o qual você envia e-mail — um resumo semanal, um changelog, um aviso de cobrança — e a resposta de um contato a ele é uma decisão permanente em vez de um filtro de público. Ele se aplica a qualquer público que uma campanha selecionar, então escolher um público diferente não é uma forma de contorná-lo. Essa é a diferença entre um centro de preferências e uma caixa de seleção que ninguém respeita.

set_topic_subscription não pode inscrever ninguém. Pedir para inscrever coloca o contato em pending e devolve um link de confirmação; nada é enviado sobre esse tópico até que uma pessoa o abra, e não há parâmetro para pular a etapa. Um agente afirmando que alguém quer receber e-mail não é evidência de que quer, e a reputação que o erro custa é sua. O Sendly não envia esse e-mail de confirmação — você envia, do seu próprio domínio verificado. Cancelar a inscrição é o contrário e tem efeito imediato: retirar o consentimento nunca deve ser mais difícil do que concedê-lo.

default_opt_in decide o que o SILÊNCIO significa. Mantido como verdadeiro, um contato que nunca respondeu conta como inscrito — o que é a leitura honesta para um tópico introduzido sobre uma lista que você já tem, já que essas pessoas consentiram em ouvir de você. Definido como falso, ausência significa "não perguntado" e apenas um sim explícito conta. subscribed_count relata apenas respostas explícitas, então ele lê baixo em um tópico default_opt_in; isso é quantas pessoas responderam, não quantas receberiam o e-mail.

Não há exclusão. archived: true aposenta um tópico — ele sai do centro de preferências e deixa de ser enviável — e cada opt-out registrado contra ele sobrevive, porque excluir o tópico excluiria as escolhas que as pessoas fizeram sobre ele.

Eventos e webhooks [#events-and-webhooks]

FerramentaO que fazPermissão
list_eventsOs eventos personalizados que sua aplicação registrouevents:read
record_eventRegistrar um evento personalizado contra um contato existenteevents:write
list_webhooksListar endpoints de webhookwebhooks:read
create_webhookAdicionar um endpoint de webhookwebhooks:write
update_webhookEditar um endpoint de webhookwebhooks:write
delete_webhookExcluir um endpoint de webhookwebhooks:write

Lista de supressão [#suppression-list]

FerramentaO que fazPermissão
list_suppressionsOs endereços que o Sendly se recusa a enviarsuppression:read
add_suppressionBloquear um endereçosuppression:write
remove_suppressionDesbloquear um endereço, reabilitando o envio para elesuppression:write

Caixas de e-mail [#mailboxes]

Caixas de e-mail são o lado conversacional: uma caixa de entrada real por trás de um endereço como support@yourdomain.com, então o e-mail enviado para lá chega no Sendly — e, com sua própria permissão, um agente pode escrever e enviar uma nova mensagem desse endereço.

FerramentaO que fazPermissão
list_mailboxesAs caixas de e-mail nos domínios deste projeto, com o status e o domínio de cada umamailboxes:read
get_mailboxUma caixa de e-mail, além do host e porta IMAP e SMTP, e o nome de usuário para conectar um cliente de e-mail. A senha não está incluída e não pode ser lida de voltamailboxes:read
create_mailboxCriar uma caixa de e-mail em um domínio verificadomailboxes:write
delete_mailboxExcluir permanentemente uma caixa de e-mail e todas as mensagens que ela contémmailboxes:write
compose_mailbox_emailEscrever um e-mail para uma caixa de e-mail: rascunhar um a partir de uma breve instrução, reescrever um rascunho que você já tem, ou sugerir linhas de assunto. Retorna texto e não envia nada — o resultado sempre diz sent: falsemailboxes:read
send_mailbox_emailEnviar um e-mail novo em texto simples do próprio endereço da caixa de e-mail, para até vinte destinatários. O destinatário pode responder, isso entra nas conversas dessa caixa de e-mail, e não pode ser recolhido. Destinatários suprimidos e e-mails que o verificador de conteúdo rejeita são recusados; uma caixa de e-mail pode enviar 60 mensagens por hora dessa formamailboxes:send

Cinco fatos sobre estes que são mais fáceis de saber agora do que descobrir depois:

  • Nenhuma ferramenta de agente lê as mensagens de uma caixa de correio. O e-mail que uma caixa de correio recebe é correspondência de terceiros, e nenhuma permissão no vocabulário cobre a leitura dela. get_mailbox retorna as configurações de conexão, nunca o conteúdo.
  • Uma caixa de correio não pode ser alterada após ser criada. Não há rota de atualização e nenhuma ferramenta de atualização — deliberadamente. Para alterar um endereço, exclua a caixa de correio e crie a que você deseja.
  • Cotas não são suportadas. Caixas de correio são criadas sem limite de armazenamento e não há como adicionar uma depois. A ferramenta não oferece o argumento, e a rota o recusa em vez de aceitar um valor que nunca aplicaria.
  • O domínio deve ser verificado primeiro, e um projeto pode ter no máximo dez caixas de correio. Ambos são recusados com um 409, não contornados silenciosamente.
  • Rascunhar e enviar são permissões diferentes. compose_mailbox_email apenas precisa de mailboxes:read porque não muda nada: ela entrega ao agente um texto para mostrar a você. Colocar esse texto na caixa de entrada de alguém como seu endereço de suporte é send_mailbox_email sob mailboxes:send, que é separado de emails:send de propósito — um agente autorizado a enviar um recibo do seu domínio verificado não foi por isso autorizado a abrir uma conversa como sua central de suporte. Ele chega sem verificação, e um agente bem-comportado mostra a você o rascunho e confirma os destinatários antes de chamá-lo.
`create_mailbox` e `delete_mailbox` exigem uma conexão autenticada cujo usuário seja um **administrador** do projeto. Uma chave de API não carrega nenhum usuário, então essas duas ferramentas nunca são oferecidas a uma conexão por chave — elas estão ausentes da lista de ferramentas dela em vez de falharem quando ela tenta. `list_mailboxes` e `get_mailbox` funcionam normalmente com uma chave.

A exclusão é a ferramenta mais afiada nesta superfície: toda mensagem que a caixa de correio contém é apagada, a Sendly não mantém outra cópia, e nem o painel nem o suporte podem trazê-la de volta. E-mails enviados para o endereço depois são rejeitados. É por isso que mailboxes:write chega sem verificação.

Chaves de API [#api-keys]

FerramentaO que ela fazPermissão
list_api_keysQuais chaves existem, o que cada uma pode fazer, quando cada uma foi usada pela última vez. Nenhum segredo é retornado — apenas os últimos quatro caracteres ainda existem em qualquer lugarapi-keys:read
create_api_keyCriar uma nova chave. O segredo não é retornado ao agente — o resultado carrega um link de uso único que só você pode abrirapi-keys:write
rotate_api_keySubstituir o segredo de uma chave no lugar, mantendo seu nome e permissões. Mesmo link de uso único; o segredo antigo para de funcionar imediatamenteapi-keys:write
revoke_api_keyRevogar permanentemente uma chave. Qualquer coisa que ainda a use falha na próxima solicitação, e ela não pode ser restauradaapi-keys:write

Um agente pode criar e rotacionar chaves, e ainda assim nunca vê um segredo — veja Ferramentas que entregam um link a você abaixo para saber como isso funciona. Dois limites valem ser ditos claramente:

  • Uma nova chave não pode ser mais ampla do que a conexão que a criou. create_api_key exige uma lista explícita de permissões, e qualquer permissão que a conexão não possua é recusada com SCOPE_ESCALATION. A solicitação é rejeitada por completo, nunca silenciosamente ajustada para caber — então um agente não pode usar api-keys:write para fabricar uma capacidade que você nunca concedeu a ele. Apenas sua própria sessão no painel é isenta, porque um administrador de projeto já tem autoridade total sobre seu próprio projeto.

  • Toda ferramenta nesta seção precisa de uma conexão OAuth. Todas as quatro rotas de chave de API identificam um administrador de projeto a partir do usuário autenticado, e uma chave de API não carrega usuário, então uma conexão por chave nunca poderia chamar uma. Portanto, elas não são oferecidas a uma conexão por chave de forma alguma — ausentes da lista de ferramentas dela em vez de falharem quando ela tenta. Isso é uma propriedade projetada, não um modo de falha: uma ferramenta que um agente não pode usar não deveria estar em sua lista. Um agente conectado com uma chave não pode listar, criar, rotacionar ou revogar chaves.

    list_api_keys é a que parece fora do lugar, então vale explicar por que ela está aqui. Esta regra é sobre a forma da rota, não sobre perigo: api-keys:read não é uma das permissões que exigem aprovação explícita, e meramente ler não é irreversível, mas a rota ainda exige um usuário autenticado e, portanto, a ferramenta ainda não pode ser usada por uma chave. Toda outra ferramenta retida neste guia é retida por causa do que ela pode fazer; esta é retida por causa de quem ela precisa ser.

Esta é a única capacidade que escapa da própria revogação. Uma chave cunhada aqui é uma credencial separada: ela não consulta nenhuma linha de consentimento, continua funcionando depois que você desconecta o aplicativo que a solicitou, e você a revoga em **Configurações → Chaves de API** em vez de em **Configurações → Aplicativos conectados**. Essa é toda a razão pela qual `api-keys:write` está desmarcada por padrão e carrega um aviso.

Ferramentas que entregam um link a você [#tools-that-hand-you-a-link]

Três ferramentas não podem terminar dentro do agente, e respondem com status: "action_required" e uma URL para você abrir em vez de um resultado:

FerramentaO que o link fazQuanto tempo dura
create_api_keyMostra o segredo da nova chave, uma vez5 minutos
rotate_api_keyMostra o novo segredo da chave rotacionada, uma vez5 minutos
start_domain_setupConfiguração de DNS guiada no seu registrador, depois retorna você à SendlyCurta duração, definida pela sessão

Para as duas ferramentas de chave, a razão é que um segredo nunca deve entrar em um resultado de ferramenta. Qualquer coisa que um agente recebe é escrita no contexto do modelo, na transcrição do cliente, e em todo log pelo qual essa transcrição passa — uma credencial permanente em todos os três. Então o segredo não cruza a fronteira de forma alguma. Em vez disso, o link é um ticket de uso único, de cinco minutos, e abri-lo exige uma sessão autenticada da Sendly pertencente a um administrador do projeto — uma credencial que nenhum agente tem, e que um token OAuth ou uma chave de API não pode produzir. O agente que solicitou a chave não pode lê-la, incluindo aquele que acabou de quebrar sua implantação ao rotacioná-la. Segurar a URL não é suficiente por si só, e um link aberto pela pessoa errada é gasto em vez de honrado, então se isso acontecer, rotacione novamente.

start_domain_setup usa a mesma forma por uma razão diferente: publicar registros DKIM, SPF e MX acontece no seu registrador, onde a Sendly não tem credenciais e nunca terá.

Transmita-o a você e diga que ele abre uma vez. Um cliente bem-comportado também pode se oferecer para abrir a janela para você — isso é um extra opcional, não o mecanismo. **A ferramenta está completa de qualquer forma**, porque a URL está no resultado que o modelo pode ler. Se seu cliente nunca se oferecer para abrir nada, nada está quebrado e nada foi pulado.

Permissões e consentimento [#permissions-and-consent]

Durante o fluxo OAuth, a Sendly mostra a você uma tela de consentimento listando exatamente o que o cliente está solicitando, com uma caixa de seleção para cada item. Estas são as descrições que você lerá:

PermissãoTexto da tela de consentimentoRequer aprovação explícita
emails:sendEnviar e-mails dos seus domínios verificadosSim
emails:readVisualizar os e-mails que você enviou e o status de entrega delesNão
contacts:readVisualizar seus contatos e os campos personalizados delesNão
contacts:writeCriar, atualizar e excluir seus contatosNão
campaigns:readVisualizar suas campanhas e o desempenho delasNão
campaigns:writeCriar, editar e organizar suas campanhasNão
segments:readVisualizar seus segmentos e quem pertence a elesNão
segments:writeCriar, editar e excluir seus segmentosNão
workflows:readVisualizar seus fluxos de automação e as execuções delesNão
workflows:writeCriar, editar, ativar e excluir seus fluxos de automaçãoSim
templates:readVisualizar seus modelos de e-mailNão
templates:writeCriar, editar e excluir seus modelos de e-mailNão
domains:readVisualizar seus domínios de envio e o status de verificação delesNão
domains:writeAdicionar e remover domínios de envio, e acionar a verificaçãoNão
webhooks:readVisualizar seus endpoints de webhook e o histórico de entrega delesNão
webhooks:writeCriar, editar e excluir seus endpoints de webhookNão
suppression:readVisualizar os endereços na sua lista de supressãoNão
suppression:writeAdicionar e remover endereços na sua lista de supressãoSim
analytics:readVisualizar suas análises de envio e métricas de engajamentoNão
usage:readVisualizar seus totais de uso e limites de cobrançaNão
events:readVisualizar os eventos personalizados que seu aplicativo registrouNão
events:writeRegistrar eventos personalizados para seus contatosNão
projects:readVisualizar seus projetos e as configurações delesNão
projects:writeCriar novos projetos na sua contaSim
api-keys:readVer quais chaves de API existem, incluindo o que cada uma tem permissão de fazerSim
api-keys:writeCriar, rotacionar e revogar chaves de API — elas continuam funcionando mesmo depois que você desconectar este aplicativoSim
campaigns:sendEnviar ou agendar suas campanhas para o público delasSim
mailboxes:readVisualizar as caixas de entrada nos seus domínios e as configurações delasNão
mailboxes:writeCriar e excluir caixas de entrada nos seus domínios verificadosSim
emails:testEnviar e-mails de teste para seu próprio endereço a partir da sandbox do SendlyNão
deliverability:readVerificar por que o e-mail de um dos seus domínios não está chegandoNão
mailboxes:sendEscrever e enviar novos e-mails das suas caixas de entrada hospedadas, como esse endereçoSim
validation:readVisualizar suas execuções de validação de e-mail e os resultados delasNão
validation:writeVerificar se endereços de e-mail podem receber mensagens — isso é cobrado por endereçoNão
topics:readVisualizar os tópicos sobre os quais você envia e quem está inscrito em cada umNão
topics:writeCriar e editar tópicos, e alterar o que seus contatos estão inscritos — isso decide quem suas campanhas alcançamNão
lists:readVisualizar suas listas de assinantes e quem está nelasNão
lists:writeCriar, renomear e excluir suas listas de assinantesNão

Nada acontece na sua conta até você aprovar, e nenhuma ferramenta é executada sob uma permissão que você não concedeu.

Cada permissão nesta tabela tem pelo menos um endpoint por trás dela, então nada do que você concede aqui é inerte. Duas delas não têm FERRAMENTA DE AGENTE ainda: lists:read e lists:write regem os endpoints /api/v1/lists, que uma chave de API ou um token OAuth pode chamar diretamente, e a superfície MCP não oferece uma ferramenta de listagem. Concedê-las a uma conexão de agente hoje portanto amplia o que um token poderia fazer via HTTP e não muda nada que o próprio agente possa alcançar — o que vale a pena saber antes de marcá-las.

Escolhendo um projeto [#choosing-a-project]

Toda ferramenta, exceto list_projects, opera em um projeto.

  • Uma conexão OAuth cobre todos os projetos dos quais você participa, e cada ferramenta aceita um projectId opcional. Pertence a apenas um? Deixe-o de fora; o Sendly o infere. Pertence a vários? O agente deve passar um, ou a chamada é recusada com PROJECT_REQUIRED e instruída a chamar list_projects primeiro. Agentes bem-comportados fazem isso por conta própria. Um projectId que não seja um dos seus projetos recebe o mesmo PROJECT_REQUIRED antes de a ferramenta fazer qualquer coisa, com a mesma redação, quer esse projeto exista ou não.
  • Uma conexão por chave de API está vinculada ao projeto da própria chave. O argumento não é oferecido de forma alguma, e um cliente que o envie mesmo assim é recusado com PROJECT_FIXED.

O Sendly recusa em vez de adivinhar em ambos os casos de propósito: escolher silenciosamente "o primeiro" projeto, ou ignorar silenciosamente um projectId que o agente acreditava estar usando, significaria agir sobre os dados do locatário errado.

Mudando de ideia [#changing-your-mind]

Para retirar uma permissão, vá em Configurações → Aplicativos conectados e desmarque-a. A conexão permanece; o agente mantém todo o resto.

Para encerrar a conexão completamente, escolha Desconectar na mesma página. Para uma conexão por chave, revogue a chave em Configurações → Chaves de API em vez disso.

Cada chamada de ferramenta verifica novamente sua concessão ativa antes de ser executada, então uma permissão retirada começa a ser recusada **imediatamente** — mesmo que o token de acesso do agente não tenha expirado — e desconectar interrompe o agente completamente na próxima chamada dele.

A lista de ferramentas é atualizada logo em seguida. A listagem de um agente é construída a partir do token que ele está segurando, então uma ferramenta retirada ainda pode aparecer lá até que esse token seja substituído: cada chamada dela é recusada com SCOPE_MISSING nesse meio tempo, então nenhuma autoridade sobrevive à mudança. A leitura do token usa a mesma concessão ativa que o portão usa, o que significa que a ferramenta retirada desaparece da listagem assim que o agente atualiza — dentro de uma hora, já que os tokens de acesso duram esse tempo — e imediatamente se ele reconectar. Uma atualização apresentada após uma desconexão completa é recusada por completo em vez de ser honrada.

Solução de problemas [#troubleshooting]

As falhas voltam para o agente como resultados de ferramenta com um código, não como erros de transporte, então o agente pode explicá-las para você em vez de simplesmente derrubar a conexão.

O que você vêO que significaCorreção
401 do endpointNenhuma credencial válida foi apresentadaExecute o fluxo OAuth, ou coloque uma chave sk_… válida no cabeçalho Authorization. Uma chave pk_… ou uma sessão de navegador não serão aceitas
SCOPE_MISSINGEsta conexão nunca recebeu essa permissão, ou ela foi revogada — ou a chave é anterior às permissões por capacidade e a ferramenta é irreversívelReaprove-a em Configurações → Apps conectados, ou crie uma nova chave em Configurações → Chaves de API com as permissões marcadas
CONSENT_REVOKEDA conexão foi desconectada da sua conta SendlyReconecte o app em Configurações → Apps conectados
KEY_REVOKEDA chave de API que esta conexão usa foi revogada ou rotacionadaReconecte com uma chave atual de Configurações → Chaves de API
PROJECT_REQUIREDSua conta tem mais de um projeto (ou nenhum), então o destino é ambíguo — ou o projectId passado não é um dos seus projetosPeça ao agente para chamar list_projects e passar o id escolhido como projectId
PROJECT_FIXEDUma conexão por chave de API recebeu um projectId, mas uma chave está vinculada a um projetoRemova o argumento, ou use uma chave pertencente ao outro projeto
USER_DECLINEDSeu cliente pediu que você confirmasse uma ação irreversível e você recusou. Nada foi feito — a recusa acontece antes de o Sendly ser chamadoNada a corrigir. Diga ao agente o que você gostaria em vez disso
CONFIRMATION_REQUIREDsend_campaign foi chamado em um projeto com mais de 1.000 contatos sem confirm: true. Nada foi enviadoPeça ao agente para informar quem a campanha alcança e o que ela diz, depois chame novamente com confirm: true
INVALID_ARGUMENTSOs argumentos não podem produzir uma chamada — uma regra entre campos da própria ferramenta os recusou, por exemplo send_email dado um fromName sem from. Nada foi feitoA mensagem diz o que mudar. Não repita os mesmos argumentos: eles produzem a mesma recusa
SCOPE_ESCALATIONcreate_api_key pediu uma permissão que esta conexão não possuiPeça uma chave cujas permissões sejam um subconjunto do que você concedeu ao agente, ou crie a chave você mesmo em Configurações → Chaves de API
TOOL_EXECUTION_FAILEDA chamada chegou ao Sendly, mas não pôde ser concluídaTente novamente. Se persistir, entre em contato com support@sendly.now
O prompt de aprovação do próprio cliente MCP é o que pede sua confirmação antes de uma ferramenta irreversível ser executada, e ele pede por causa da própria política do cliente — a maioria dos clientes confirma toda chamada de ferramenta, ou toda chamada que você ainda não aprovou para a sessão. O Sendly não o aciona.

A anotação destructive que o Sendly publica marca uma coisa mais restrita, e vale a pena saber qual: uma ferramenta que apaga ou sobrescreve algo que já existia — delete_contact, edit_workflow (cujos steps substituem cada etapa existente), revoke_api_key (que invalida um segredo ativo), delete_list (que leva as associações junto). Um envio não é marcado como destrutivo, porque não destrói nada; ele é irreversível na outra direção, e nenhuma anotação captura isso. Não leia uma ferramenta não marcada como segura.

O Sendly também pode perguntar pelo protocolo, e USER_DECLINED é a resposta que uma recusa produz, mas apenas clientes em um transporte que carrega uma conversa com escopo de sessão a exibirão; no endpoint atual essa solicitação não pode ser entregue, então nenhum prompt do próprio Sendly aparece. Nada depende disso: a permissão que você marcou na tela de consentimento é a concessão, e toda ferramenta interativa é concluída ao retornar um link.

A única confirmação que o Sendly impõe por conta própria é a proteção de envio em massa: acima de 1.000 contatos, send_campaign exige uma segunda chamada com confirm: true. Essa funciona neste transporte justamente porque pede um argumento em vez de uma conversa.

Como isso se relaciona com o resto da plataforma [#how-it-relates-to-the-rest-of-the-platform]

O servidor MCP não é um backend separado. Toda chamada de ferramenta sai pela própria API REST pública do Sendly carregando a mesma credencial com a qual você se conectou, então as mesmas verificações de escopo, regras de associação e regras de projeto desabilitado se aplicam a um agente como a curl ou aos SDKs. Não há atalho privilegiado.

A [referência da API](/api-reference/overview) é gerada a partir do contrato OpenAPI do Sendly, então toda rota nomeada nesta página tem sua própria página lá, com os esquemas completos de requisição e resposta. Os SDKs `sendly-js` e `sendly-python` são gerados a partir desse mesmo contrato em seu próprio ritmo de lançamento, então uma rota adicionada desde o último lançamento chega a eles no próximo. Até lá, ela é acessível da mesma forma que tudo aqui: via HTTP com sua chave, ou pela ferramenta MCP que a encapsula. Comandos de configuração por cliente, e um prompt que um agente pode buscar e executar sozinho Credenciais servidor a servidor — para seu próprio código, e para conectar um agente headless A superfície REST pela qual toda chamada de ferramenta MCP passa