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

# Upsert de uma entidade

> Cria ou atualiza uma entidade no gu1 com detecção de duplicatas que resolve conflitos em ID externo, identificação fiscal e dados de contato.

## Visão Geral

O endpoint de upsert cria inteligentemente uma nova entidade ou atualiza uma existente com base em estratégias configuráveis de detecção de duplicatas. Ele gerencia automaticamente conflitos e previne registros duplicados usando correspondência exata, correspondência difusa ou detecção de similaridade alimentada por IA.

## Endpoint

```
PUT http://api.gu1.ai/entities/upsert
```

## Autenticação

Requer uma chave de API válida no cabeçalho Authorization:

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```

## Corpo da Requisição

<ParamField body="entity" type="object" required>
  Os dados da entidade (mesma estrutura de [Criar entidade](/pt/api-reference/entities/create)), incluindo campos raiz opcionais como `email`, `phone` e `nationality` (ISO 3166-1 alpha-2 ou rótulo mapeável).
</ParamField>

<Note>
  O esquema pode aceitar as mesmas chaves que criar (ex.: `monitoring`, `autoExecuteIntegrations`). **O upsert não executa auto-enriquecimentos nem aplica `monitoring`.** Use `POST /entities` ou `POST /entities/automatic` para lista / Regtia op 1 durante o enriquecimento.
</Note>

<ParamField body="options" type="object">
  Opções de configuração para o comportamento do upsert
</ParamField>

<ParamField body="options.conflictResolution" type="enum">
  Como lidar com conflitos quando uma entidade existente é encontrada:

  * `source_wins` - Novos dados sobrescrevem os dados existentes
  * `target_wins` - Mantém os dados existentes, ignora novos dados
  * `manual_review` - Sinaliza para revisão manual sem atualizar
  * `smart_merge` (padrão) - Mescla inteligentemente ambos os conjuntos de dados
</ParamField>

<ParamField body="options.deduplicationStrategy" type="enum">
  Estratégia para detectar entidades duplicadas:

  * `exact_match` - Correspondência por externalId e taxId (insensível a maiúsculas)
  * `fuzzy_match` - Correspondência de similaridade em name e taxId (limiar de 80%)
  * `ai_similarity` - Detecção de similaridade semântica alimentada por IA
  * `hybrid` (recomendado) - Correspondência exata com fallback difuso
</ParamField>

<ParamField body="options.createRelationships" type="boolean" default="true">
  Se deve criar automaticamente relacionamentos entre entidades
</ParamField>

## Resposta

<ResponseField name="success" type="boolean">
  Indica se a operação foi bem-sucedida
</ResponseField>

<ResponseField name="action" type="string">
  A ação realizada: `created` ou `updated`
</ResponseField>

<ResponseField name="entity" type="object">
  O estado final da entidade após o upsert
</ResponseField>

<ResponseField name="previousEntity" type="object">
  O estado da entidade antes da atualização (null se recém-criada)
</ResponseField>

<ResponseField name="confidence" type="number">
  Pontuação de confiança (0-1) para a correspondência de detecção de duplicatas
</ResponseField>

<ResponseField name="reasoning" type="string">
  Explicação do porquê a entidade foi criada/atualizada
</ResponseField>

<ResponseField name="conflicts" type="array">
  Array de conflitos em nível de campo detectados durante a mesclagem (se houver)
</ResponseField>

## Estratégias de Deduplicação

### Correspondência Exata

Corresponde entidades com base em comparação exata de campos (insensível a maiúsculas):

* **Campos**: `externalId`, `taxId`
* **Caso de uso**: Quando você tem identificadores únicos confiáveis
* **Velocidade**: Mais rápida
* **Precisão**: 100% para valores idênticos

### Correspondência Difusa

Usa distância de Levenshtein para correspondência de similaridade:

* **Campos**: `name`, `taxId`
* **Limiar**: 80% de similaridade
* **Caso de uso**: Ao lidar com erros de digitação ou variações
* **Velocidade**: Moderada
* **Precisão**: Alta para strings similares

### Similaridade IA

Detecção de similaridade semântica alimentada por IA:

* **Método**: Embeddings vetoriais e similaridade de cosseno
* **Caso de uso**: Correspondência complexa de múltiplos campos
* **Velocidade**: Mais lenta
* **Precisão**: Mais alta para entidades semanticamente similares

### Híbrida (Recomendada)

Combina correspondência exata e difusa:

* **Primária**: Correspondência exata em identificadores
* **Fallback**: Correspondência difusa em nomes
* **Limiar de confiança**: 80%
* **Caso de uso**: Melhor equilíbrio entre velocidade e precisão

## Estratégias de Resolução de Conflitos

### smart\_merge (Padrão)

Mescla inteligentemente dados de ambas as fontes:

* **Prioridade**: Dados mais recentes para campos simples
* **Arrays**: Mescla e deduplica
* **Objetos**: Mesclagem profunda com detecção de conflitos
* **Valores vazios**: Preserva valores existentes não vazios

### source\_wins

Novos dados substituem completamente os existentes:

* **Caso de uso**: Quando os dados recebidos são autoritativos
* **Comportamento**: Todos os campos da origem
* **Risco**: Pode perder dados existentes valiosos

### target\_wins

Mantém dados existentes, ignora os recebidos:

* **Caso de uso**: Quando os dados existentes são autoritativos
* **Comportamento**: Nenhuma atualização realizada
* **Risco**: Pode perder atualizações importantes

### manual\_review

Sinaliza conflitos sem resolução automática:

* **Caso de uso**: Dados de alto risco que requerem revisão humana
* **Comportamento**: Cria tarefa de revisão
* **Resultado**: Entidade marcada para resolução manual

## Exemplos

### Upsert Simples (Comportamento Padrão)

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT http://api.gu1.ai/entities/upsert \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "entity": {
        "type": "person",
        "externalId": "customer_12345",
        "name": "María González",
        "countryCode": "AR",
        "taxId": "20-12345678-9",
        "entityData": {
          "person": {
            "firstName": "María",
            "lastName": "González",
            "dateOfBirth": "1985-03-15",
            "occupation": "Software Engineer",
            "income": 85000
          }
        }
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('http://api.gu1.ai/entities/upsert', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      entity: {
        type: 'person',
        externalId: 'customer_12345',
        name: 'María González',
        countryCode: 'AR',
        taxId: '20-12345678-9',
        entityData: {
          person: {
            firstName: 'María',
            lastName: 'González',
            dateOfBirth: '1985-03-15',
            occupation: 'Software Engineer',
            income: 85000
          }
        }
      }
    })
  });

  const result = await response.json();
  console.log(`Action: ${result.action}`); // 'created' or 'updated'
  console.log(`Confidence: ${result.confidence}`);
  ```

  ```python Python theme={null}
  import requests

  response = requests.put(
      'http://api.gu1.ai/entities/upsert',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'entity': {
              'type': 'person',
              'externalId': 'customer_12345',
              'name': 'María González',
              'countryCode': 'AR',
              'taxId': '20-12345678-9',
              'entityData': {
                  'person': {
                      'firstName': 'María',
                      'lastName': 'González',
                      'dateOfBirth': '1985-03-15',
                      'occupation': 'Software Engineer',
                      'income': 85000
                  }
              }
          }
      }
  )

  result = response.json()
  print(f"Action: {result['action']}")
  print(f"Confidence: {result['confidence']}")
  ```
