Skip to content

Integracao com CRM

Sincronize entregas do fast_deliv com seu CRM (Salesforce, HubSpot, Pipedrive, etc.) para acompanhar clientes e automatizar followups.


Estrategias

Estrategia Quando usar Latencia
Polling periodico CRM nao aceita webhook Minutos
Webhook → CRM Atualizacao imediata ao mudar status Segundos

Mapeamento de campos

Campo fast_deliv Campo CRM sugerido Descricao
delivery.id external_id ID externo da atividade
delivery.title subject / deal_name Nome da atividade ou negocio
delivery.status stage / status Estagio do pipeline
delivery.origin_address pickup_address Endereco de coleta
delivery.destination_address delivery_address Endereco de entrega
delivery.driver_earnings logistics_cost Custo logistico
delivery.created_at activity_date Data da atividade
delivery.completed_at closed_date Data de conclusao
driver.full_name assigned_to Responsavel pela entrega

Sincronizacao via polling

Script Python que sincroniza entregas periodicamente:

import time
import requests
from datetime import datetime, timezone

BASE_URL = "https://fast-deliv-backend.vercel.app"
CRM_BASE_URL = "https://api.seu-crm.com"

def get_fast_deliv_deliveries(token: str) -> list[dict]:
    resp = requests.get(
        f"{BASE_URL}/api/v1/deliveries",
        headers={"Authorization": f"Bearer {token}"},
    )
    resp.raise_for_status()
    return resp.json()

def upsert_to_crm(crm_token: str, delivery: dict) -> None:
    """Cria ou atualiza um registro no CRM."""
    payload = {
        "external_id": delivery["id"],
        "subject": delivery["title"],
        "stage": map_status_to_crm_stage(delivery["status"]),
        "pickup_address": delivery["origin_address"],
        "delivery_address": delivery["destination_address"],
        "logistics_cost": delivery.get("driver_earnings"),
        "activity_date": delivery["created_at"],
    }

    # Verificar se ja existe pelo external_id
    search = requests.get(
        f"{CRM_BASE_URL}/activities",
        headers={"Authorization": f"Bearer {crm_token}"},
        params={"external_id": delivery["id"]},
    )
    existing = search.json().get("results", [])

    if existing:
        # Atualizar
        crm_id = existing[0]["id"]
        requests.patch(
            f"{CRM_BASE_URL}/activities/{crm_id}",
            headers={"Authorization": f"Bearer {crm_token}"},
            json=payload,
        )
    else:
        # Criar
        requests.post(
            f"{CRM_BASE_URL}/activities",
            headers={"Authorization": f"Bearer {crm_token}"},
            json=payload,
        )

def map_status_to_crm_stage(status: str) -> str:
    return {
        "pending":     "Aguardando",
        "assigned":    "Em Rota de Coleta",
        "in_progress": "Em Transito",
        "completed":   "Entregue",
        "cancelled":   "Cancelado",
    }.get(status, status)

# Loop de sincronizacao a cada 5 minutos
def sync_loop(fast_deliv_token: str, crm_token: str):
    while True:
        print(f"[{datetime.now(timezone.utc).isoformat()}] Sincronizando...")
        deliveries = get_fast_deliv_deliveries(fast_deliv_token)
        for d in deliveries:
            upsert_to_crm(crm_token, d)
        print(f"  {len(deliveries)} entregas sincronizadas")
        time.sleep(300)  # 5 minutos

if __name__ == "__main__":
    import os
    sync_loop(
        fast_deliv_token=os.environ["FAST_DELIV_TOKEN"],
        crm_token=os.environ["CRM_TOKEN"],
    )

Webhook → CRM (atualizacao imediata)

Configure um endpoint no seu servidor para receber eventos do fast_deliv e repassar ao CRM:

from fastapi import FastAPI, Request, BackgroundTasks
import requests

app = FastAPI()
CRM_BASE_URL = "https://api.seu-crm.com"
CRM_TOKEN = "seu_crm_token"

def push_to_crm(delivery: dict):
    """Enfileirar atualizacao no CRM em background."""
    stage = map_status_to_crm_stage(delivery["status"])

    # Buscar pelo external_id e atualizar estagio
    search = requests.get(
        f"{CRM_BASE_URL}/activities",
        headers={"Authorization": f"Bearer {CRM_TOKEN}"},
        params={"external_id": delivery["id"]},
    )
    results = search.json().get("results", [])
    if results:
        crm_id = results[0]["id"]
        requests.patch(
            f"{CRM_BASE_URL}/activities/{crm_id}",
            headers={"Authorization": f"Bearer {CRM_TOKEN}"},
            json={"stage": stage},
        )
        print(f"CRM atualizado: entrega {delivery['id']} -> {stage}")

@app.post("/webhooks/delivery-status")
async def delivery_status_webhook(request: Request, bg: BackgroundTasks):
    """
    Configure seu sistema para chamar este endpoint
    quando uma entrega mudar de status.
    (Implemente sua propria autenticacao aqui)
    """
    payload = await request.json()
    delivery = payload.get("delivery")
    if delivery:
        bg.add_task(push_to_crm, delivery)
    return {"ok": True}

Tratamento de duplicatas

Sempre use o campo id da entrega como external_id no CRM para evitar duplicatas:

def safe_upsert(crm_client, delivery: dict) -> str:
    """Retorna 'created' ou 'updated'."""
    external_id = delivery["id"]

    existing = crm_client.find_by_external_id(external_id)
    if existing:
        crm_client.update(existing["id"], build_payload(delivery))
        return "updated"
    else:
        crm_client.create(build_payload(delivery))
        return "created"

Idempotencia

O fast_deliv pode chamar seu webhook mais de uma vez para o mesmo evento. Sempre implemente upsert (nao apenas insert) para evitar duplicatas.