# GHL Webhook Specs — Lançamento Cloud PhotoRF 2.0
# Preparado por Amanda-CRM em 2026-09-11
# Para integração da landing espera.px3lab.com.br → CRM Linkia PX3

---

## Endpoint: Criar Contato

**POST** `https://services.leadconnectorhq.com/contacts/`

### Headers obrigatórios

```
Authorization: Bearer <PX3_TOKEN>
Version: 2021-07-28
Content-Type: application/json
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
```

> ATENÇÃO: o Cloudflare do GHL bloqueia UA padrão de Python/Node (requests, axios sem UA).
> Sempre definir um User-Agent de browser realista. Testado: UA Chrome funciona.

### Body — payload de exemplo

```json
{
  "locationId": "W7PGxpfbsFaEEUoQOtUb",
  "firstName": "João",
  "lastName": "Silva",
  "email": "joao@exemplo.com",
  "phone": "+5511999999999",
  "source": "landing-espera",
  "tags": ["waitlist-photorf-2.0"],
  "customFields": [
    {
      "id": "ysHWPzyR0uZ2nd8D9sbi",
      "value": "instagram"
    },
    {
      "id": "Hiabk9sp0zIkgLjUYJjR",
      "value": "social"
    },
    {
      "id": "H16g1x7tRA8OoHnqiTdp",
      "value": "waitlist-photorf-2026"
    }
  ]
}
```

### Campos de referência (Custom Fields UTM — PX3)

| Campo      | ID do campo (GHL)          | Exemplo de valor         |
|------------|----------------------------|--------------------------|
| utm_source | ysHWPzyR0uZ2nd8D9sbi       | instagram / google       |
| utm_medium | Hiabk9sp0zIkgLjUYJjR       | social / cpc             |
| utm_campaign | H16g1x7tRA8OoHnqiTdp    | waitlist-photorf-2026    |
| utm_content | ppQzEkQdPyQPMlUdxCdp     | criativo-01              |
| utm_term   | bNblpNN7VTrRJ6CgBytE        | keyword                  |

### Tag obrigatória

Todo lead da landing deve receber a tag: `waitlist-photorf-2.0`

### Pipeline e Stage de entrada

> IDs confirmados após criação manual na UI (preencher abaixo quando criados):

| Item             | ID             |
|------------------|----------------|
| Pipeline ID      | _a preencher_  |
| Stage "Lista de Espera" ID | _a preencher_ |

Para adicionar o contato ao pipeline no momento da criação, incluir no body:

```json
{
  "opportunitySource": "landing-espera",
  "pipelineId": "<PIPELINE_ID>",
  "pipelineStageId": "<STAGE_LISTA_DE_ESPERA_ID>",
  "status": "open"
}
```

> Nota: esses campos criam uma oportunidade associada ao contato. Se quiser criar
> contato e oportunidade separadamente (mais controle), ver seção abaixo.

---

## Endpoint alternativo: Criar Oportunidade separada

Após criar o contato (que retorna o `contactId`), criar a oportunidade:

**POST** `https://services.leadconnectorhq.com/opportunities/`

```json
{
  "locationId": "W7PGxpfbsFaEEUoQOtUb",
  "pipelineId": "<PIPELINE_ID>",
  "pipelineStageId": "<STAGE_LISTA_DE_ESPERA_ID>",
  "contactId": "<ID_RETORNADO_NA_CRIACAO_DO_CONTATO>",
  "name": "João Silva — Waitlist PhotoRF 2.0",
  "status": "open",
  "source": "landing-espera"
}
```

---

## Resposta esperada — Criação de contato (200/201)

```json
{
  "contact": {
    "id": "abc123xyz",
    "locationId": "W7PGxpfbsFaEEUoQOtUb",
    "firstName": "João",
    "lastName": "Silva",
    "email": "joao@exemplo.com",
    "phone": "+5511999999999",
    "tags": ["waitlist-photorf-2.0"],
    ...
  }
}
```

---

## Gotchas críticos (aprendidos na integração PX3)

### 1. Sempre consumir o body do fetch (mesmo em erro)

Em JavaScript/Node, sempre fazer `await response.json()` ou `await response.text()` mesmo
quando não vai usar o resultado. Conexões que não consomem o body causam memory leak e
podem travar o pool de conexões do fetch nativo.

### 2. Dedupe 400 — extrair contactId do erro

Se o lead já existe (mesmo email), a API retorna HTTP 400 com body assim:

```json
{
  "statusCode": 400,
  "message": "Contact already exists",
  "errors": {
    "contactId": "ID_DO_CONTATO_EXISTENTE"
  }
}
```

