Desenvolvedores

API pública Beta

Crie integrações para o seu espaço de trabalho com chaves de API seguras e com escopo, e um contrato JSON estável e versionado.

Abrir a referência interativa da API

Início rápido

  1. 01

    Abra as chaves de API

    Abra Configurações, selecione Desenvolvedor, encontre Chaves de API e selecione Criar chave. Proprietários e administradores podem criar chaves.

  2. 02

    Crie a chave de API

    Informe um Nome, escolha Expira em (dias), defina Acesso aos canais como Todos os canais ou Canais selecionados e escolha em Escopos os escopos mínimos de que sua integração precisa. Uma requisição só é aceita quando a chave tem exatamente a ação sobre o recurso exigida pelo endpoint. Selecione Criar chave.

  3. 03

    Salve sua chave de API

    A chave completa é exibida uma única vez. Copie-a para o seu gerenciador de segredos e selecione Já salvei.

  4. 04

    Envie a chave

    Use um token Bearer ou envie o mesmo valor em x-api-key. Nunca coloque chaves em query strings nem em código do navegador.

cURL

curl https://www.usesonny.com/api/v1/contacts?limit=25 \
  --header "Authorization: Bearer sonny_your_key"

As chaves ficam protegidas

Segurança das chaves
As chaves usam o prefixo sonny_, 64 caracteres aleatórios, hash irreversível no armazenamento, expiração configurável e um limite de 600 requisições/minuto por chave. Cada chave pertence a um único espaço de trabalho.
Para revogar uma chave, selecione o botão de lixeira ao lado dela. Confirme Revogar chave de API? selecionando Excluir. A chave para de funcionar na hora.
Autorização em todas as chamadas
O Sonny verifica o hash e o escopo e, em seguida, confere de novo se quem criou a chave continua como membro ativo do espaço de trabalho, além da função e da situação do faturamento. Remover ou desativar esse usuário desativa as chaves dele imediatamente.
Os canais selecionados valem para todas as chamadas da API REST e do MCP. Os endpoints de contatos, propriedades, tags e gerenciamento de webhooks exigem acesso a todos os canais. A criação por formulário pode usar contacts:write com conversations:write em canais selecionados; os endpoints de contato independentes continuam valendo para todo o espaço de trabalho.

Escopos

  • contacts:read
  • contacts:write
  • tags:read
  • tags:write
  • conversations:read
  • conversations:write
  • messages:read
  • messages:write
  • messages:send
  • webhooks:read
  • webhooks:write
  • kb:read
  • kb:write
  • csat:read
  • attachments:write
  • members:read
  • contact-memory:read
  • contact-memory:write
  • reporting:read

Recursos

Contatos
Gerencie contatos, propriedades tipadas, filtros por valor exato e memórias de clientes. Arquive um contato ou apague-o de vez, junto com todas as conversas dele, para atender a pedidos de proteção de dados.
Origens
Descubra as origens configuradas e se cada uma aceita chat, e-mail ou ambos.
Conversas
Crie solicitações a partir de formulários, filtre o que precisa de atenção, atribua agentes ou equipes, adie, adicione tags e atualize em lote.
Sincronização
Reproduza as mudanças persistentes do espaço de trabalho e os registros de exclusão a partir de um cursor salvo.
Membros e equipes
Descubra os colegas que podem receber atribuições, a disponibilidade deles e o acesso efetivo aos canais.
Relatórios
Leia relatórios de suporte, equipe, IA, conhecimento, leads e disponibilidade.
Mensagens
Leia o histórico de mensagens e o conteúdo extraído dos anexos, envie arquivos privados, adicione notas internas e envie ou edite respostas aos clientes.
Webhooks
Gerencie endpoints, assinaturas, testes, entregas e novas tentativas.
Base de conhecimento
Crie, leia, atualize e exclua artigos e categorias da central de ajuda de cada origem.
Satisfação do cliente
Leia as notas de CSAT do espaço de trabalho, de cada canal e de cada conversa, e liste avaliações individuais filtradas por nota, comentário, responsável ou período.

Usando o Sonny a partir de uma ferramenta de IA

