Skip to main content
PUT
http://api.gu1.ai
/
entities
/
upsert
Upsert
curl --request PUT \
  --url http://api.gu1.ai/entities/upsert \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "entity": {},
  "options": {},
  "options.conflictResolution": {},
  "options.deduplicationStrategy": {},
  "options.createRelationships": true
}
'
{
  "success": true,
  "action": "<string>",
  "entity": {},
  "previousEntity": {},
  "confidence": 123,
  "reasoning": "<string>",
  "conflicts": [
    {}
  ]
}

Resumen

El endpoint de upsert crea inteligentemente una nueva persona o actualiza una existente según estrategias configurables de detección de duplicados. 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:
Authorization: Bearer YOUR_API_KEY

Cuerpo de la Solicitud

entity
object
required
Los datos de la persona (misma estructura que el endpoint Crear Persona)
options
object
Opciones de configuración para el comportamiento de upsert
options.conflictResolution
enum
Cómo manejar conflictos cuando se encuentra una persona 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
options.deduplicationStrategy
enum
Estrategia para detectar personas duplicadas:
  • exact_match - Coincidir 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
options.createRelationships
boolean
default:"true"
Si se deben crear relaciones automáticamente entre entidades

Respuesta

success
boolean
Indica si la operación tuvo éxito
action
string
La acción realizada: created o updated
entity
object
El estado final de la persona después del upsert
previousEntity
object
El estado de la persona antes de la actualización (null si fue recién creada)
confidence
number
Puntuación de confianza (0-1) para la coincidencia de detección de duplicados
reasoning
string
Explicación de por qué la persona fue creada/actualizada
conflicts
array
Array de conflictos a nivel de campo detectados durante la fusión (si los hay)

Ejemplos

Upsert Simple (Comportamiento Predeterminado)

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
        }
      }
    }
  }'

Upsert con Coincidencia Difusa

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"
    }
  }'

Ejemplos de Respuesta

Persona Creada Nueva

{
  "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": []
}

Persona Existente Actualizada

{
  "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

Importación de Datos desde CRM

// Importar datos de clientes desde CRM, evitando duplicados
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();
}

Enriquecimiento Progresivo de Datos

def enrich_person_data(external_id, new_data):
    """Agregar progresivamente datos a la persona 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': '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'  # Fusionar nuevos con existentes
            }
        }
    )

    result = response.json()
    if result['action'] == 'updated':
        print(f"Enriched existing person 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 escenarios de producción
  2. Manejar Conflictos con Gracia:
    • Usar smart_merge para resolución automática
    • Usar manual_review para datos críticos
    • Verificar el array conflicts en la respuesta para cambios importantes
  3. Monitorear Puntuaciones de Confianza:
    • Puntuaciones por debajo de 0.7 pueden indicar coincidencias débiles
    • Registrar actualizaciones de baja confianza para revisión

Respuestas de Error

400 Bad Request

{
  "error": "Invalid tax ID format for country"
}

500 Internal Server Error

{
  "error": "Failed to upsert entity"
}

Próximos Pasos