> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useaira.com/llms.txt
> Use this file to discover all available pages before exploring further.

# HubSpot

> Conecte o HubSpot à Aira e transforme deals fechados em clientes, contratos e cobranças — via app nativo ou webhooks.

> A integração com o HubSpot permite que seu time comercial mantenha o CRM como fonte de verdade dos dados de cliente e, ao fechar um deal, dispare automaticamente a criação do cliente, conta de pagamento e contrato correspondentes na Aira — junto com o início da cobrança.

<h2 id="o-que-e-possivel">
  O que é possível
</h2>

* Criar cliente, conta de pagamento e contrato na Aira a partir de um deal fechado no HubSpot
* Iniciar a cobrança do contrato automaticamente, sem retrabalho manual
* Registrar expansões (novos produtos) em contratos já existentes
* Vincular registros entre os dois sistemas e evitar duplicidade ao reprocessar o mesmo deal
* Anexar rastreabilidade de receita (proposta + data efetiva) por produto, quando o módulo está habilitado

<br />

<h2 id="como-integrar">
  Como integrar
</h2>

Existem **dois modos** de conectar o HubSpot à Aira. Os dois chegam ao mesmo resultado — cliente, conta de pagamento e contrato na Aira — mudando apenas como a conexão é feita e quem monta os dados.

|                                 | **App HubSpot** (recomendado)                            | **Webhooks via API**                                 |
| ------------------------------- | -------------------------------------------------------- | ---------------------------------------------------- |
| Como conecta                    | Instala o app da Aira no seu portal (OAuth)              | Gera uma API key e monta a chamada você mesmo        |
| O que dispara                   | Automático, quando o deal entra no estágio de fechamento | Você dispara (workflow, Zapier, código próprio)      |
| Dados do deal                   | A Aira lê o deal e os itens direto do HubSpot            | Você monta e envia o payload completo                |
| Mapeamento de campos e produtos | A Aira configura junto com você                          | Você mapeia produtos → UUIDs no seu fluxo            |
| Processamento                   | Assíncrono, com reprocessamento automático               | Síncrono                                             |
| Ideal para                      | A maioria dos times — sem desenvolvimento                | Integrações customizadas / controle total do payload |

<Note>
  O **App HubSpot** é o caminho recomendado: não exige desenvolvimento do seu lado e a Aira lê os dados do deal automaticamente. Use os **Webhooks via API** quando você precisar montar o payload por conta própria ou já tiver um fluxo intermediário (workflow, Zapier, integração customizada).
</Note>

<br />

<h2 id="app-hubspot">
  App HubSpot
</h2>

O app nativo da Aira é instalado no seu portal HubSpot e passa a observar os deals. Quando um deal entra no estágio de fechamento que você definiu, a Aira lê o deal direto do HubSpot e cria os registros correspondentes — sem você precisar montar nenhuma requisição.

<h3 id="app-como-funciona">
  Como funciona
</h3>

<Steps>
  <Step title="O deal é fechado no HubSpot">
    Um deal entra no estágio de fechamento configurado (ex: *Ganho* / *Closed won*).
  </Step>

  <Step title="O HubSpot avisa a Aira">
    O app é inscrito em mudanças de estágio dos deals. Ao entrar no estágio configurado, o HubSpot notifica a Aira automaticamente.
  </Step>

  <Step title="A Aira lê o deal">
    Usando o acesso concedido na instalação, a Aira lê as propriedades do deal (dados do cliente) e os itens de linha (produtos) direto do HubSpot.
  </Step>

  <Step title="A Aira cria os registros e inicia a cobrança">
    Os dados são mapeados para o modelo da Aira, que cria o cliente, a conta de pagamento e o contrato com os planos correspondentes, e dá início ao ciclo de cobrança.
  </Step>
</Steps>

<h3 id="app-leitura">
  O que a Aira lê
</h3>

A integração é **somente leitura** no seu HubSpot: a Aira **lê** deals e itens de linha, e **nunca cria, edita ou apaga** nada no seu CRM. Os acessos concedidos na instalação se limitam a:

| Acesso                        | Para quê                                               |
| ----------------------------- | ------------------------------------------------------ |
| `crm.objects.deals.read`      | Ler as propriedades do deal fechado (dados do cliente) |
| `crm.objects.line_items.read` | Ler os itens de linha do deal (produtos contratados)   |

<h3 id="app-mapeamento">
  Mapeamento
</h3>

