Back to all resources
ContX IQ ContX IQ Json

ContX IQ: With User node as a subject, upsert a metadata attribute.

This use case explains how to upsert a metadata attribute.

ContX IQ: With User node as a subject, upsert a metadata attribute.

Link a user access token with existing captured data and use this authorization to upsert metadata within the scope of a policy with a user as subject.

Use case

In this case, a user access token is sent and introspected then a new property with metadata is added to an existing node and metadata is added to an existing property.

Then, we retrieve data according to the value of one of the metadata added.

ikg

Requirements

- ServiceAccount credentials created in the IndyKite Hub for your organization.

- AppAgent credentials created in the IndyKite Hub, using the REST endpoints or using Terraform for your Project / Application.

- Access token for a Person node

User Access token is sent in CIQ Execution in Headers: key:Authorization, value:Bearer token.

Steps

1. Using the AppAgent credential as API Key (name: X-IK-ClientKey), ingest data in your IKG (IndyKite Knowledge Graph) using the script provided.

2. Using the ServiceAccount credential as Bearer token, create a CIQ Policy which designates the Subject node, the cypher, the nodes allowed to be upserted and the nodes allowed to be read.

3. Using the ServiceAccount credential as Bearer token, create a CIQ Query in the context of the policy to retrieve and upsert a new property with metadata and an existing property with metadata on a node.

4. Using the AppAgent credential as API Key (name: X-IK-ClientKey), run a CIQ Execution to get the newly created property information.

5. Using the ServiceAccount credential as Bearer token, create a CIQ Query in the context of the policy to retrieve property information according to a filter on one of the newly created metadata.

6. Using the AppAgent credential as API Key (name: X-IK-ClientKey), run a CIQ Execution to read the data.

Step 1

Ingest the nodes needed for this use case.

POST https://eu.api.indykite.com/capture/v1/nodes/Json
{
  "nodes": [
    {
      "external_id": "alice",
      "type": "Person",
      "is_identity": true,
      "properties": [
        {
          "type": "email",
          "value": "alice@email.com"
        },
        {
          "type": "name",
          "value": "Alice Smith"
        }
      ]
    },
    {
      "external_id": "satchmo",
      "type": "Person",
      "is_identity": true,
      "properties": [
        {
          "type": "email",
          "value": "satchmo@demo.com"
        },
        {
          "type": "name",
          "value": "Louis Armstrong"
        }
      ]
    },
    {
      "external_id": "karel",
      "type": "Person",
      "is_identity": true,
      "properties": [
        {
          "type": "email",
          "value": "karel@demo.com"
        },
        {
          "type": "name",
          "value": "Karel Plihal"
        }
      ]
    },
    {
      "external_id": "kitt",
      "type": "Car",
      "is_identity": false,
      "properties": [
        {
          "type": "manufacturer",
          "value": "pontiac"
        },
        {
          "type": "model",
          "value": "Firebird"
        }
      ]
    },
    {
      "external_id": "caddilacv16",
      "type": "Car",
      "is_identity": false,
      "properties": [
        {
          "type": "manufacturer",
          "value": "Caddilac"
        },
        {
          "type": "model",
          "value": "V-16"
        }
      ]
    },
    {
      "external_id": "harmonika",
      "type": "Bus",
      "is_identity": false,
      "properties": [
        {
          "type": "manufacturer",
          "value": "Ikarus"
        },
        {
          "type": "model",
          "value": "280"
        }
      ]
    },
    {
      "external_id": "ln-xxx",
      "type": "LicenseNumber",
      "is_identity": false,
      "properties": [
        {
          "type": "license",
          "value": "ln-xxx-value"
        }
      ]
    },
    {
      "external_id": "ln-yyy",
      "type": "LicenseNumber",
      "is_identity": false,
      "properties": [
        {
          "type": "license",
          "value": "ln-yyy-value"
        }
      ]
    },
    {
      "external_id": "ln-zzz",
      "type": "LicenseNumber",
      "is_identity": false,
      "properties": [
        {
          "type": "license",
          "value": "ln-zzz-value"
        }
      ]
    }
  ]
}

Ingest the relationships needed for this use case.