</CodeGroup>

### Upsert com Estratégia de Correspondência Exata

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT http://api.gu1.ai/entities/upsert \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "entity": {
        "type": "company",
        "externalId": "company_789",
        "name": "Tech Solutions S.A.",
        "countryCode": "BR",
        "taxId": "12.345.678/0001-90",
        "entityData": {
          "company": {
            "legalName": "Tech Solutions Sociedade Anônima",
            "revenue": 7500000
          }
        }
      },
      "options": {
        "deduplicationStrategy": "exact_match",
        "conflictResolution": "smart_merge"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('http://api.gu1.ai/entities/upsert', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      entity: {
        type: 'company',
        externalId: 'company_789',
        name: 'Tech Solutions S.A.',
        countryCode: 'BR',
        taxId: '12.345.678/0001-90',
        entityData: {
          company: {
            legalName: 'Tech Solutions Sociedade Anônima',
            revenue: 7500000
          }
        }
      },
      options: {
        deduplicationStrategy: 'exact_match',
        conflictResolution: 'smart_merge'
      }
    })
  });

  const result = await response.json();
  if (result.action === 'updated') {
    console.log('Found and updated existing company');
    console.log('Conflicts:', result.conflicts);
  }
  ```

  ```python Python theme={null}
  import requests

  response = requests.put(
      'http://api.gu1.ai/entities/upsert',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'entity': {
              'type': 'company',
              'externalId': 'company_789',
              'name': 'Tech Solutions S.A.',
              'countryCode': 'BR',
              'taxId': '12.345.678/0001-90',
              'entityData': {
                  'company': {
                      'legalName': 'Tech Solutions Sociedade Anônima',
                      'revenue': 7500000
                  }
              }
          },
          'options': {
              'deduplicationStrategy': 'exact_match',
              'conflictResolution': 'smart_merge'
          }
      }
  )

  result = response.json()
  if result['action'] == 'updated':
      print("Found and updated existing company")
      print(f"Conflicts: {result['conflicts']}")
  ```
</CodeGroup>

### Upsert com Correspondência Difusa

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT http://api.gu1.ai/entities/upsert \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "entity": {
        "type": "person",
        "externalId": "customer_new_123",
        "name": "Maria Gonzales",
        "countryCode": "AR",
        "taxId": "20-12345678-9",
        "entityData": {
          "person": {
            "firstName": "Maria",
            "lastName": "Gonzales"
          }
        }
      },
      "options": {
        "deduplicationStrategy": "fuzzy_match",
        "conflictResolution": "smart_merge"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  // Vai corresponder "Maria Gonzales" com "María González" existente
  // devido ao limiar de similaridade de 80%+

  const response = await fetch('http://api.gu1.ai/entities/upsert', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      entity: {
        type: 'person',
        externalId: 'customer_new_123',
        name: 'Maria Gonzales', // Leve variação na ortografia
        countryCode: 'AR',
        taxId: '20-12345678-9',
        entityData: {
          person: {
            firstName: 'Maria',
            lastName: 'Gonzales'
          }
        }
      },
      options: {
        deduplicationStrategy: 'fuzzy_match',
        conflictResolution: 'smart_merge'
      }
    })
  });

  const result = await response.json();
  console.log(`Matched with confidence: ${result.confidence}`);
  console.log(`Reasoning: ${result.reasoning}`);
  ```

  ```python Python theme={null}
  import requests

  # Vai corresponder "Maria Gonzales" com "María González" existente
  response = requests.put(
      'http://api.gu1.ai/entities/upsert',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'entity': {
              'type': 'person',
              'externalId': 'customer_new_123',
              'name': 'Maria Gonzales',  # Leve variação
              'countryCode': 'AR',
              'taxId': '20-12345678-9',
              'entityData': {
                  'person': {
                      'firstName': 'Maria',
                      'lastName': 'Gonzales'
                  }
              }
          },
          'options': {
              'deduplicationStrategy': 'fuzzy_match',
              'conflictResolution': 'smart_merge'
          }
      }
  )

  result = response.json()
  print(f"Matched with confidence: {result['confidence']}")
  print(f"Reasoning: {result['reasoning']}")
  ```
