Back to all resources
ContX IQ ContX IQ Json

ContX IQ: Application as Service - Create Person Linked to Multiple Nodes

Demonstrates service-to-service data creation where an Application (not a user) creates new Person nodes and links them to existing Country and Company nodes. Common pattern for system integrations and automated data pipelines.

ContX IQ: Application as Service - Create Person Linked to Multiple Nodes

This example shows Application-as-subject creating nodes with multiple relationships:

Service-to-service pattern:

- No user token involved

- Application authenticates with its API key

- Application creates data on behalf of the system

Operation:

Create Person node and link to two existing nodes:

- Person -[LIVES_IN]-> Country

- Person -[WORKS_AT]-> Company

Use cases:

- Data import pipelines

- System integrations

- Automated onboarding workflows

Use case

Scenario: An HR integration system automatically creates employee records.

Existing data:

- Country(USA)

- Company(Acme Corp)

Integration operation:

1. HR system triggers employee creation

2. Application creates: Person(name: "John Doe")

3. Links: Person -[LIVES_IN]-> Country(USA)

4. Links: Person -[WORKS_AT]-> Company(Acme Corp)

Final graph:

Country(USA) <-[LIVES_IN]- Person(John) -[WORKS_AT]-> Company(Acme)

Key difference from user-based creation:

- Uses $_appId filter (auto-populated)

- No user token required

- Application is the authorized subject

ikg

Requirements

Prerequisites:

- ServiceAccount credentials: For creating policies and queries (Bearer token)

- AppAgent credentials: For data ingestion and query execution (X-IK-ClientKey)

No user token needed:

- Application acts as its own subject

- $_appId automatically identifies the calling application

Steps

Step 1: Ingest Reference Data

- Authentication: AppAgent credential (X-IK-ClientKey header)

- Action: POST Country and Company nodes

- Result: Reference nodes ready for linking

Step 2: Create Node Creation Policy

- Authentication: ServiceAccount credential (Bearer token)

- Action: POST policy allowing:

- CREATE Person nodes

- CREATE LIVES_IN relationships (Person -> Country)

- CREATE WORKS_AT relationships (Person -> Company)

- Result: Policy ID returned

Step 3: Create Node Creation Query

- Authentication: ServiceAccount credential (Bearer token)

- Action: POST query with parameters:

- $personId, $personName (for Person node)

- $countryId (to link Country)

- $companyId (to link Company)

- Result: Query ID returned

Step 4: Execute Creation

- Authentication: AppAgent credential (X-IK-ClientKey header)

- Action: POST to /contx-iq/v1/execute with:

- personId: "john-doe-123"

- personName: "John Doe"

- countryId: "usa"

- companyId: "acme-corp"

- Result: Person created with both relationships

Step 5: Cleanup

- Action: DELETE query and policy configurations

Step 1

Capture the nodes needed for this use case.

POST https://eu.api.indykite.com/capture/v1/nodes/Json
{
  "nodes": [
    {
      "external_id": "Norway",
      "type": "Country"
    },
    {
      "external_id": "Forsenty",
      "type": "Company"
    }
  ]
}

Step 2

Policy which designates the derived query can create a Person node, a relationship with a Country node, and a relationship with a Company node.

policy.jsonJson
{
  "meta": {
    "policy_version": "1.0-ciq"
  },
  "subject": {
    "type": "_Application"
  },
  "condition": {
    "cypher": "MATCH (subject:_Application) MATCH (country:Country) MATCH (company:Company)",
    "filter": [
      {
        "app": "app1",
        "operator": "AND",
        "operands": [
          {
            "attribute": "subject.external_id",
            "operator": "=",
            "value": "$_appId"
          },
          {
            "attribute": "country.external_id",
            "operator": "=",
            "value": "$country_external_id"
          },
          {
            "attribute": "company.external_id",
            "operator": "=",
            "value": "$company_external_id"
          }
        ]
      }
    ]
  },
  "allowed_reads": {
    "nodes": [
      "country",
      "country.*",
      "company",
      "company.*"
    ]
  },
  "allowed_upserts": {
    "nodes": {
      "node_types": [
        "Person"
      ]
    },
    "relationships": {
      "relationship_types": [
        {
          "type": "BELONGS_TO",
          "source_node_label": "Person",
          "target_node_label": "Country"
        },
        {
          "type": "BELONGS_TO",
          "source_node_label": "Person",
          "target_node_label": "Company"
        }
      ]
    }
  }
}

Request to create a 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\":\"_Application\"},\"condition\":{\"cypher\":\"MATCH (subject:_Application) MATCH (country:Country) MATCH (company:Company)\",\"filter\":[{\"app\":\"app1\",\"operator\":\"AND\",\"operands\":[{\"attribute\":\"subject.external_id\",\"operator\":\"=\",\"value\":\"$_appId\"},{\"attribute\":\"country.external_id\",\"operator\":\"=\",\"value\":\"$country_external_id\"},{\"attribute\":\"company.external_id\",\"operator\":\"=\",\"value\":\"$company_external_id\"}]}]},\"allowed_reads\":{\"nodes\":[\"country\",\"country.*\",\"company\",\"company.*\"]},\"allowed_upserts\":{\"nodes\":{\"node_types\":[\"Person\"]},\"relationships\":{\"relationship_types\":[{\"type\":\"BELONGS_TO\",\"source_node_label\":\"Person\",\"target_node_label\":\"Country\"},{\"type\":\"BELONGS_TO\",\"source_node_label\":\"Person\",\"target_node_label\":\"Company\"}]}}}",
  "status": "ACTIVE",
  "tags": []
}