POST https://eu.api.indykite.com/capture/v1/relationships/Json
{
  "relationships": [
    {
      "source": {
        "external_id": "alice",
        "type": "Person"
      },
      "target": {
        "external_id": "kitt",
        "type": "Car"
      },
      "type": "OWNS",
      "properties": [
        {
          "type": "weight",
          "value": 1
        }
      ]
    },
    {
      "source": {
        "external_id": "alice",
        "type": "Person"
      },
      "target": {
        "external_id": "caddilacv16",
        "type": "Car"
      },
      "type": "OWNS",
      "properties": [
        {
          "type": "weight",
          "value": 2
        }
      ]
    },
    {
      "source": {
        "external_id": "satchmo",
        "type": "Person"
      },
      "target": {
        "external_id": "caddilacv16",
        "type": "Car"
      },
      "type": "OWNS"
    },
    {
      "source": {
        "external_id": "karel",
        "type": "Person"
      },
      "target": {
        "external_id": "harmonika",
        "type": "Bus"
      },
      "type": "OWNS"
    },
    {
      "source": {
        "external_id": "kitt",
        "type": "Car"
      },
      "target": {
        "external_id": "ln-xxx",
        "type": "LicenseNumber"
      },
      "type": "HAS",
      "properties": [
        {
          "type": "weight",
          "value": 3
        }
      ]
    },
    {
      "source": {
        "external_id": "caddilacv16",
        "type": "Car"
      },
      "target": {
        "external_id": "ln-zzz",
        "type": "LicenseNumber"
      },
      "type": "HAS"
    },
    {
      "source": {
        "external_id": "harmonika",
        "type": "Bus"
      },
      "target": {
        "external_id": "ln-yyy",
        "type": "LicenseNumber"
      },
      "type": "HAS"
    }
  ]
}

Step 2

Create a CIQ Policy which designates the Subject node, the cypher, the nodes allowed to be upserted and the nodes allowed to be read.

policy.jsonJson
{
  "meta": {
    "policy_version": "1.0-ciq"
  },
  "subject": {
    "type": "Person"
  },
  "condition": {
    "cypher": "MATCH (subject:Person)-[:OWNS]->(car:Car)-[:HAS]->(ln:LicenseNumber)",
    "filter": [
      {
        "operator": "AND",
        "operands": [
          {
            "attribute": "subject.external_id",
            "operator": "=",
            "value": "$subject_external_id"
          },
          {
            "attribute": "$token.sub",
            "operator": "=",
            "value": "$token_sub"
          }
        ]
      }
    ]
  },
  "allowed_reads": {
    "nodes": [
      "car",
      "ln",
      "car.*",
      "ln.*"
    ]
  },
  "allowed_upserts": {
    "nodes": {
      "existing_nodes": [
        "ln"
      ]
    }
  }
}

Request to create the CIQ Policy configuration using REST.

POST https://eu.api.indykite.com/configs/v1/authorization-policiesJson
{
  "project_id": "your_project_gid",
  "description": "description of policy",
  "display_name": "policy name",
  "name": "policy-name",
  "policy": "{\"meta\":{\"policy_version\":\"1.0-ciq\"},\"subject\":{\"type\":\"Person\"},\"condition\":{\"cypher\":\"MATCH (subject:Person)-[:OWNS]->(car:Car)-[:HAS]->(ln:LicenseNumber)\",\"filter\":[{\"operator\":\"AND\",\"operands\":[{\"attribute\":\"subject.external_id\",\"operator\":\"=\",\"value\":\"$subject_external_id\"},{\"attribute\":\"$token.sub\",\"operator\":\"=\",\"value\":\"$token_sub\"}]}]},\"allowed_reads\":{\"nodes\":[\"car\",\"ln\",\"car.*\",\"ln.*\"]},\"allowed_upserts\":{\"nodes\":{\"existing_nodes\":[\"ln\"]}}}",
  "status": "ACTIVE",
  "tags": []
}

Request to read the CIQ Policy configuration using REST.

policy_request.jsonJson
{
  "id": "your_policy_configuration_gid"
}

Step 3

Create a CIQ Query in the context of the policy to upsert and retrieve properties with metadata on a node.

knowledge_query.jsonJson
{
  "nodes": [
    "car",
    "ln.property.status",
    "ln.property.status.metadata.source",
    "ln.property.status.metadata.assurance_level",
    "ln.property.status.metadata.somethingImportant",
    "ln.property.license",
    "ln.property.license.metadata.source"
  ],
  "relationships": [],
  "upsert_nodes": [
    {
      "name": "ln",
      "properties": [
        {
          "type": "status",
          "value": "$status",
          "metadata": [
            {
              "type": "source",
              "value": "$token.iss"
            },
            {
              "type": "assurance_level",
              "value": 2
            },
            {
              "type": "somethingImportant",
              "value": "supercoolvalue"
            }
          ]
        },
        {
          "type": "license",
          "value": "$ln_number",
          "metadata": [
            {
              "type": "source",
              "value": "The government"
            }
          ]
        }
      ]
    }
  ],
  "filter": {
    "attribute": "ln.external_id",
    "operator": "=",
    "value": "$ln_external_id"
  }
}

Request to create a CIQ Query configuration using REST.