</CodeGroup>

### Estratégia Híbrida (Recomendada)

<CodeGroup>
  ```bash cURL theme={null}
  curl -X PUT http://api.gu1.ai/entities/upsert \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "entity": {
        "type": "company",
        "externalId": "comp_456",
        "name": "TechSolutions SA",
        "countryCode": "BR",
        "taxId": "12.345.678/0001-90",
        "entityData": {
          "company": {
            "employeeCount": 100
          }
        }
      },
      "options": {
        "deduplicationStrategy": "hybrid"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  // Tenta correspondência exata primeiro, fallback para difusa se necessário
  const response = await fetch('http://api.gu1.ai/entities/upsert', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      entity: {
        type: 'company',
        externalId: 'comp_456',
        name: 'TechSolutions SA', // Variação de "Tech Solutions S.A."
        countryCode: 'BR',
        taxId: '12.345.678/0001-90', // Correspondência exata no ID fiscal
        entityData: {
          company: {
            employeeCount: 100
          }
        }
      },
      options: {
        deduplicationStrategy: 'hybrid' // O melhor dos dois mundos
      }
    })
  });

  const result = await response.json();
  // Vai corresponder por taxId (exata) ou name (difusa)
  console.log(`Strategy used: ${result.reasoning}`);
  ```

  ```python Python theme={null}
  import requests

  # Híbrida: tenta correspondência exata primeiro, difusa como fallback
  response = requests.put(
      'http://api.gu1.ai/entities/upsert',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'entity': {
              'type': 'company',
              'externalId': 'comp_456',
              'name': 'TechSolutions SA',
              'countryCode': 'BR',
              'taxId': '12.345.678/0001-90',
              'entityData': {
                  'company': {
                      'employeeCount': 100
                  }
              }
          },
          'options': {
              'deduplicationStrategy': 'hybrid'
          }
      }
  )

  result = response.json()
  print(f"Strategy used: {result['reasoning']}")
  ```
</CodeGroup>

## Exemplos de Resposta

### Nova Entidade Criada

