name: painel-corretor-api-discovery
description: Reverse-engineering Painel do Corretor (Trindade) API via n8n workflow token extraction and GraphQL discovery
category: devops
Painel do Corretor — API Discovery via n8n
Context
Painel do Corretor (Trindade Tecnologia) has no public API documentation. The REST API is blocked by Cloudflare (GET → 405). The only working access is via GraphQL using a JWT extracted from an active n8n workflow.
Key Findings
Authentication
- - Panel uses Auth0 RS256 JWTs stored in n8n workflow nodes
- - Token extracted from:
workflow_entity.nodesfield in n8n PostgreSQL database - - Token format:
Bearer eyJhbG...embedded in workflow JSON - - Token lifetime: ~3 days (exp field in JWT payload)
- - When token expires: get fresh one from n8n DB again
- - URL:
https://api.paineldocorretor.net/graphql - - Headers:
Authorization: Bearer,X-Tenant: a1af7a2f-7ec6-40cd-b257-86c045875979 - - Query:
negociosElastic— the working query that n8n uses - - Table:
crm_leads_duplicatein Supabase Cloud projectdauftiqcvgaydddoxqhh - - Contains Panel leads with: Id, Nome, Etapa, Contato.Email, Contato.Telefones (empty), CriadoEm, source=CRM
- - n8n workflow syncs every 1 minute via cron
- -
contato.telefonesreturns[](empty) for ALL leads in GraphQL - - But
contato.emailIS populated - - This means email matching with Chatwoot is viable, phone matching is not via API
- -
painel_negocio_idis the Painel negocio UUID — does NOT matchcrm_leads_duplicate.Iddirectly (type mismatch) - - All
chatwoot_conversation_idvalues are NULL — must use Chatwoot Search API to resolve by email - -
etapastores the normalized etapa key (e.g.novos_leads) already normalized from display name - - REST returns 405 (Cloudflare blocked)
- - GraphQL JWTs expire →
AUTH_NOT_AUTHORIZED - - API token:
2AfB8VhS79FTmxG1dL8774RJ - - Account ID:
1 - - URL:
https://chat.rochasalesseguros.com.br - - Labels (already exist):
etapa-novos_leads,etapa-qualificacao, etc.
⚠️ JWT expiration manifests as 500 errors from Painel GraphQL (not 401). If negociosElastic suddenly returns 500, the first troubleshooting step is to extract and update the JWT secret in Supabase:
`bash
Extract fresh JWT from n8n
docker exec n8n-postgres psql -U n8n -t -c \
"SELECT nodes FROM workflow_entity WHERE name = 'RS - Automação CRM Rocha Sales (Batch Optimized) NOVA TABELA';" \
| grep -o 'Bearer eyJ[a-zA-Z0-9_-]\.[a-zA-Z0-9_-]\.[a-zA-Z0-9_-]*' | head -1
Update secret (no redeploy needed — Edge Functions read secrets at runtime)
supabase secrets set PAINEL_JWT="
`
IMPORTANT: Do NOT redeploy the Edge Function after updating the secret. Supabase Edge Functions read Deno.env.get() at runtime, so only the secret needs updating.
Database Connection (n8n)
`bash
docker exec n8n-postgres psql -U n8n -c "SELECT nodes FROM workflow_entity WHERE name = 'RS - Automação CRM Rocha Sales (Batch Optimized) NOVA TABELA';"
`
Extract JWT with: grep -o 'Bearer eyJ[a-zA-Z0-9_-]\.[a-zA-Z0-9_-]\.[a-zA-Z0-9_-]*'
GraphQL Endpoint
Query Format (n8n-style)
`graphql
query FooBarQuery($request_0: NegociosFilterInput!) {
negocios_0: negociosElastic(request: $request_0) {
quantidade
items {
id nome
etapa { id nome }
contato { id nome email telefones }
valor
etiquetas { nome }
criadoEm
}
}
}
Variables:
{"request_0": {"busca": "", "take": 5000, "conditions": [{"field": "etapaId", "operator": "", "value": ""}]}}
`
Stage IDs (all 9 + Sem Interesse = 10) — VERIFIED
`
60008110-e9b1-4512-b514-ab1539ea1a1e → Novos Leads
885d4f95-99e5-42a0-8150-b494c42c0e34 → Qualificação
6699997d-6978-4679-8b4c-eaab9917fefd → Remarketing
4646a3e9-b21a-4339-b75b-6997fa3dbb76 → Reunião Agendada
4e61480b-b4dc-4b80-b0c8-dd3ddf8e43b2 → Proposta Enviada p/cliente
29511da1-1e40-4e9c-8b14-a268ccbdc1d0 → Análise Seguradora
2584da59-4c1e-4fcb-8cba-8374acd896a7 → Aguardando Pagamento
df8db361-5b4c-4e66-baac-afcfd9fbe50a → Negócios Fechados
70150b84-6864-4cff-aae1-83195a182d8d → Declinado ← verify this UUID
63f4b9df-55d6-4ff0-a42c-af5ff2ff367b → Sem Interesse
`
REST API (BROKEN — Cloudflare blocked)
| Method | Endpoint | Result |
| -------- | ---------- | -------- |
| GET | /api/crm/negocios | 405 Method Not Allowed (NOT 401!) |
| POST | /api/crm/negocios | 403 Forbidden (Cloudflare) |
| PUT/PATCH | /api/crm/negocios/{id} | 405 |
Never use the REST API for Painel sync — use GraphQL negociosElastic exclusively.
Supabase Table (populated by n8n)
Critical Limitation
Python Extraction Script
`python
import subprocess, re, base64, json, urllib.request
Extract JWT from n8n
result = subprocess.run(
['docker', 'exec', 'n8n-postgres', 'psql', '-U', 'n8n', '-t', '-c',
"SELECT nodes FROM workflow_entity WHERE name = 'RS - Automação CRM Rocha Sales (Batch Optimized) NOVA TABELA';"],
capture_output=True, text=True, timeout=30
)
jwt_match = re.search(r'Bearer (eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+)', result.stdout.strip())
token = jwt_match.group(1)
Use token with GraphQL
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}",
"X-Tenant": "a1af7a2f-7ec6-40cd-b257-86c045875979"
}
...
`
Lessons Learned
1. When official API is blocked, look for automation tools (n8n, zapier, etc.) that already use it — they have valid credentials
2. n8n workflows store credentials in PostgreSQL workflow_entity table — docker exec into n8n's DB to extract
3. GraphQL negociosElastic is the working query — different from negocios which gives AUTH_NOT_AUTHORIZED
4. REST API blocked by Cloudflare — not a code problem, a infrastructure config problem
5. When GraphQL telehones array is empty but email works, use email as the join key
chatwoot_painel_map table (for Edge Functions)
`
chatwoot_painel_map — 1000 rows in Supabase project dauftiqcvgaydddoxqhh
Columns: id (UUID), painel_negocio_id (UUID), chatwoot_conversation_id (INTEGER, NULL for all),
etapa (normalized API key like 'novos_leads'), source ('CRM'|'vps-direct')
`
Edge Functions: Read from crm_leads_duplicate, not Painel API
Supabase Edge Functions (Deno) should NOT call the Painel API directly:
Instead, use crm_leads_duplicate table which n8n syncs every 1 min. The table has 999 CRM leads with Etapa column storing display names like "Novos Leads" (NOT UUID IDs — must normalize via ETAPA_DISPLAY_MAP). See skill painel-corretor-graphql-api for the complete normalization function and Edge Function template.
Supabase Edge Function secret for Painel JWT (for reference only — use crm_leads_duplicate instead)
`
supabase secrets set PAINEL_JWT="
`
JWT is stored in n8n Postgres: SELECT nodes FROM workflow_entity WHERE id = 'fuVLvmFke1C7GskY'; (RS NOVA TABELA workflow, updated 2026-05-16).