Update an entity by external ID
curl --request PATCH \
--url http://api.gu1.ai/entities/by-external-id/:externalId \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"taxId": "<string>",
"email": {},
"phone": {},
"nationality": {},
"status": "<string>",
"reason": "<string>",
"changeStatusManual": true,
"riskMatrixId": [
"<string>"
],
"riskMatrixIds": [
"<string>"
],
"entityData": {},
"attributes": {},
"metadata": {}
}
'import requests
url = "http://api.gu1.ai/entities/by-external-id/:externalId"
payload = {
"name": "<string>",
"taxId": "<string>",
"email": {},
"phone": {},
"nationality": {},
"status": "<string>",
"reason": "<string>",
"changeStatusManual": True,
"riskMatrixId": ["<string>"],
"riskMatrixIds": ["<string>"],
"entityData": {},
"attributes": {},
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
taxId: '<string>',
email: {},
phone: {},
nationality: {},
status: '<string>',
reason: '<string>',
changeStatusManual: true,
riskMatrixId: ['<string>'],
riskMatrixIds: ['<string>'],
entityData: {},
attributes: {},
metadata: {}
})
};
fetch('http://api.gu1.ai/entities/by-external-id/:externalId', 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/by-external-id/:externalId",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'taxId' => '<string>',
'email' => [
],
'phone' => [
],
'nationality' => [
],
'status' => '<string>',
'reason' => '<string>',
'changeStatusManual' => true,
'riskMatrixId' => [
'<string>'
],
'riskMatrixIds' => [
'<string>'
],
'entityData' => [
],
'attributes' => [
],
'metadata' => [
]
]),
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/by-external-id/:externalId"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"taxId\": \"<string>\",\n \"email\": {},\n \"phone\": {},\n \"nationality\": {},\n \"status\": \"<string>\",\n \"reason\": \"<string>\",\n \"changeStatusManual\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"entityData\": {},\n \"attributes\": {},\n \"metadata\": {}\n}")
req, _ := http.NewRequest("PATCH", 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.patch("http://api.gu1.ai/entities/by-external-id/:externalId")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"taxId\": \"<string>\",\n \"email\": {},\n \"phone\": {},\n \"nationality\": {},\n \"status\": \"<string>\",\n \"reason\": \"<string>\",\n \"changeStatusManual\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"entityData\": {},\n \"attributes\": {},\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://api.gu1.ai/entities/by-external-id/:externalId")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"taxId\": \"<string>\",\n \"email\": {},\n \"phone\": {},\n \"nationality\": {},\n \"status\": \"<string>\",\n \"reason\": \"<string>\",\n \"changeStatusManual\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"entityData\": {},\n \"attributes\": {},\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"entity": {},
"evaluation": {},
"previousEntity": {},
"404 Not Found": {},
"400 Bad Request": {}
}Update an entity by external ID
Update any gu1 entity by passing your external identifier in place of the internal UUID, covering companies, persons, and transactions in one call.
PATCH
/
entities
/
by-external-id
/
:externalId
Update an entity by external ID
curl --request PATCH \
--url http://api.gu1.ai/entities/by-external-id/:externalId \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"taxId": "<string>",
"email": {},
"phone": {},
"nationality": {},
"status": "<string>",
"reason": "<string>",
"changeStatusManual": true,
"riskMatrixId": [
"<string>"
],
"riskMatrixIds": [
"<string>"
],
"entityData": {},
"attributes": {},
"metadata": {}
}
'import requests
url = "http://api.gu1.ai/entities/by-external-id/:externalId"
payload = {
"name": "<string>",
"taxId": "<string>",
"email": {},
"phone": {},
"nationality": {},
"status": "<string>",
"reason": "<string>",
"changeStatusManual": True,
"riskMatrixId": ["<string>"],
"riskMatrixIds": ["<string>"],
"entityData": {},
"attributes": {},
"metadata": {}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
taxId: '<string>',
email: {},
phone: {},
nationality: {},
status: '<string>',
reason: '<string>',
changeStatusManual: true,
riskMatrixId: ['<string>'],
riskMatrixIds: ['<string>'],
entityData: {},
attributes: {},
metadata: {}
})
};
fetch('http://api.gu1.ai/entities/by-external-id/:externalId', 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/by-external-id/:externalId",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'taxId' => '<string>',
'email' => [
],
'phone' => [
],
'nationality' => [
],
'status' => '<string>',
'reason' => '<string>',
'changeStatusManual' => true,
'riskMatrixId' => [
'<string>'
],
'riskMatrixIds' => [
'<string>'
],
'entityData' => [
],
'attributes' => [
],
'metadata' => [
]
]),
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/by-external-id/:externalId"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"taxId\": \"<string>\",\n \"email\": {},\n \"phone\": {},\n \"nationality\": {},\n \"status\": \"<string>\",\n \"reason\": \"<string>\",\n \"changeStatusManual\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"entityData\": {},\n \"attributes\": {},\n \"metadata\": {}\n}")
req, _ := http.NewRequest("PATCH", 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.patch("http://api.gu1.ai/entities/by-external-id/:externalId")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"taxId\": \"<string>\",\n \"email\": {},\n \"phone\": {},\n \"nationality\": {},\n \"status\": \"<string>\",\n \"reason\": \"<string>\",\n \"changeStatusManual\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"entityData\": {},\n \"attributes\": {},\n \"metadata\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://api.gu1.ai/entities/by-external-id/:externalId")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"taxId\": \"<string>\",\n \"email\": {},\n \"phone\": {},\n \"nationality\": {},\n \"status\": \"<string>\",\n \"reason\": \"<string>\",\n \"changeStatusManual\": true,\n \"riskMatrixId\": [\n \"<string>\"\n ],\n \"riskMatrixIds\": [\n \"<string>\"\n ],\n \"entityData\": {},\n \"attributes\": {},\n \"metadata\": {}\n}"
response = http.request(request)
puts response.read_body{
"entity": {},
"evaluation": {},
"previousEntity": {},
"404 Not Found": {},
"400 Bad Request": {}
}Overview
This endpoint allows you to update an entity using your own external identifier instead of our internal UUID. This is useful when you donβt store our UUIDs in your system and only track your own external IDs. The functionality is identical toPATCH /entities/:id, but uses externalId as the identifier.
You cannot change the entityβs external ID through this
PATCH body (or any entity PATCH). Use Change external ID instead.Path Parameters
string
required
Your unique external identifier for the entity
Request Body
string
Entity name (person full name or company name)
string
Tax identification number (SSN, EIN, VAT, RFC, etc.)
string | null
Root-level contact email. Omit to leave unchanged; send
null to clear.string | null
Root-level contact phone. Omit to leave unchanged; send
null to clear.string | null
Root-level nationality (ISO 3166-1 alpha-2 when persisted). Omit to leave unchanged; send
null to clear. Updating nationality inside entityData in the same request may recalculate the root field.string
Entity status. Canonical values (see Entities overview):
not_started,under_review,pending_verification,awaiting_information,active,inactive,suspended,blocked,rejected,expired,deleted
reason for audit. Operations are blocked for blocked, suspended, and rejected.string
Required when changing status to
blocked, suspended, or rejected. Provides audit trail for the status change.boolean
default:"false"
Same semantics as Update entity by ID. When
true, risk matrix rules and automations cannot change status.string | string[] | null
Legacy: one UUID, an array of UUIDs, or
null to clear all assigned matrices. When riskMatrixIds is sent non-empty, it takes precedence. See Update entity by ID β Risk matrices.string[]
Preferred for multiple matrices: ordered list of UUIDs belonging to your organization. Send
[] to remove all assignments.object
Entity-specific data structure. For person entities, use
entityData.person. For company entities, use entityData.company.Person fields:firstName: First namelastName: Last namemiddleName: Middle namedateOfBirth: Date of birth (YYYY-MM-DD)nationality: Nationality (ISO 3166-1 alpha-2)email: Email addressphone: Phone numberaddress: Address object (street, city, state, country, postalCode)
legalName: Legal company nametradingNames: Array of trading namesregistrationNumber: Company registration numberincorporationDate: Date of incorporation (YYYY-MM-DD)industry: Industry/sectoremployees: Number of employeeswebsite: Company websiteaddress: Address object
object
Custom key-value attributes for flexible entity data storage
object
System metadata (usually set by the system, but can be updated)
Immutable Fields
The following fields cannot be changed after entity creation:type: Entity type (person or company)countryCode: Entity country code (ISO 3166-1 alpha-2)
Response
Returns the updated entity object.object
The updated entity object with all current values
object | null
Evaluation object (currently null - re-evaluation feature temporarily disabled)
object
The entity state before the update (for audit purposes)
Example Request
curl -X PATCH https://api.gueno.ai/entities/by-external-id/customer-12345 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "John Michael Doe",
"status": "active",
"entityData": {
"person": {
"firstName": "John",
"middleName": "Michael",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+1-555-0123"
}
},
"riskMatrixIds": ["onboarding-matrix-uuid", "post-kyc-matrix-uuid"]
}'
Example Response
{
"entity": {
"id": "entity-uuid",
"organizationId": "org-uuid",
"externalId": "customer-12345",
"type": "person",
"name": "John Michael Doe",
"taxId": "123-45-6789",
"countryCode": "US",
"nationality": "US",
"status": "active",
"riskScore": "35.00",
"riskMatrixIds": ["onboarding-matrix-uuid", "post-kyc-matrix-uuid"],
"entityData": {
"person": {
"firstName": "John",
"middleName": "Michael",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+1-555-0123"
}
},
"createdAt": "2025-12-20T10:00:00Z",
"updatedAt": "2025-12-24T15:30:00Z"
},
"evaluation": null,
"previousEntity": {
"id": "entity-uuid",
"name": "John Doe",
"status": "pending",
...
}
}
Status Change with Reason
When changing status toblocked, suspended, or rejected, you must provide a reason:
curl -X PATCH https://api.gueno.ai/entities/by-external-id/customer-12345 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"status": "blocked",
"reason": "Failed sanctions screening - OFAC match detected"
}'
Use Cases
1. Update Customer Information
Update customer data from your CRM or user management system:{
"name": "Jane Smith-Johnson",
"entityData": {
"person": {
"lastName": "Smith-Johnson",
"email": "jane.smithjohnson@example.com",
"address": {
"street": "456 New St",
"city": "Seattle",
"state": "WA",
"country": "US",
"postalCode": "98101"
}
}
}
}
2. Assign Risk Matrix
Assign or change the risk matrix for an entity:{
"riskMatrixIds": ["high-risk-matrix-uuid"]
}
POST /entities/:entityId/analyze to re-evaluate the entity with the new rules.
3. Block Entity After Investigation
Block an entity after compliance investigation:{
"status": "blocked",
"reason": "Investigation revealed connections to sanctioned entities"
}
4. Sync Company Data
Update company information from business registry:{
"entityData": {
"company": {
"employees": 250,
"revenue": 50000000,
"website": "https://company-new-domain.com"
}
}
}
Events and Webhooks
Real-time Events
After a successful update, the following real-time event is emitted via WebSocket:{
"event": "entity.updated",
"entityId": "entity-uuid",
"externalId": "customer-12345",
"updatedFields": ["name", "entityData"],
"previousValues": {...},
"newValues": {...}
}
Webhook Triggers
If you change only thestatus field (without other field changes), a webhook is triggered:
Event: entity.status_changed
{
"event": "entity.status_changed",
"entityId": "entity-uuid",
"externalId": "customer-12345",
"oldStatus": "active",
"newStatus": "blocked",
"reason": "Failed sanctions screening",
"changedBy": "user-uuid",
"timestamp": "2025-12-24T15:30:00Z"
}
Audit Trail
Every entity update creates anATTRIBUTE_CHANGED event in the entity events log with:
- Before state (all changed fields)
- After state (all changed fields)
- User who made the change
- Timestamp
- Source (API, dashboard, etc.)
GET /entity-events?entityId=:entityId&eventType=ATTRIBUTE_CHANGED
Error Responses
error
Entity with the specified
externalId not found in your organization{
"error": "Entity not found"
}
error
Invalid request data or validation error
{
"error": "Changing status to 'blocked' requires a reason for audit purposes."
}
error
Attempting to change immutable fields
{
"error": "Field 'type' cannot be changed after entity creation"
}
Best Practices
-
Always Set External ID on Creation: Set
externalIdwhen creating entities viaPOST /entitiesto enable updates by external ID. - Use for System Integration: This endpoint is ideal for integrations where you sync data from external systems (CRM, ERP, etc.) using your own IDs.
- Provide Reasons for Status Changes: Always include meaningful reasons when blocking, suspending, or rejecting entities for compliance audit trail.
-
Re-analyze After Risk Matrix Change: After assigning a new risk matrix, trigger
POST /entities/:entityId/analyzeto re-evaluate with new rules. -
Handle 404 Gracefully: If entity not found by external ID, you may need to create it first using
POST /entities. - Batch Updates: For updating multiple entities, call this endpoint concurrently with different external IDs for better performance.
Related Endpoints
- Create Entity - Create new entity
- Update Entity by UUID - Update using internal UUID
- Get Entity - Retrieve entity details
- Analyze Entity - Trigger risk analysis
Was this page helpful?