Overview
Materializes relationships and related entities for an existing person or company using the latest row in normalized_enrichment. Typical use cases:
- Brazil — company: create/update the shareholder chain (QSA) from normalized data.
- Brazil — person: create/update related companies and related persons from normalized data.
The endpoint can optionally re-run enrichments on the root dossier first (runEnrichmentFirst, with runAllActiveIntegrationsOnRootFirst, rootIntegrationCodesBeforeMaterialize, or strategy defaults), then run the same style of shareholder/related-entity pipeline used in automatic creation.
The entity must be company or person. Other types return 400. The dossier country must have an automatic-creation strategy (today this flow is primarily used for Brazil; other countries may return 400 if defaults are missing or depth/providers are invalid).
Endpoint
POST http://api.gu1.ai/entities/{entityId}/relationships/materialize
Authentication
Requires a valid API key:
Authorization: Bearer YOUR_API_KEY
Path parameters
UUID of the root entity (person or company) whose relationships you want to materialize.
Request body
When true, the API re-executes enrichments on the root dossier entity before materializing. Which providers run is controlled by runAllActiveIntegrationsOnRootFirst, rootIntegrationCodesBeforeMaterialize, or (if both are off) the country strategy defaults for relationship discovery (e.g. Brazil: shareholders for companies; related companies + related persons for persons).When false, a normalized_enrichment row must already exist for the entity; otherwise the API returns 422 (NO_NORMALIZED_ENRICHMENT).
rootIntegrationCodesBeforeMaterialize
Explicit list of provider codes to run on the root entity when runEnrichmentFirst is true. Ignored if runAllActiveIntegrationsOnRootFirst is true. If omitted and runAllActiveIntegrationsOnRootFirst is false, defaults come from the country strategy.
runAllActiveIntegrationsOnRootFirst
When true (with runEnrichmentFirst: true), runs every active marketplace enrichment for the root entity’s type and country before materializing. Overrides rootIntegrationCodesBeforeMaterialize and strategy defaults for that pre-step. Higher cost/time. Requires runEnrichmentFirst.
Only applies when runEnrichmentFirst is true: prefer fresh provider data over cache when the integration allows it.
How many levels of shareholders or related entities to process. Allowed range 0–5 (schema default 1).
Per–child-type integrations to run when creating or enriching each child entity (company vs person), same idea as automatic creation:{
"company": ["br_bdc_shareholders_enrichment"],
"person": ["br_cpfcnpj_complete_person_enrichment"]
}
Keys company and person are arrays of provider enum codes. Optional.
relationshipChildrenFromSourceOnly
When true, each new child row is created from normalized data only (name + tax ID), without the strategy’s prerequisite “basic data” enrichment step. Applies to both dossier types in Brazil: companies (QSA shareholders) and persons (entries in normalized.relationships plus companies in normalized.shareholders where the person is an owner). If shareholderEnrichments lists are non-empty, those providers still run after the row exists (batch). Omit or set false to keep the default child-creation path (same as omitting this field).
When true (default), the API returns 202 immediately with data.status: "processing" and runs enrichment, materialization, and optional risk matrix on the server. Completion is signaled over Socket.IO (see below).When false, the server waits for the full pipeline and returns 200 with counts and flags in data.
Optional. After the pipeline finishes, run the rules / risk matrix on the root entity only.
execute (boolean, required when the object is sent): set true to run the matrix after materialization.
riskMatrixId (UUID | null, optional): null or omitted → use the matrix assigned to the entity; a UUID → run that matrix for this execution only (override, does not change the entity row).
"riskMatrix": { "execute": true, "riskMatrixId": null }
allActiveIntegrationsForChildEntities
When true, each discovered child entity (shareholder / related company / related person) is enriched using all active marketplace integrations for that child’s type (company vs person), instead of the explicit lists in shareholderEnrichments. When false or omitted, use shareholderEnrichments (and depth) as usual.
reEnrichExistingChildEntities
When true, if a discovered related entity already exists in your org, the pipeline re-runs configured enrichments for that child instead of skipping refresh. Applies to the shareholder / related-entity materialization pass.
Async behavior (default): HTTP 202 + Socket.IO
When runInBackground is true, the response is 202:
{
"success": true,
"data": {
"status": "processing",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"countryCode": "BR",
"entityType": "company"
}
}
Subscribe to your existing Socket.IO connection (same as the dashboard). Events:
| Event | When | Payload (high level) |
|---|
entity:relationship-materialize-started | Pipeline queued | entityId, mainEntityName, mainEntityTaxId, mainEntityType, userId |
entity:relationship-materialize-completed | Success or partial pipeline end | entityId, success, entitiesCreated, relationshipsCreated, enrichmentExecuted, enrichmentProviders, riskMatrixExecuted, optional error string |
entity:relationship-materialize-failed | Unhandled failure | entityId, error: { code, message, details? }, userId |
After completion, refetch the entity, relationships, and list endpoints as needed (e.g. GET /entities/:id, list queries).
Synchronous response (runInBackground: false): HTTP 200
{
"success": true,
"data": {
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"countryCode": "BR",
"entityType": "company",
"entitiesCreated": 3,
"relationshipsCreated": 5,
"enrichmentExecuted": true,
"enrichmentProviders": ["br_bdc_shareholders_enrichment"],
"riskMatrixExecuted": true
}
}
If the materialization step finishes with a pipeline warning (e.g. partial graph), success may be true while data.error carries a human-readable message—check both.
Example: Brazil company, async + risk matrix
curl -X POST "http://api.gu1.ai/entities/550e8400-e29b-41d4-a716-446655440000/relationships/materialize" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"runEnrichmentFirst": true,
"forceRefresh": false,
"depth": 2,
"shareholderEnrichments": {
"company": ["br_bdc_shareholders_enrichment"],
"person": ["br_cpfcnpj_complete_person_enrichment"]
},
"runInBackground": true,
"riskMatrix": { "execute": true, "riskMatrixId": null }
}'
Example: use a specific matrix once (override)
{
"runEnrichmentFirst": false,
"depth": 1,
"runInBackground": false,
"riskMatrix": {
"execute": true,
"riskMatrixId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
}
}
Error responses (selection)
| HTTP | Code (typical) | Meaning |
|---|
| 400 | INVALID_ENTITY_TYPE | Entity is not company or person |
| 400 | COUNTRY_NOT_SUPPORTED | No strategy / materialization not supported for this country |
| 400 | NO_ACTIVE_ENRICHMENTS | runAllActiveIntegrationsOnRootFirst with no active providers |
| 400 | NO_DEFAULT_RELATIONSHIP_ENRICHMENTS | Country has no default relationship codes; pass rootIntegrationCodesBeforeMaterialize or set runAllActiveIntegrationsOnRootFirst |
| 404 | ENTITY_NOT_FOUND | Unknown entityId for the organization |
| 422 | NO_NORMALIZED_ENRICHMENT | runEnrichmentFirst: false but no normalized row exists |
| 422 | INVALID_RELATIONSHIP_ENRICHMENT_CONFIG | Invalid shareholderEnrichments / depth for the strategy |
| 500 | ENRICHMENT_FAILED | Enrichment failed when runEnrichmentFirst is true (details in error payload) |
See also