O Sonny MCP disponibiliza cada operação da API pública como uma ferramenta. Os clientes se conectam fazendo login com OAuth 2.1 — ou com uma chave de API com escopo — e cada chamada mantém os mesmos escopos, limites do espaço de trabalho e regras de negócio.

Leia o guia do Sonny MCP

Respostas e erros

As respostas de coleções usam data e incluem paginação quando aplicável. Toda resposta inclui x-request-id; você pode enviar um ID de requisição seguro e o Sonny o devolverá. Os erros retornam uma mensagem segura, sem expor detalhes sensíveis da implementação.

{
  "error": {
    "type": "validation_error",
    "message": "Invalid email address",
    "requestId": "req_01J..."
  }
}
400
Entrada, JSON, consulta ou cursor inválido.
401
Chave de API ausente, inválida, expirada ou sem o escopo necessário.
402
A situação do faturamento do espaço de trabalho bloqueia esta requisição.
403
A função de quem criou a chave no espaço de trabalho não tem permissão.
404
O recurso não existe no espaço de trabalho da chave.
409
A requisição entra em conflito com um recurso existente.
410
O cursor de sincronização expirou. Carregue o estado atual e reproduza a partir de um novo cursor.
413
O envio excede o tamanho permitido.
422
A origem não tem canal de e-mail ou um valor de campo enviado é inválido.
429
O limite de requisições por chave foi excedido.
500
Ocorreu um erro inesperado. Tente novamente com o ID da requisição.
503
A fila de entrega de webhooks está saturada. Tente novamente mais tarde.

Limites de requisições

Cada chave de API pode fazer até 600 requisições por minuto. Toda resposta informa a janela atual pelos cabeçalhos padrão RateLimit-Limit, RateLimit-Remaining e RateLimit-Reset, para que os clientes regulem o próprio ritmo em vez de adivinhar. Quando o limite é excedido, a API retorna 429 com um cabeçalho Retry-After — aguarde esse número de segundos antes de tentar de novo.

Versionamento e descontinuação

A API é versionada no caminho da URL (/api/v1). Dentro de uma versão, só fazemos mudanças aditivas — novos endpoints, novos campos opcionais, novos valores de enum. Mudanças incompatíveis saem em uma nova versão e, antes de desativar qualquer endpoint da v1, avisamos com pelo menos seis meses de antecedência: nesta página, por e-mail aos proprietários de espaços de trabalho com chaves de API ativas e pelos cabeçalhos Deprecation e Sunset nos endpoints afetados.

Editar uma resposta enviada

  1. Dê à sua chave de API ou conexão MCP os escopos messages:read e messages:send e acesso ao canal da resposta.
  2. Leia as mensagens da conversa e copie o ID de uma resposta humana que você enviou. Uma chave de API age como quem a criou; o OAuth age como o colega conectado.
  3. Envie o novo texto com a requisição abaixo ou chame edit_message no MCP com conversationId, messageId e body.
  4. Confira a mensagem retornada. O ID, os anexos, a confirmação de leitura e o horário original de envio continuam os mesmos.
curl --request PATCH \
  https://www.usesonny.com/api/v1/conversations/conversation_1/messages/message_1 \
  --header "Authorization: Bearer sonny_your_key" \
  --header "Content-Type: application/json" \
  --data '{"body":"The corrected reply"}'

A edição corrige o histórico da conversa e os clientes de chat conectados. Ela não envia outro e-mail nem notificação, e os e-mails já entregues não mudam. Só é possível editar as suas próprias respostas humanas aos clientes; mensagens recebidas, respostas de bot, notas internas e respostas de outros colegas não podem ser editadas. Espere a entrega pendente do e-mail terminar antes de editar. O novo texto precisa ter de 1 a 50.000 caracteres; o HTML anterior e as pré-visualizações de links são removidos. As integrações recebem um webhook message.updated e um evento de sincronização. Consultar apenas IDs de mensagens mais novas não encontra edições; use o feed de sincronização persistente.

Criar uma conversa a partir de um formulário

