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
}
'import requests
url = "http://api.gu1.ai/entities/upsert"
payload = {
"entity": {},
"options": {},
"options.conflictResolution": {},
"options.deduplicationStrategy": {},
"options.createRelationships": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
entity: {},
options: {},
'options.conflictResolution': {},
'options.deduplicationStrategy': {},
'options.createRelationships': true
})
};
fetch('http://api.gu1.ai/entities/upsert', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "http://api.gu1.ai/entities/upsert",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'entity' => [
],
'options' => [
],
'options.conflictResolution' => [
],
'options.deduplicationStrategy' => [
],
'options.createRelationships' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://api.gu1.ai/entities/upsert"
payload := strings.NewReader("{\n \"entity\": {},\n \"options\": {},\n \"options.conflictResolution\": {},\n \"options.deduplicationStrategy\": {},\n \"options.createRelationships\": true\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("http://api.gu1.ai/entities/upsert")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"entity\": {},\n \"options\": {},\n \"options.conflictResolution\": {},\n \"options.deduplicationStrategy\": {},\n \"options.createRelationships\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://api.gu1.ai/entities/upsert")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"entity\": {},\n \"options\": {},\n \"options.conflictResolution\": {},\n \"options.deduplicationStrategy\": {},\n \"options.createRelationships\": true\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"action": "<string>",
"entity": {},
"previousEntity": {},
"confidence": 123,
"reasoning": "<string>",
"conflicts": [
{}
]
}Referencia API
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.
PUT
/
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
}
'import requests
url = "http://api.gu1.ai/entities/upsert"
payload = {
"entity": {},
"options": {},
"options.conflictResolution": {},
"options.deduplicationStrategy": {},
"options.createRelationships": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
entity: {},
options: {},
'options.conflictResolution': {},
'options.deduplicationStrategy': {},
'options.createRelationships': true
})
};
fetch('http://api.gu1.ai/entities/upsert', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "http://api.gu1.ai/entities/upsert",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'entity' => [
],
'options' => [
],
'options.conflictResolution' => [
],
'options.deduplicationStrategy' => [
],
'options.createRelationships' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "http://api.gu1.ai/entities/upsert"
payload := strings.NewReader("{\n \"entity\": {},\n \"options\": {},\n \"options.conflictResolution\": {},\n \"options.deduplicationStrategy\": {},\n \"options.createRelationships\": true\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("http://api.gu1.ai/entities/upsert")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"entity\": {},\n \"options\": {},\n \"options.conflictResolution\": {},\n \"options.deduplicationStrategy\": {},\n \"options.createRelationships\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://api.gu1.ai/entities/upsert")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"entity\": {},\n \"options\": {},\n \"options.conflictResolution\": {},\n \"options.deduplicationStrategy\": {},\n \"options.createRelationships\": true\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"action": "<string>",
"entity": {},
"previousEntity": {},
"confidence": 123,
"reasoning": "<string>",
"conflicts": [
{}
]
}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:Authorization: Bearer YOUR_API_KEY
Cuerpo de la solicitud
object
required
Los datos de la empresa (misma estructura que el endpoint Crear empresa)
object
Opciones de configuración para el comportamiento del upsert
enum
Cómo manejar conflictos cuando se encuentra una empresa existente:
source_wins- Los nuevos datos sobrescriben los datos existentestarget_wins- Mantener datos existentes, ignorar nuevos datosmanual_review- Marcar para revisión manual sin actualizarsmart_merge(predeterminado) - Fusionar inteligentemente ambos conjuntos de datos
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 IAhybrid(recomendado) - Coincidencia exacta con respaldo difuso
boolean
default:"true"
Si crear automáticamente relaciones entre entidades
Respuesta
boolean
Indica si la operación tuvo éxito
string
La acción realizada:
created o updatedobject
El estado final de la empresa después del upsert
object
El estado de la empresa antes de la actualización (null si se creó recientemente)
number
Puntuación de confianza (0-1) para la coincidencia de detección de duplicados
string
Explicación de por qué se creó/actualizó la empresa
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": "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 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}`);
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']}")
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": "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"
}
}'
// 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}`);
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']}")
Ejemplos de respuesta
Empresa nueva creada
{
"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
{
"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
// 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
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
-
Elige la estrategia correcta:
exact_matchpara datos limpios y estructurados con IDs confiablesfuzzy_matchpara datos ingresados por usuarios con posibles errores tipográficoshybridpara la mayoría de los escenarios de producción
-
Maneja conflictos con elegancia:
- Usa
smart_mergepara resolución automática - Usa
manual_reviewpara datos críticos - Verifica el array
conflictsen la respuesta para cambios importantes
- Usa
-
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
{
"error": "Invalid tax ID format for country"
}
500 Internal Server Error
{
"error": "Failed to upsert entity"
}
Próximos pasos
- Listar empresas - Consultar empresas upserted
- Actualizar empresa - Realizar actualizaciones específicas
- Obtener empresa - Recuperar detalles completos de la empresa
Was this page helpful?