POST https://eu.api.indykite.com/configs/v1/knowledge-queriesJson
{
  "project_id": "your_project_gid",
  "description": "description of knowledge query",
  "display_name": "knowledge query name",
  "name": "knowledge-query-name",
  "policy_id": "your_policy_gid",
  "query": "{\"nodes\":[\"car\",\"ln.property.status\",\"ln.property.status.metadata.source\",\"ln.property.status.metadata.assurance_level\",\"ln.property.status.metadata.somethingImportant\",\"ln.property.license\",\"ln.property.license.metadata.source\"],\"relationships\":[],\"upsert_nodes\":[{\"name\":\"ln\",\"properties\":[{\"type\":\"status\",\"value\":\"$status\",\"metadata\":[{\"type\":\"source\",\"value\":\"$token.iss\"},{\"type\":\"assurance_level\",\"value\":2},{\"type\":\"somethingImportant\",\"value\":\"supercoolvalue\"}]},{\"type\":\"license\",\"value\":\"$ln_number\",\"metadata\":[{\"type\":\"source\",\"value\":\"The government\"}]}]}],\"filter\":{\"attribute\":\"ln.external_id\",\"operator\":\"=\",\"value\":\"$ln_external_id\"}}",
  "status": "ACTIVE"
}

Read the CIQ Query Configuration.

GET https://eu.api.indykite.com/configs/v1/knowledge-queries/{id}Json
{
  "id": "your_knowledge_query_configuration_gid"
}

Step 4

Run a CIQ Execution to get the newly created property information.

POST https://eu.api.indykite.com/contx-iq/v1/executeJson
{
  "id": "knowledge_query_gid",
  "input_params": {
    "subject_external_id": "alice",
    "token_sub": "alice_user_external_id",
    "status": "Valid",
    "ln_number": "ln-xxx-value",
    "ln_external_id": "ln-xxx"
  },
  "page_token": 1
}

CIQ Execution response.

response.jsonJson
{
  "data": [
    {
      "nodes": {
        "car": {
          "Id": 58,
          "ElementId": "4:a5c213aa-aa4b-4be5-a17a-a677a80ee634:58",
          "Labels": [
            "Unique",
            "Resource",
            "Car"
          ],
          "Props": {
            "_service": "capture-api",
            "create_time": "2025-08-13T17:19:43.014Z",
            "external_id": "kitt",
            "id": "twixV9zqQniA201VtZdzxw",
            "type": "Car",
            "update_time": "2025-08-13T17:20:00.141Z"
          }
        },
        "ln.property.license": "ln-xxx-value",
        "ln.property.license.metadata.source": "The government",
        "ln.property.status": "Valid",
        "ln.property.status.metadata.assurance_level": 2,
        "ln.property.status.metadata.somethingImportant": "supercoolvalue",
        "ln.property.status.metadata.source": "https://issuer_url"
      }
    }
  ]
}

Step 5

Create a CIQ Query in the context of the policy to retrieve property information according to a filter on one of the newly created metadata.

knowledge_query.jsonJson
{
  "nodes": [
    "car",
    "ln.property.status",
    "ln.property.status.metadata.source",
    "ln.property.status.metadata.assurance_level"
  ],
  "relationships": [],
  "filter": {
    "attribute": "ln.property.status.metadata.assurance_level",
    "operator": ">=",
    "value": 2
  }
}

Request to create a CIQ Query configuration using REST.

POST https://eu.api.indykite.com/configs/v1/knowledge-queriesJson
{
  "project_id": "your_project_gid",
  "description": "description of knowledge query",
  "display_name": "knowledge query name",
  "name": "knowledge-query-name",
  "policy_id": "your_policy_gid",
  "query": "{\"nodes\":[\"car\",\"ln.property.status\",\"ln.property.status.metadata.source\",\"ln.property.status.metadata.assurance_level\"],\"relationships\":[],\"filter\":{\"attribute\":\"ln.property.status.metadata.assurance_level\",\"operator\":\">=\",\"value\":2}}",
  "status": "ACTIVE"
}

Read the CIQ Query Configuration.

GET https://eu.api.indykite.com/configs/v1/knowledge-queries/{id}Json
{
  "id": "your_knowledge_query_configuration_gid"
}

Step 6

Run a CIQ Execution to read the data.

POST https://eu.api.indykite.com/contx-iq/v1/executeJson
{
  "id": "knowledge_query_gid",
  "input_params": {
    "subject_external_id": "alice",
    "token_sub": "alice_user_external_id"
  },
  "page_token": 1
}

CIQ Execution response.

response.jsonJson
{
  "data": [
    {
      "nodes": {
        "car": {
          "Id": 16,
          "ElementId": "4:a5c213aa-aa4b-4be5-a17a-a677a80ee634:16",
          "Labels": [
            "Unique",
            "Resource",
            "Car"
          ],
          "Props": {
            "_service": "capture-api",
            "create_time": "2025-08-13T14:18:57.565Z",
            "external_id": "kitt",
            "id": "ylK0vV4_T2CeCUxpolR7aw",
            "type": "Car",
            "update_time": "2025-08-13T14:18:57.565Z"
          }
        },
        "ln.property.status": "Valid",
        "ln.property.status.metadata.assurance_level": 2,
        "ln.property.status.metadata.source": "https://issuer_url"
      }
    }
  ]
}