Envie as respostas de um formulário para POST /api/v1/conversations. O Sonny encontra ou cria o contato pelo e-mail, guarda as respostas e abre uma conversa recebida no canal de e-mail da origem escolhida. A equipe, as regras de atribuição e as notificações do canal são aplicadas. Os agentes respondem por e-mail.

  1. Crie uma chave com conversations:write e contacts:write. Você pode restringi-la aos canais selecionados do cliente. Encontre o ID da origem com GET /api/v1/sources, que também precisa de conversations:read.
  2. No n8n, adicione um nó HTTP Request: método POST, URL https://www.usesonny.com/api/v1/conversations. Guarde a chave em uma credencial Header Auth: Authorization com o valor Bearer sonny_your_key.
  3. Ative Send Body, escolha JSON e Using JSON, depois mude o campo JSON inteiro para Expression e cole este exemplo. Substitua o ID da origem e mapeie os campos de entrada para o seu formulário. Use o ID de envio estável e único do formulário para que uma nova tentativa use o mesmo valor.
{{ {
  sourceId: "YOUR_CLIENT_SOURCE_ID",
  contact: { email: $json.email, name: $json.name },
  subject: "Website enquiry",
  message: $json.message,
  fields: {
    Company: String($json.company ?? ""),
    Budget: String($json.budget ?? ""),
    Service: String($json.service ?? "")
  },
  externalId: "website-form-" + $json.submissionId
} }}

Para mais opções do nó, veja o guia do HTTP Request do n8n. A ferramenta MCP equivalente é create_conversation, com o mesmo payload e as mesmas permissões.

Nomes de campos novos viram propriedades de texto. Campos existentes de número, URL, data e seleção precisam receber valores de texto válidos; um valor inválido retorna 422 indicando o campo, e nada é salvo. Datas aceitam datas ISO ou timestamps; valores de seleção precisam corresponder a uma opção. São aceitos até 50 campos, com nomes de até 100 caracteres e valores de até 5.000. As propriedades aparecem no contato e na barra lateral da conversa. Os dois corpos da mensagem guardam uma cópia das respostas, inclusive quando você envia o htmlMessage opcional.

O campo opcional tags aceita até 20 IDs de tags existentes do espaço de trabalho. A resposta contém conversation, um resumo de contact, message e deduplicated. Envios novos retornam 201. Reutilizar o externalId na mesma origem retorna 200 com os IDs originais e deduplicated: true; conteúdo alterado é ignorado. Sem um ID externo, cada chamada cria uma nova conversa. Anexos na criação e respostas automáticas de IA não são suportados.

Fluxos de agentes

Faça a triagem, aja e fique sincronizado

REST e MCP compartilham as mesmas permissões e fluxos. As credenciais só podem restringir o seu acesso atual aos canais; remover um canal da sua associação também o remove das suas integrações.

Encontre conversas que precisam de atenção

Filtre por awaitingReply, unread, unassigned, assigneeId, agentGroupId, snoozed, priority ou tagIds. Aguardando resposta ignora notas internas; não lidas é específico do colega autenticado. Sem responsável significa nenhum responsável individual, mesmo que uma equipe esteja atribuída. As tags correspondem a qualquer ID informado.

GET /api/v1/conversations?status=open&awaitingReply=true&compact=true&sort=waitingSince&direction=asc

Ordene por waitingSince, lastMessageAt, createdAt ou prioridade de negócio, com direção asc ou desc. Os IDs desempatam. Filtros omitidos mantêm compact=false e snoozed=any. Na REST, tagIds aceita IDs separados por vírgula; o MCP também aceita uma lista. waitingSince começa na primeira mensagem recebida depois da última resposta; mensagens de acompanhamento e notas internas não o reiniciam. Rode essa varredura da fila de espera de forma agendada, mesmo quando nenhum webhook chegar, para que conversas antigas voltem a aparecer.

Fique em dia sem reler a caixa de entrada

Use GET /api/v1/sync com conversations:read. O feed persistente inclui mudanças em conversas, tags, mensagens, propriedades de contatos, memórias e registros de exclusão. Cada payload também exige o próprio escopo de leitura: corpos de mensagens precisam de messages:read e memórias precisam de contact-memory:read. Credenciais restritas recebem apenas os canais permitidos.

  1. Comece sem cursor, siga nextCursor até hasMore ser false e salve esse cursor.
  2. Leia as listas atuais de conversas e contatos e todo o histórico de que precisar para o seu estado inicial.
  3. Reproduza a partir do cursor salvo para capturar as mudanças ocorridas durante essa leitura. Processe cada página e depois salve nextCursor.