Cada portal HubSpot tem suas próprias propriedades e seu próprio catálogo de produtos. Por isso, **o de-para é definido junto com a Aira no onboarding**, a partir do seu setup:

* **Campos do deal → dados da Aira** — quais propriedades do deal correspondem a razão social, CNPJ/CPF, e-mails de cobrança e data de início do contrato.
* **Produtos do HubSpot → planos da Aira** — quais produtos (itens de linha) do deal correspondem a quais planos cadastrados na Aira.
* **Estágio de disparo** — qual estágio do funil representa o fechamento que deve criar o contrato.

<Note>
  O mapeamento fica do lado da Aira — você não precisa configurar nada técnico no HubSpot além de instalar o app. Basta alinhar com o time da Aira quais campos e produtos você usa.
</Note>

<h3 id="app-criado">
  O que é criado na Aira
</h3>

Para cada deal fechado, a Aira cria (ou reaproveita):

* **Cliente** — identificado pelo documento (CNPJ/CPF). Cliente já existente é reutilizado, não duplicado.
* **Conta de pagamento** — com razão social, documento fiscal e e-mails de cobrança extraídos do deal.
* **Contrato** — com uma instância de plano para cada produto mapeado, e ciclo de faturamento iniciado.

<h3 id="app-idempotencia">
  Idempotência
</h3>

Todo contrato criado pela integração fica **vinculado ao deal de origem**. Se o mesmo deal disparar mais de uma vez (ou for reprocessado), a Aira reconhece o vínculo e **não cria um contrato duplicado**.

<h3 id="app-seguranca">
  Segurança e confiabilidade
</h3>

* **Assinatura verificada** — cada notificação recebida do HubSpot tem sua assinatura validada antes de ser processada.
* **Processamento assíncrono com reprocessamento** — as notificações entram em uma fila e são processadas em segundo plano; falhas temporárias são reprocessadas automaticamente.
* **Somente leitura** — a Aira nunca escreve no seu HubSpot.

<h3 id="app-conectar">
  Conectar o HubSpot
</h3>

<Steps>
  <Step title="Alinhe o setup com a Aira">
    Fale com o suporte ([contato@useaira.com](mailto:contato@useaira.com)) informando o estágio que representa o fechamento e enviando um exemplo de deal já fechado. Com isso a Aira configura o de-para de campos e produtos do seu portal.
  </Step>

  <Step title="Instale o app no seu portal">
    A Aira envia um link de instalação. Ao abri-lo logado como administrador do portal, você autoriza o acesso de leitura a deals e itens de linha. A conexão fica salva para o seu portal.
  </Step>

  <Step title="Valide com um deal de teste">
    Mova um deal para o estágio de fechamento configurado e confirme com a Aira que o cliente, a conta de pagamento e o contrato foram criados corretamente.
  </Step>
</Steps>

<br />

<h2 id="webhooks-api">
  Webhooks via API
</h2>

Neste modo você mesmo dispara a integração, enviando um `POST` para a Aira quando um deal é fechado ou expandido. Útil para times que já têm um fluxo intermediário (workflow do HubSpot, Zapier, código próprio) ou que precisam de controle total sobre o payload. A Aira processa a chamada **sincronamente**.

| Webhook       | URL                                   | Quando usar                             |
| ------------- | ------------------------------------- | --------------------------------------- |
| **Novo deal** | `POST /v1/webhooks/hubspot/new-deal`  | Deal novo fechado no HubSpot            |
| **Expansão**  | `POST /v1/webhooks/hubspot/expansion` | Upsell/cross-sell em contrato existente |

<h3 id="autenticacao">
  Autenticação
</h3>

Todas as requisições precisam incluir o header `X-API-KEY` com uma chave que tenha a role `contracts:write`:

