Tutorial Completo: Configuração de Apex Triggers (Salesforce -> Reev). Este tutorial foi feito para seguirem passo a passo. Ele cobre desde a criação dos artefatos Apex no Salesforce até a validação final no Reev.

Para que a Reev receba criações e alterações feitas no Salesforce, é necessário criar gatilhos no Salesforce que façam POST para o webhook da Reev.

Método de conexão via Apex

1) Objetivo da configuração

Quando houver criação ou atualização de Lead, Contact, Account ou Opportunity no Salesforce, enviar evento para o Reev processar automaticamente.

Endpoint Reev: https://api.reev.co/webhooks/salesforce/events

2) Pré-requisitos

  • Integração Salesforce já conectada no Reev.
  • Ter em mãos o user_id da Reev (número inteiro) da conta correta.
  • Perfil com permissão para criar Classes Apex e Triggers.
  • Acesso ao Setup do Salesforce (Lightning ou Classic).

3) Configurar Remote Site Settings

1. No Salesforce, abra Configuração.
2. Na caixa de Busca Rápida, pesquise por “Configurações do site remoto” e selecione esta opção.
3. Clique em Novo Site Remoto.
4. Nome do site remoto: ReevApi
5. URL do site remoto: https://api.reev.co
6. Marque Ativada e clique em Salvar.

0:00
/0:29

4) Como criar os artefatos Apex (Classe + Triggers)

1. Clique em Configuração (canto superior direito).
2. Na caixa de Busca Rápida, pesquise por “Classes do Apex” e selecione esta opção.
3. Clique em “Developer Console”.
4. Para classe: File -> New -> Apex Class, nome: ReevWebhookQueueable.
5. Cole o código da classe e salve (Ctrl+S).
6. Para trigger: File -> New -> Apex Trigger, selecione o objeto (Lead, Account, Contact, Opportunity), nomeie o trigger, cole o código e salve.

0:00
/0:19


5) Classe Apex Queueable (única)
Crie a classe abaixo com o nome ReevWebhookQueueable:

0:00
/0:21

public with sharing class ReevWebhookQueueable implements Queueable, Database.AllowsCallouts {
private String objectName;
private Set recordIds;

public ReevWebhookQueueable(String objectName, Set recordIds) { this.objectName = objectName;

this.recordIds = recordIds;
}
public void execute(QueueableContext context) {
String orgId = UserInfo.getOrganizationId();
// IMPORTANTE: troque pelo user_id correto da Reev
Integer reevUserId = 48104;
for (Id rid : recordIds) {
Map<String, Object> payload = new Map<String, Object>{
'organization_id' => orgId,
'user_id' => reevUserId,
'object' => objectName,
'data' => new Map<String, Object>{ 'Id' => String.valueOf(rid)
}
};
HttpRequest req = new HttpRequest(); req.setEndpoint('https://api.reev.co/webhooks/salesforce/events'); req.setMethod('POST'); req.setHeader('Content-Type', 'application/json'); req.setBody(JSON.serialize(payload));
req.setTimeout(10000);

Http http = new Http();
HttpResponse res = http.send(req);
System.debug('REEV STATUS: ' + res.getStatusCode());
System.debug('REEV BODY: ' + res.getBody());
System.debug('REEV PAYLOAD: ' + req.getBody());
}
}
}

6) Criar os 4 Triggers Apex

0:00
/0:16

6.1) Trigger de Lead

trigger ReevLeadTrigger on Lead (after insert, after update) {
if (Trigger.isAfter) {
Set ids = new Set();
for (Lead l : Trigger.new) ids.add(l.Id);
System.enqueueJob(new ReevWebhookQueueable('Lead', ids));
}
}

6.2) Trigger de Contact

trigger ReevContactTrigger on Contact (after insert, after update) {
if (Trigger.isAfter) {
Set ids = new Set();
for (Contact c : Trigger.new) ids.add(c.Id);
System.enqueueJob(new ReevWebhookQueueable('Contact', ids));
}
}

6.3) Trigger de Account

trigger ReevAccountTrigger on Account (after insert, after update) {
if (Trigger.isAfter) {
Set ids = new Set();
for (Account a : Trigger.new) ids.add(a.Id);
System.enqueueJob(new ReevWebhookQueueable('Account', ids));
}
}

6.4) Trigger de Opportunity

trigger ReevOpportunityTrigger on Opportunity (after insert, after update) {
if (Trigger.isAfter) {
Set ids = new Set();
for (Opportunity o : Trigger.new) ids.add(o.Id);
System.enqueueJob(new ReevWebhookQueueable('Opportunity', ids));
}
}

7) Publicar, ativar e validar no Salesforce

7. Salvar a classe e os triggers sem erro de compilação.
8. Se estiver em Sandbox, fazer deploy para Produção pelo fluxo da sua empresa (Change Set / DevOps Center / SFDX).
9. Editar 1 registro de cada objeto para disparar os triggers.
10. Setup -> Debug Logs: conferir REEV STATUS: 200 e payload enviado.

8) Validação funcional no Reev

  • Lead criado/alterado no Salesforce aparece/atualiza no Reev.
  • Contato criado/alterado no Salesforce aparece/atualiza no Reev.
  • Empresa (Account) com telefone atualiza em Empresas no Reev.
  • Oportunidade (Opportunity) atualiza no módulo de Oportunidades do Reev.