Elimine duplicatas pelo id do evento: a reprodução entrega pelo menos uma vez, então as ações seguintes precisam de proteção própria contra duplicatas. Uma requisição sem cursor cobre a última hora, não um retrato completo. Os eventos ficam guardados por 30 dias; HTTP 410 resync_required significa carregar o estado de novo. Carregue de novo também depois de ampliar escopos ou acesso a canais. Use limit até 100 e maxBodyChars até 10.000 (padrão 500). Defina compact=true para receber os campos textPreview/textTruncated das mensagens, limitados a 200 caracteres, em vez de body/bodyTruncated. Webhooks podem acordar um agente; o feed continua disponível sem assinaturas de webhook ou quando a entrega de webhooks está atrasada.

Registre verificações uma vez e compartilhe o resultado

Antes de repetir uma investigação, leia list_conversation_checks (GET /api/v1/conversations/{conversationId}/checks). Salve um resultado com record_conversation_check (PUT no mesmo caminho), informando key, result, checkedBy e uma reference opcional para o ID ou a URL do card. Por exemplo: key=product-version, result=Shopstar Go verified, checkedBy=Engineer, reference=card-X. O Sonny registra o actorId autenticado e o timestamp checkedAt. Reutilizar uma key substitui só aquela verificação; isto é o estado atual, não um histórico. Leituras precisam de conversations:read e gravações de conversations:write, ambos limitados ao canal da conversa. Essas chamadas não enviam resposta nem marcam o vendedor como respondido.

Atribua e atualize o trabalho em lotes

Descubra colegas e equipes ativos que podem receber atribuições com GET /api/v1/members and /teams (members:read). As respostas incluem disponibilidade e acesso efetivo aos canais, sem endereços de e-mail. Use conversations:write para alterar status, priority, assigneeId, agentGroupId, snoozedUntil, snoozedUntilReply, addTagIds ou removeTagIds.

POST /api/v1/conversations/batch
{
  "conversationIds": ["conversation_1", "conversation_2"],
  "updates": { "agentGroupId": "team_1", "assignment": "round_robin" }
}

O rodízio escolhe um membro disponível da equipe que tenha acesso ao canal da conversa. Sem nenhum membro elegível, uma atualização individual retorna 409 e um item do lote falha. Cada lote aceita até 100 IDs únicos e aplica uma alteração atômica por conversa. Confira cada resultado { id, ok, error? }; alguns itens podem falhar. Os lotes usam o limite atual por requisição, sem cobrança ponderada pela quantidade de itens.

Compartilhe o contexto do cliente com o Sonny AI

Liste, salve e remova memórias de contatos com contact-memory:read/write. Informe tanto contactId quanto um sourceId acessível; o contato precisa ter uma conversa nessa origem. Os fatos salvos usam a mesma validação, o mesmo tratamento de duplicatas e os mesmos limites do app e são registrados como memórias manuais.

Leia as definições de propriedades em /api/v1/properties e leia ou defina valores em /api/v1/contacts/{contactId}/properties. O MCP disponibiliza list_properties, get_contact_properties e set_contact_property. Eles exigem contacts:read/write e acesso a todos os canais. Defina exatamente um propertyId ou propertyName, com um valor de texto ou null para limpá-lo. Valores de texto, número, URL, data e seleção são validados de acordo com a definição do campo.

PUT /api/v1/contacts/contact_1/properties
{ "propertyName": "Plan", "value": "Pro" }

GET /api/v1/contacts?property[Plan]=Pro

Os filtros de propriedades correspondem a textos armazenados exatos; várias propriedades precisam corresponder todas. Valores enviados pela API são identificados como dados da API no Co-Pilot e na resposta automática. As regras existentes de cliente verificado e de origem continuam valendo. Valores comuns de campos internos preenchidos manualmente continuam fora desse contexto de IA.