Request to read the CIQ Policy configuration using REST.

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

Step 3

The CIQ Knowledge Query designates the node to create and the relationships to upsert.

knowledge_query.jsonJson
{
  "nodes": [
    "person",
    "person.external_id"
  ],
  "relationships": [],
  "upsert_nodes": [
    {
      "name": "person",
      "type": "Person",
      "external_id": "$person_external_id",
      "properties": [
        {
          "type": "VerificationMethod",
          "value": "$verification_method",
          "metadata": [
            {
              "type": "Assurance_level",
              "value": "$assurance_level"
            },
            {
              "type": "source",
              "value": "$source"
            }
          ]
        },
        {
          "type": "Email",
          "value": "$email",
          "metadata": [
            {
              "type": "Assurance_level",
              "value": "$assurance_level"
            },
            {
              "type": "source",
              "value": "$source"
            }
          ]
        },
        {
          "type": "PhoneNumber",
          "value": "$phone_number",
          "metadata": [
            {
              "type": "assurance_level",
              "value": "$assurance_level"
            },
            {
              "type": "source",
              "value": "$source"
            }
          ]
        },
        {
          "type": "FirstName",
          "value": "$first_name",
          "metadata": [
            {
              "type": "assurance_level",
              "value": "$assurance_level"
            },
            {
              "type": "source",
              "value": "$source"
            }
          ]
        },
        {
          "type": "LastName",
          "value": "$last_name",
          "metadata": [
            {
              "type": "assurance_level",
              "value": "$assurance_level"
            },
            {
              "type": "source",
              "value": "$source"
            }
          ]
        }
      ]
    }
  ],
  "upsert_relationships": [
    {
      "name": "rel1",
      "source": "person",
      "target": "country",
      "type": "BELONGS_TO",
      "properties": []
    },
    {
      "name": "rel2",
      "source": "person",
      "target": "company",
      "type": "BELONGS_TO",
      "properties": []
    }
  ]
}

Request to create a CIQ Knowledge 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\":[\"person\",\"person.external_id\"],\"relationships\":[],\"upsert_nodes\":[{\"name\":\"person\",\"type\":\"Person\",\"external_id\":\"$person_external_id\",\"properties\":[{\"type\":\"VerificationMethod\",\"value\":\"$verification_method\",\"metadata\":[{\"type\":\"Assurance_level\",\"value\":\"$assurance_level\"},{\"type\":\"source\",\"value\":\"$source\"}]},{\"type\":\"Email\",\"value\":\"$email\",\"metadata\":[{\"type\":\"Assurance_level\",\"value\":\"$assurance_level\"},{\"type\":\"source\",\"value\":\"$source\"}]},{\"type\":\"PhoneNumber\",\"value\":\"$phone_number\",\"metadata\":[{\"type\":\"assurance_level\",\"value\":\"$assurance_level\"},{\"type\":\"source\",\"value\":\"$source\"}]},{\"type\":\"FirstName\",\"value\":\"$first_name\",\"metadata\":[{\"type\":\"assurance_level\",\"value\":\"$assurance_level\"},{\"type\":\"source\",\"value\":\"$source\"}]},{\"type\":\"LastName\",\"value\":\"$last_name\",\"metadata\":[{\"type\":\"assurance_level\",\"value\":\"$assurance_level\"},{\"type\":\"source\",\"value\":\"$source\"}]}]}],\"upsert_relationships\":[{\"name\":\"rel1\",\"source\":\"person\",\"target\":\"country\",\"type\":\"BELONGS_TO\",\"properties\":[]},{\"name\":\"rel2\",\"source\":\"person\",\"target\":\"company\",\"type\":\"BELONGS_TO\",\"properties\":[]}]}",
  "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

CIQ Execution request in json format.

POST https://eu.api.indykite.com/contx-iq/v1/executeJson
{
  "id": "knowledge_query_gid",
  "input_params": {
    "person_external_id": "456985",
    "verification_method": "BREGG",
    "assurance_level": 3,
    "source": "NAV",
    "email": "elias@email.com",
    "phone_number": "4725639685",
    "first_name": "Elias",
    "last_name": "Boomy",
    "country_external_id": "Norway",
    "company_external_id": "Forsenty"
  },
  "page_token": 1
}

CIQ Execution response in json format.

response.jsonJson
{
  "data": [
    {
      "nodes": {
        "person": {
          "Id": 5,
          "ElementId": "4:a5c213aa-aa4b-4be5-a17a-a677a80ee634:5",
          "Labels": [
            "Unique",
            "Resource",
            "Person"
          ],
          "Props": {
            "create_time": "2025-09-26T11:29:25.43Z",
            "external_id": "456985",
            "id": "I2kGlVoQQHmj_gfNvH4b-A",
            "type": "Person",
            "update_time": "2025-09-26T11:29:25.43Z"
          }
        },
        "person.external_id": "456985"
      }
    }
  ]
}

Step 5

Delete the CIQ Query.

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

Delete the CIQ Policy.

DELETE https://eu.api.indykite.com/configs/v1/authorization-policies/{id}Json
{
  "id": "your_policy_configuration_gid"
}

ikg