> ## 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 una entidad empresa

> Crea o actualiza una empresa en gu1 con detección de duplicados que verifica ID externo, identificación fiscal y razón social para evitar colisiones.

## Descripción general

El endpoint upsert crea inteligentemente una nueva empresa o actualiza una existente basándose en estrategias de detección de duplicados configurables. Maneja automáticamente conflictos y previene registros duplicados usando coincidencia exacta, coincidencia difusa o detección de similitud impulsada por IA.

## Endpoint

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

## Autenticación

Requiere una clave API válida en el encabezado Authorization:

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

## Cuerpo de la solicitud

<ParamField body="entity" type="object" required>
  Los datos de la empresa (misma estructura que el endpoint Crear empresa)
</ParamField>

<ParamField body="options" type="object">
  Opciones de configuración para el comportamiento del upsert
</ParamField>

<ParamField body="options.conflictResolution" type="enum">
  Cómo manejar conflictos cuando se encuentra una empresa existente:

  * `source_wins` - Los nuevos datos sobrescriben los datos existentes
  * `target_wins` - Mantener datos existentes, ignorar nuevos datos
  * `manual_review` - Marcar para revisión manual sin actualizar
  * `smart_merge` (predeterminado) - Fusionar inteligentemente ambos conjuntos de datos
</ParamField>

<ParamField body="options.deduplicationStrategy" type="enum">
  Estrategia para detectar empresas duplicadas:

  * `exact_match` - Coincidencia por externalId y taxId (insensible a mayúsculas)
  * `fuzzy_match` - Coincidencia de similitud en nombre y taxId (umbral del 80%)
  * `ai_similarity` - Detección de similitud semántica impulsada por IA
  * `hybrid` (recomendado) - Coincidencia exacta con respaldo difuso
</ParamField>

<ParamField body="options.createRelationships" type="boolean" default="true">
  Si crear automáticamente relaciones entre entidades
</ParamField>

## Respuesta

<ResponseField name="success" type="boolean">
  Indica si la operación tuvo éxito
</ResponseField>

<ResponseField name="action" type="string">
  La acción realizada: `created` o `updated`
</ResponseField>

<ResponseField name="entity" type="object">
  El estado final de la empresa después del upsert
</ResponseField>

<ResponseField name="previousEntity" type="object">
  El estado de la empresa antes de la actualización (null si se creó recientemente)
</ResponseField>

<ResponseField name="confidence" type="number">
  Puntuación de confianza (0-1) para la coincidencia de detección de duplicados
</ResponseField>

<ResponseField name="reasoning" type="string">
  Explicación de por qué se creó/actualizó la empresa
</ResponseField>

<ResponseField name="conflicts" type="array">
  Array de conflictos a nivel de campo detectados durante la fusión (si los hay)
</ResponseField>

## Ejemplos

### Upsert simple (comportamiento predeterminado)

<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": "business_12345",
        "name": "María González",
        "countryCode": "AR",
        "taxId": "20-12345678-9",
        "entityData": {
          "company": {
            "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: 'company',
        externalId: 'business_12345',
        name: 'María González',
        countryCode: 'AR',
        taxId: '20-12345678-9',
        entityData: {
          company: {
            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' o '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': 'company',
              'externalId': 'business_12345',
              'name': 'María González',
              'countryCode': 'AR',
              'taxId': '20-12345678-9',
              'entityData': {
                  'company': {
                      '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 con coincidencia 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": "company",
        "externalId": "business_new_123",
        "name": "Maria Gonzales",
        "countryCode": "AR",
        "taxId": "20-12345678-9",
        "entityData": {
          "company": {
            "firstName": "Maria",
            "lastName": "Gonzales"
          }
        }
      },
      "options": {
        "deduplicationStrategy": "fuzzy_match",
        "conflictResolution": "smart_merge"
      }
    }'
  ```

  ```javascript JavaScript theme={null}
  // Coincidirá "Maria Gonzales" con "María González" existente
  // debido al umbral de similitud del 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: 'company',
        externalId: 'business_new_123',
        name: 'Maria Gonzales', // Ligera variación en la ortografía
        countryCode: 'AR',
        taxId: '20-12345678-9',
        entityData: {
          company: {
            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

  # Coincidirá "Maria Gonzales" con "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': 'company',
              'externalId': 'business_new_123',
              'name': 'Maria Gonzales',  # Ligera variación
              'countryCode': 'AR',
              'taxId': '20-12345678-9',
              'entityData': {
                  'company': {
                      '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>

## Ejemplos de respuesta

### Empresa nueva creada

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

### Empresa existente actualizada

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

## Casos de uso

### Importación de datos desde CRM

```javascript theme={null}
// Importar datos de negocio desde CRM, evitando duplicados
async function importBusiness(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: 'company',
        externalId: crmData.businessId,
        name: crmData.fullName,
        countryCode: crmData.country,
        taxId: crmData.taxId,
        entityData: {
          company: {
            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();
}
```

### Enriquecimiento progresivo de datos

```python theme={null}
def enrich_company_data(external_id, new_data):
    """Agregar progresivamente datos a la empresa a medida que estén disponibles"""
    response = requests.put(
        'http://api.gu1.ai/entities/upsert',
        headers={
            'Authorization': 'Bearer YOUR_API_KEY',
            'Content-Type': 'application/json'
        },
        json={
            'entity': {
                'type': 'company',
                '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'  # Fusionar nuevo con existente
            }
        }
    )

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

## Mejores prácticas

1. **Elige la estrategia correcta**:
   * `exact_match` para datos limpios y estructurados con IDs confiables
   * `fuzzy_match` para datos ingresados por usuarios con posibles errores tipográficos
   * `hybrid` para la mayoría de los escenarios de producción

2. **Maneja conflictos con elegancia**:
   * Usa `smart_merge` para resolución automática
   * Usa `manual_review` para datos críticos
   * Verifica el array `conflicts` en la respuesta para cambios importantes

3. **Monitorea puntuaciones de confianza**:
   * Las puntuaciones por debajo de 0.7 pueden indicar coincidencias débiles
   * Registra las actualizaciones de baja confianza para revisión

## Respuestas de error

### 400 Bad Request

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

### 500 Internal Server Error

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

## Próximos pasos

* [Listar empresas](/es/api-reference/company/list) - Consultar empresas upserted
* [Actualizar empresa](/es/api-reference/company/update) - Realizar actualizaciones específicas
* [Obtener empresa](/es/api-reference/company/get) - Recuperar detalles completos de la empresa