Leia os mesmos relatórios que sua equipe

Com reporting:read, chame GET /api/v1/reporting/{kind}. Os tipos são overview, volume, response-times, agents, sources, tags, csat, ai, knowledge, leads e online-hours. Overview combina contagens, tempos de resposta e CSAT. Os filtros são period (1–365 dias, padrão 30), datas from/to em par (to é exclusivo), granularity (day/month), source, assigneeId e tagId. Source aceita all, all-chat, all-email, website:{id} ou email:{id}.

Os relatórios usam as consultas do painel e as verificações de acesso atuais. Knowledge usa as datas e os canais permitidos, independentemente da origem, do responsável ou da tag selecionados. Online-hours mede a presença dos colegas acessíveis no espaço de trabalho; as contagens de conversas continuam limitadas por canal. Os endpoints /csat existentes mantêm o próprio escopo csat:read e podem descrever um conjunto diferente.

Envie arquivos com respostas ou notas internas

Conceda attachments:write e envie um arquivo de até 25 MB para uma conversa. POST /api/v1/attachments recebe os campos multipart file e conversationId. A resposta contém um id e expiresAt. Passe até 10 attachmentIds para uma resposta ou nota em até uma hora. Cada envio fica vinculado ao seu usuário e à conversa e só pode ser usado uma vez. Envios não usados são limpos após expirarem.

POST /api/v1/conversations/conversation_1/reply
{ "attachmentIds": ["upload_1"] }

Respostas exigem messages:send; notas internas exigem messages:write e nunca chegam aos clientes. Mensagens só com anexos são suportadas. Respostas por e-mail incluem os arquivos dentro do limite de tamanho do e-mail e links de download para o restante; e-mails de chat offline incluem links dos arquivos. Os links enviados por e-mail continuam funcionando enquanto o anexo existir, para que os destinatários possam abri-los depois. Encaminhar o e-mail compartilha o acesso a esses arquivos. Confira emailDeliveryStatus para ver falhas de entrega.

Leituras de mensagens autorizadas incluem downloadUrl, downloadExpiresAt, aiStatus, aiDescription e aiExtractedText, além de videoTranscripts para vídeos com link (Loom, Vimeo e outros). Os links de download duram 15 minutos; leia a mensagem de novo para obter links novos. Novos envios pela API/MCP ficam em armazenamento privado. Anexos mais antigos continuam públicos e são marcados como access=legacy_public: a URL original deles não expira. Ler uma mensagem inicia a leitura das imagens dela quando o espaço de trabalho tem o Sonny AI. Leituras de imagens e transcrições de vídeos terminam pouco depois da chegada da mensagem: enquanto alguma ainda estiver em andamento, a resposta começa com readsInProgress, cujo nextStep indica a chamada exata a fazer. Passe waitSeconds (até 30) para esperar por elas em uma única requisição. Mensagens do widget e em tempo real exibidas aos clientes nunca incluem extrações nem transcrições.

Explore os contratos completos de requisição e resposta

Base de conhecimento

Sincronize a partir de uma fonte externa

Sincronize artigos e categorias usando IDs externos estáveis, importe Markdown ou HTML, envie imagens, defina a ordem e gerencie os públicos de leitores. Repetir um upsert atualiza o conteúdo existente.

  1. Escolha o sourceId do seu canal e conceda kb:read e kb:write. Mantenha a chave de API no seu servidor e limite o Acesso aos canais dela.
  2. Crie a categoria e depois sincronize um artigo como rascunho. Revise a formatação e o acesso antes de publicar.
  3. Configure o acesso à central de ajuda, publique e teste a visão do leitor. Use paginação e IDs externos estáveis nas próximas atualizações.
Siga o passo a passo completo de sincronização via REST

Gerencie públicos de clientes

Crie grupos a partir de características de clientes verificados e aplique-os a uma central de ajuda, categoria ou artigo. Todas as restrições herdadas precisam ser atendidas. Credenciais de API e MCP agem como equipe dentro dos seus escopos; visualize e teste uma sessão real de cliente para conferir o acesso de leitura.

Configure e teste públicos da central de ajuda

Documentos relacionados