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.
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.
5) Classe Apex Queueable (única)
Crie a classe abaixo com o nome ReevWebhookQueueable:
public with sharing class ReevWebhookQueueable implements Queueable, Database.AllowsCallouts {
private String objectName;
private Set
public ReevWebhookQueueable(String objectName, Set
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
6.1) Trigger de Lead
trigger ReevLeadTrigger on Lead (after insert, after update) {
if (Trigger.isAfter) {
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
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
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
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):
- Vá em Configuração.
- Procure por Fluxos.
- Clique em Novo fluxo.
- Escolha Fluxo acionado por registro.
- Selecione o objeto (ex.: Lead).
- Defina para executar em Quando um registro for criado ou atualizado.
- Adicione uma ação de HTTP Callout (POST).
- URL:
https://api.reev.co/webhooks/salesforce/events - Envie payload JSON (modelo abaixo).
- Salve e Ative.
- 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:
- Crie ou altere um Lead no Salesforce.
- Confirme na Reev se o registro foi criado/atualizado.
- 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