```bash theme={null}
curl -X POST https://api.useaira.com/v1/webhooks/hubspot/new-deal \
  -H "X-API-KEY: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

| Código             | Significado                                                           |
| ------------------ | --------------------------------------------------------------------- |
| `204 No Content`   | Webhook processado com sucesso                                        |
| `400 Bad Request`  | Payload inválido ou regra de negócio violada                          |
| `401 Unauthorized` | API key ausente ou inválida                                           |
| `403 Forbidden`    | Chave sem role `contracts:write` ou integração desabilitada no tenant |
| `404 Not Found`    | Contrato ou cliente não encontrado (expansão)                         |

<Note>
  Cada chamada recebida é registrada no log de auditoria de webhooks, incluindo IP, user-agent, payload e código de resposta.
</Note>

<h3 id="webhook-novo-deal">
  Webhook: Novo deal
</h3>

`POST /v1/webhooks/hubspot/new-deal`

Cria um novo contrato na Aira a partir de um deal do HubSpot. Se o cliente (identificado por `externalId`) ainda não existir, ele é criado. Se a conta de pagamento (identificada por `taxId`) já existir para aquele cliente, ela é reutilizada — caso contrário, é criada.

<h4 id="corpo-novo-deal">
  Corpo da requisição
</h4>

```json theme={null}
{
  "customer": {
    "externalId": "hubspot_deal_12345",
    "name": "Empresa Exemplo Ltda",
    "customFields": {
      "segment": "enterprise"
    }
  },
  "paymentAccount": {
    "businessName": "Empresa Exemplo Ltda",
    "taxId": "12345678000190",
    "taxIdType": "cnpj",
    "emails": ["financeiro@empresaexemplo.com"]
  },
  "contract": {
    "startDate": "2026-05-01",
    "endDate": "2027-04-30",
    "rateAdjustmentIndex": "ipca",
    "customFields": {
      "sales_owner": "maria@useaira.com"
    }
  },
  "products": [
    {
      "productId": "7f3a5d2c-...-uuid",
      "revenueTraceability": [
        {
          "proposal": "PROP-2026-0042",
          "effectiveDate": "2026-05"
        }
      ]
    }
  ]
}
```

<h4 id="campos-novo-deal">
  Campos
</h4>

| Campo                                            | Tipo                | Obrigatório      | Descrição                                                                    |
| ------------------------------------------------ | ------------------- | ---------------- | ---------------------------------------------------------------------------- |
| `customer.externalId`                            | string              | sim              | Identificador único do cliente no HubSpot — usado para vincular e deduplicar |
| `customer.name`                                  | string              | sim              | Nome do cliente (razão social ou nome fantasia)                              |
| `customer.customFields`                          | object              | não              | Campos customizados livres (chave → valor)                                   |
| `paymentAccount.businessName`                    | string              | sim              | Razão social da conta de pagamento                                           |
| `paymentAccount.taxId`                           | string              | sim              | CNPJ ou CPF (apenas dígitos)                                                 |
| `paymentAccount.taxIdType`                       | `"cnpj"` \| `"cpf"` | sim              | Tipo do documento fiscal                                                     |
| `paymentAccount.emails`                          | string\[]           | não              | Emails para envio de cobranças e notas fiscais                               |
| `contract.startDate`                             | date (`YYYY-MM-DD`) | sim              | Data de início do contrato                                                   |
| `contract.endDate`                               | date \| null        | não              | Data de término (null para contratos sem fim definido)                       |
| `contract.rateAdjustmentIndex`                   | enum \| null        | não              | `none`, `igpm`, `ipca`, `other` ou `null`                                    |
| `contract.customFields`                          | object              | não              | Campos customizados do contrato                                              |
| `products`                                       | array               | sim              | Lista de produtos contratados (mínimo 1)                                     |
| `products[].productId`                           | uuid                | sim              | UUID do produto já cadastrado na Aira                                        |
| `products[].revenueTraceability`                 | array               | não              | Rastreabilidade de receita (requer módulo habilitado)                        |
| `products[].revenueTraceability[].proposal`      | string              | sim (se enviada) | Identificador da proposta comercial                                          |
| `products[].revenueTraceability[].effectiveDate` | string (`YYYY-MM`)  | sim (se enviada) | Mês de vigência, no formato `AAAA-MM`                                        |

<h4 id="comportamento-novo-deal">
  Comportamento
</h4>

* Cliente com `externalId` já existente é **reutilizado**. Conta de pagamento com `taxId` já existente para o cliente também é reutilizada.
* O contrato é criado com alocação de **100%** para a conta de pagamento informada.
* Ciclo de faturamento padrão: **mensal**, ancorado no **primeiro dia do mês**.
* Para cada produto, uma instância do plano mapeado é criada no contrato.
* Se o módulo de rastreabilidade de receita estiver habilitado, os itens de `revenueTraceability` são persistidos.

<h3 id="webhook-expansao">
  Webhook: Expansão
</h3>

`POST /v1/webhooks/hubspot/expansion`

Adiciona novos produtos (e, opcionalmente, rastreabilidade de receita) a um contrato **já existente**. Útil para registrar upsells, cross-sells e aumentos de escopo sem duplicar o contrato.

<h4 id="corpo-expansao">
  Corpo da requisição
</h4>

```json theme={null}
{
  "contractId": "a1b2c3d4-...-uuid",
  "customerExternalId": "hubspot_deal_12345",
  "products": [
    {
      "productId": "9e8d7c6b-...-uuid",
      "revenueTraceability": [
        {
          "proposal": "PROP-2026-0088",
          "effectiveDate": "2026-07"
        }
      ]
    }
  ]
}
```

<h4 id="campos-expansao">
  Campos
</h4>

| Campo                                            | Tipo               | Obrigatório      | Descrição                                                      |
| ------------------------------------------------ | ------------------ | ---------------- | -------------------------------------------------------------- |
| `contractId`                                     | uuid               | sim              | ID do contrato existente na Aira                               |
| `customerExternalId`                             | string             | sim              | `externalId` do cliente — deve pertencer ao contrato informado |
| `products`                                       | array              | sim              | Lista de produtos a adicionar (mínimo 1)                       |
| `products[].productId`                           | uuid               | sim              | UUID do produto já cadastrado na Aira                          |
| `products[].revenueTraceability`                 | array              | não              | Rastreabilidade de receita (requer módulo habilitado)          |
| `products[].revenueTraceability[].proposal`      | string             | sim (se enviada) | Identificador da proposta                                      |
| `products[].revenueTraceability[].effectiveDate` | string (`YYYY-MM`) | sim (se enviada) | Mês de vigência                                                |

<h4 id="comportamento-expansao">
  Comportamento
</h4>

* Valida que o `contractId` existe e que o `customerExternalId` pertence ao cliente daquele contrato (caso contrário retorna `400` ou `404`).
* Para cada produto: se o plano correspondente ainda não está no contrato, uma nova instância é criada. Produtos já presentes são ignorados.
* Itens de rastreabilidade de receita são deduplicados pela combinação `contractId + productId + proposal + effectiveDate`. Duplicatas são ignoradas silenciosamente.

<Note>
  A expansão **não altera** datas, alocação ou índice de reajuste do contrato original — apenas adiciona produtos e rastreabilidade de receita.
</Note>

<h3 id="configuracao">
  Configuração
</h3>

<Steps>
  <Step title="Habilitar a integração">
    Entre em contato com o suporte ([contato@useaira.com](mailto:contato@useaira.com)) para ativar a integração HubSpot no seu tenant.
  </Step>

  <Step title="Solicitar a API key">
    Solicite ao time da Aira uma API key com a role `contracts:write` através do suporte ([contato@useaira.com](mailto:contato@useaira.com)). Armazene o valor em local seguro.
  </Step>

  <Step title="Configurar workflow no HubSpot">
    Crie um workflow que dispare um `POST` para os endpoints da Aira quando um deal entrar no estágio desejado (ex: `closed-won`) ou quando uma expansão for registrada. Inclua o header `X-API-KEY` com a chave gerada.
  </Step>

  <Step title="Mapear produtos">
    Cada `productId` enviado no webhook precisa corresponder a um produto cadastrado na Aira. Mantenha uma tabela de mapeamento atualizada no seu workflow entre produtos do HubSpot e UUIDs da Aira.
  </Step>
</Steps>

<h3 id="erros-comuns">
  Erros comuns
</h3>

| Erro                                         | Causa provável                                               |
| -------------------------------------------- | ------------------------------------------------------------ |
| `403` — HubSpot integration is not enabled   | Integração não ativada no tenant — contate o suporte         |
| `403` — API key sem permissão                | Chave não tem a role `contracts:write`                       |
| `404` — contract not found                   | `contractId` inexistente na Aira (expansão)                  |
| `404` — customer not found                   | `customerExternalId` não encontrado na Aira (expansão)       |
| `400` — customer does not belong to contract | Cliente e contrato informados não correspondem ao mesmo deal |
| Produto não aparece no contrato              | `productId` não está mapeado para um plano ativo             |

<br />

<h2 id="proximos-passos">
  Próximos passos
</h2>

* [Contratos](/contratos/criar-contratos) — estrutura e ciclo de vida de contratos na Aira
* [Clientes](/clientes/criar-clientes) — modelo de clientes e uso do `externalId`
* [Autenticação da API](/api-reference/autenticacao) — como solicitar e usar API keys