9) Erros comuns e correções

  • Unauthorized endpoint: Remote Site Settings não configurado para https://api.reev.co.
  • Processado mas não atualiza no Reev: user_id no Queueable incorreto para a conta Reev certa.
  • Evento vai para integração errada: falta user_id correto no payload (roteamento fica ambíguo).
  • Telefone não sincroniza: validar Account.Phone e permissões de campo (FLS) no perfil Salesforce.

10) Checklist final para cliente

  • Remote Site Settings criado e ativo.
  • Classe ReevWebhookQueueable criada.
  • Triggers de Lead, Contact, Account e Opportunity criados.
  • reevUserId preenchido corretamente no código.
  • Logs com status 200.
  • Dados aparecendo no Reev para os quatro objetos.

Método de conexão via Flows

1) Pré-requisitos

  • A integração Salesforce já deve estar conectada na Reev.
  • O usuário Salesforce que cria os gatilhos deve ter permissão de admin.
  • URL do webhook da Reev:
    api.reev.co/webhooks/salesforce/events

2) Quais objetos configurar

Criar gatilhos para os objetos:

  • Lead
  • Contact
  • Account
  • Opportunity

E disparar em:

  • criação
  • atualização

3) Como criar no Salesforce (Flow)

Ref: help.salesforce.com/s/articleView?id=platform.flow_build.htm&type=5

No Salesforce (Lightning):

  1. Vá em Configuração.
  2. Procure por Fluxos.
  3. Clique em Novo fluxo.
  4. Escolha Fluxo acionado por registro.
  5. Selecione o objeto (ex.: Lead).
  6. Defina para executar em Quando um registro for criado ou atualizado.
  7. Adicione uma ação de HTTP Callout (POST).
  8. URL:
    https://api.reev.co/webhooks/salesforce/events
  9. Envie payload JSON (modelo abaixo).
  10. Salve e Ative.
  11. Repita para Contact, Account e Opportunity.

4) Payload recomendado

Modelo mínimo:

{
"organization_id":"00DXXXXXXXXXXXX",
"object":"Lead",
"data":{
"Id":"00QXXXXXXXXXXXX"
}
}

Troque object para cada fluxo:

  • Lead
  • Contact
  • Account
  • Opportunity

> Importante: organization_id, object e data.Id são obrigatórios para rotear corretamente o evento.

5) Como descobrir o organization_id

No Salesforce, é o Org ID (começa com 00D...), visível em:

  • Company Information / Informações da empresa.

6) Teste final (obrigatório)

Após ativar os fluxos:

  1. Crie ou altere um Lead no Salesforce.
  2. Confirme na Reev se o registro foi criado/atualizado.
  3. Repita para Contact, Account e Opportunity.

7) Boas práticas

  • Começar com payload mínimo (Id) e expandir depois.
  • Garantir que os 4 fluxos estejam ativos.
  • Evitar duplicidade de fluxos para o mesmo objeto/evento.
  • Manter logs de erro do Flow habilitados para troubleshooting.

Exemplos de payloads aceitos:

{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Lead",
"data": {
"Id": "00QXXXXXXXXXXXX"
}
}

2) Payload com dados já expandidos

{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Contact",
"data": {
"Id": "003XXXXXXXXXXXX",
"FirstName": "Ana",
"LastName": "Silva",
"Email": "ana@empresa.com",
"Phone": "+5511999999999",
"AccountId": "001XXXXXXXXXXXX",
"LastModifiedDate": "2026-03-20T12:34:56.000Z"
}
}

3) Payload com record dentro de data

{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Account",
"data": {
"record": {
"Id": "001XXXXXXXXXXXX",
"Name": "Cogecom",
"Phone": "+551133333333",
"Website": "https://cogecom.com.br",
"LastModifiedDate": "2026-03-20T12:34:56.000Z"
}
}
}

4) Payload com id na raiz (Reev injeta em data.Id se faltar)

{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Opportunity",
"id": "006XXXXXXXXXXXX",
"data": {
"Name": "Projeto Enterprise",
"StageName": "Proposal",
"AccountId": "001XXXXXXXXXXXX",
"Amount": 5000
}
}

5) Lote via events (array)

{
"events": [
{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Lead",
"data": { "Id": "00QXXXXXXXXXXXX" }
},
{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Account",
"data": { "Id": "001XXXXXXXXXXXX" }
}
]
}

6) Lote no body como array puro (_json)

[
{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Contact",
"data": { "Id": "003XXXXXXXXXXXX" }
},
{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Opportunity",
"data": { "Id": "006XXXXXXXXXXXX" }
}
]

7) Compatível com records

{
"records": [
{
"organization_id": "00DXXXXXXXXXXXX",
"object": "Lead",
"data": { "Id": "00QXXXXXXXXXXXX" }
}
]
}

8) Variações de identificação de objeto aceitas

Também funciona usando:

  • object
  • sobject
  • data.sobject
  • data.attributes.type

Exemplo:

{
"organization_id": "00DXXXXXXXXXXXX",
"sobject": "Lead",
"data": {
"Id": "00QXXXXXXXXXXXX"
}
}

9) Fallback por user_id (quando não mandar organization_id)

{
"user_id": 48104,
"object": "Lead",
"data": { "Id": "00QXXXXXXXXXXXX" }
}

Mínimo recomendado (sempre)

  • organization_id
  • object (Lead, Contact, Account, Opportunity)
  • data.Id