Lógica recomendada:
```js
if (response.status === 400) {
  const err = await response.json();
  const existingId = err?.errors?.contactId;
  if (existingId) {
    // contato já existe — use o ID para adicionar tag / mover pipeline
    await addTagToContact(existingId, "waitlist-photorf-2.0");
    return existingId;
  }
}
```

### 3. Delay de indexação (30 a 90 segundos)

Contatos criados via API levam 30-90 segundos para aparecer em buscas no CRM
(endpoint GET /contacts/search). Não assumir que um contato não existe só porque
a busca retornou vazio - aguardar antes de fazer lookups pós-criação.

### 4. User-Agent de browser obrigatório

O Cloudflare em frente ao GHL bloqueia UAs padrão de bibliotecas HTTP:
- Bloqueado: `python-requests/2.x`, `node-fetch/3.x`, `axios/1.x` (sem UA)
- Funcionando: qualquer UA de Chrome/Firefox realista

Sempre passar header `User-Agent` explicitamente.

### 5. Rate limit do PIT token

O PIT token tem limite de requests por minuto (estimado: ~20-30 req/min por location).
Em imports em massa, adicionar delay de 2-3 segundos entre requests ou usar queue.
Se receber 429, aguardar 60 segundos antes de retentar.

### 6. Phone format

Sempre enviar telefone com DDI completo: `+5511999999999` (não `11999999999`).
Números sem DDI são aceitos mas podem causar problemas de deduplicação interna do GHL.

---

## Credenciais de referência (não incluir no código da landing - usar variável de ambiente)

- Location ID: `W7PGxpfbsFaEEUoQOtUb`
- Token: em `/opt/mia/workspace/clientes/px3lab/config_ghl.py` (variável `PX3_TOKEN`)

---

## Status das integrações — atualizar conforme executar

| Item                              | Status            | ID / Observação                          |
|-----------------------------------|-------------------|------------------------------------------|
| Pipeline "Lançamento PhotoRF 2.0" | Manual na UI      | Ver passos abaixo                        |
| Stage "Lista de Espera"           | Manual na UI      | Stage default (posição 0)                |
| Stage "Engajado"                  | Manual na UI      | —                                        |
| Stage "Aquecido"                  | Manual na UI      | —                                        |
| Stage "Comprou"                   | Manual na UI      | —                                        |
| Stage "Não comprou"               | Manual na UI      | —                                        |
| Tag `waitlist-photorf-2.0`        | Manual na UI      | Ver passos abaixo                        |
| Workflow de boas-vindas           | Manual na UI      | Ver passos abaixo                        |

---

## Passos manuais necessários na UI do CRM Linkia

### Criar o Pipeline

1. Acessar CRM Linkia PX3 > Opportunities > Pipelines
2. Clicar em "+ Add Pipeline"
3. Nome: **Lançamento PhotoRF 2.0**
4. Adicionar os 5 stages na ordem:
   - **Lista de Espera** (marcar como default se possível)
   - **Engajado**
   - **Aquecido**
   - **Comprou**
   - **Não comprou**
5. Salvar e anotar os IDs gerados (visíveis na URL ou via API GET após criação)
6. Atualizar a tabela de status acima e o arquivo config_ghl.py

### Criar a Tag

1. Acessar CRM Linkia PX3 > Settings > Tags
2. Clicar em "+ Add Tag"
3. Nome: **waitlist-photorf-2.0**
4. Salvar e anotar o ID retornado
5. Atualizar a tabela de status acima e o arquivo config_ghl.py

### Criar o Workflow de Boas-Vindas

> A API GHL não expõe endpoints de criação/edição de workflows (apenas leitura).
> Este passo obrigatoriamente precisa ser feito na UI.

1. Acessar CRM Linkia PX3 > Automation > Workflows
2. Clicar em "+ Create Workflow" > "Start from Scratch"
3. Nome: **Boas-vindas Waitlist PhotoRF 2.0**
4. Configurar o Trigger:
   - Trigger: **Contact Created**
   - Filtro: Tag = `waitlist-photorf-2.0`
5. Adicionar Action 1 — Email de boas-vindas:
   - Action: **Send Email**
   - From: conta de email configurada no PX3
   - Subject: `Você está na lista - Cloud PhotoRF 2.0`
   - Body (sugestão):

```
Oi {{contact.firstName}},

Você está dentro.

Vou te avisando as novidades por aqui e por WhatsApp. Guarde a data: 23 de setembro.

Até lá,
Vinícius
```

6. Adicionar Action 2 — Adicionar ao pipeline:
   - Action: **Add to Pipeline/Opportunity**
   - Pipeline: Lançamento PhotoRF 2.0
   - Stage: Lista de Espera
   - Status: Open
7. Publicar o workflow (toggle "Publish")

---

*Arquivo gerado por Amanda-CRM | Atualizado em 2026-09-11*