```json theme={null}
{
  "success": true,
  "action": "created",
  "entity": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "externalId": "customer_12345",
    "type": "person",
    "name": "María González",
    ...
  },
  "previousEntity": null,
  "confidence": 1.0,
  "reasoning": "No existing entity found matching criteria. Created new entity.",
  "conflicts": []
}
```

### Entidade Existente Atualizada

```json theme={null}
{
  "success": true,
  "action": "updated",
  "entity": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "externalId": "customer_12345",
    "type": "person",
    "name": "María González",
    "entityData": {
      "person": {
        "income": 95000
      }
    },
    ...
  },
  "previousEntity": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "entityData": {
      "person": {
        "income": 85000
      }
    },
    ...
  },
  "confidence": 1.0,
  "reasoning": "Exact match found on externalId. Updated existing entity with smart merge.",
  "conflicts": [
    {
      "field": "entityData.person.income",
      "oldValue": 85000,
      "newValue": 95000,
      "resolution": "source_wins"
    }
  ]
}
```

## Casos de Uso

### Importação de Dados de Sistema Externo

```javascript theme={null}
// Importar dados de clientes do CRM, evitando duplicatas
async function importCustomer(crmData) {
  const response = await fetch('http://api.gu1.ai/entities/upsert', {
    method: 'PUT',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      entity: {
        type: 'person',
        externalId: crmData.customerId,
        name: crmData.fullName,
        countryCode: crmData.country,
        taxId: crmData.taxId,
        entityData: {
          person: {
            firstName: crmData.firstName,
            lastName: crmData.lastName,
            income: crmData.annualIncome
          }
        },
        attributes: {
          source: 'crm_import',
          importDate: new Date().toISOString()
        }
      },
      options: {
        deduplicationStrategy: 'hybrid',
        conflictResolution: 'smart_merge'
      }
    })
  });

  return response.json();
}
```

### Enriquecimento Progressivo de Dados

```python theme={null}
def enrich_entity_data(external_id, new_data):
    """Adiciona progressivamente dados à entidade conforme ficam disponíveis"""
    response = requests.put(
        'http://api.gu1.ai/entities/upsert',
        headers={
            'Authorization': 'Bearer YOUR_API_KEY',
            'Content-Type': 'application/json'
        },
        json={
            'entity': {
                'type': 'person',
                'externalId': external_id,
                'name': new_data.get('name'),
                'countryCode': new_data.get('country'),
                'entityData': new_data.get('details', {}),
                'attributes': new_data.get('attributes', {})
            },
            'options': {
                'deduplicationStrategy': 'exact_match',
                'conflictResolution': 'smart_merge'  # Mescla novos com existentes
            }
        }
    )

    result = response.json()
    if result['action'] == 'updated':
        print(f"Enriched existing entity with new data")
    return result
```

## Melhores Práticas

1. **Escolha a Estratégia Certa**:
   * `exact_match` para dados limpos e estruturados com IDs confiáveis
   * `fuzzy_match` para dados digitados por usuários com potenciais erros
   * `hybrid` para a maioria dos cenários de produção

2. **Gerencie Conflitos com Cuidado**:
   * Use `smart_merge` para resolução automática
   * Use `manual_review` para dados financeiros críticos
   * Verifique o array `conflicts` na resposta para mudanças importantes

3. **Monitore as Pontuações de Confiança**:
   * Pontuações abaixo de 0.7 podem indicar correspondências fracas
   * Registre atualizações com baixa confiança para revisão
   * Considere limiar de revisão manual

4. **Gerenciamento de Relacionamentos**:
   * Defina `createRelationships: true` para vincular automaticamente entidades relacionadas
   * Útil para relacionamentos transação-cliente, empresa-pessoa

## Respostas de Erro

### 400 Bad Request

```json theme={null}
{
  "error": "Invalid tax ID format for country"
}
```

### 400 Campos Obrigatórios Ausentes

```json theme={null}
{
  "error": "Missing required fields",
  "missingFields": ["legalName"],
  "requiredFields": ["legalName", "industry"]
}
```

### 500 Internal Server Error

```json theme={null}
{
  "error": "Failed to upsert entity"
}
```

## Próximos Passos

* [Batch Upsert](/pt/api-reference/entities/upsert) - Processar múltiplas entidades de uma vez
* [List Entities](/api-reference/entities/list) - Consultar entidades com upsert
* [Update Entity](/api-reference/entities/update) - Fazer atualizações direcionadas
* [Get Entity](/api-reference/entities/get) - Recuperar detalhes completos da entidade
