ContX IQ: Create Nodes and Relationships via Authorized Write Query
This example demonstrates authorized WRITE operations in ContX IQ:
Phase 1 - Link Application to Company:
1. Create policy allowing _Application to create HAS_AGREEMENT_WITH relationships
2. Execute query to link Application to Company1
Phase 2 - Create Contract with Relationships:
3. Create policy allowing Contract node creation and COVERS/ACCEPTED relationships
4. Execute write query with parameters to create:
- New Contract node (with parameterized external_id and number)
- COVERS relationship: Contract -> Vehicle
- ACCEPTED relationship: Person -> Contract
Authorization constraint: The Application can only create contracts for vehicles owned by companies it has an agreement with.
Use case
Scenario: Your application needs to create new rental contracts programmatically.
Business rule: Contracts can only be created for vehicles owned by companies your application has agreements with.
Write operations performed:
1. CREATE Contract node (with properties: external_id, number)
2. CREATE COVERS relationship (Contract -> Vehicle)
3. CREATE ACCEPTED relationship (Person -> Contract)
Graph change:
Before: Person(Ryan), Vehicle(Car1), Company1 exist separately
After: Person(Ryan) -[ACCEPTED]-> Contract(New) -[COVERS]-> Vehicle(Car1)
Key feature: The external_id and number for the Contract are passed as query parameters at execution time.

Requirements
Prerequisites:
- ServiceAccount credentials: For creating policies and queries (Bearer token)
- AppAgent credentials: For data ingestion and query execution (X-IK-ClientKey)
Required API access:
- POST /capture/v1/nodes/ and /capture/v1/relationships/ (initial data)
- POST /configs/v1/authorization-policies (create policies)
- POST /configs/v1/knowledge-queries (create queries)
- POST /contx-iq/v1/execute (run queries)
Steps
Step 1: Ingest Initial Graph Data
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action: POST nodes (Person, Vehicle, Company) and relationships
- Result: Base graph structure ready for contract creation
Step 2: Create Application Linking Policy
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST policy allowing _Application to create HAS_AGREEMENT_WITH relationships
- Result: Policy ID returned
Step 3: Create Application Linking Query
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST write query that creates Application -> Company relationship
- Result: Query ID returned
Step 4: Execute Application Linking
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action: Execute the linking query
- Result: _Application -[HAS_AGREEMENT_WITH]-> Company1 created
Step 5: Create Contract Write Policy
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST policy with allowed_upserts defining:
- allowed_upserts.nodes: Can create Contract nodes
- allowed_upserts.relationships: Can create COVERS and ACCEPTED relationships
- Result: Policy ID returned
Step 6: Create Contract Write Query
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST parameterized query that creates Contract node and relationships
- Parameters: $contractId, $contractNumber, $personEmail, $vehicleLicense
- Result: Query ID returned
Step 7: Execute Contract Creation
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action: Execute with parameter values (e.g., contractId="C001", contractNumber="12345")
- Result: New Contract node and relationships created in the graph
Step 8: Cleanup
- Action: DELETE queries and policies
Step 1a
Capture base nodes: Person, Company, Vehicle, LicenseNumber. These will be linked by the contract created later.
{
"nodes": [
{
"external_id": "alice",
"is_identity": true,
"type": "Person",
"properties": [
{
"type": "email",
"value": "alice@email.com"
},
{
"type": "given_name",
"value": "Alice"
},
{
"type": "last_name",
"value": "Smith"
}
]
},
{
"external_id": "ryan",
"is_identity": true,
"type": "Person",
"properties": [
{
"type": "email",
"value": "ryan@yahoo.co.uk"
},
{
"type": "given_name",
"value": "ryan"
},
{
"type": "last_name",
"value": "mushu"
}
]
},
{
"external_id": "tilda",
"is_identity": true,
"type": "Person",
"properties": [
{
"type": "email",
"value": "tilda@yahoo.co.uk"
},
{
"type": "given_name",
"value": "tilda"
},
{
"type": "last_name",
"value": "mushu"
}
]
},
{
"external_id": "cb123",
"type": "PaymentMethod",
"properties": [
{
"type": "payment_name",
"value": "Credit Card"
}
]
},
{
"external_id": "kl123",
"type": "PaymentMethod",
"properties": [
{
"type": "payment_name",
"value": "Klarna"
}
]
},
{
"external_id": "ct123",
"type": "Contract",
"properties": [
{
"type": "category",
"value": "Insurance"
},
{
"type": "status",
"value": "Active"
},
{
"type": "number",
"value": "hfgrten123",
"metadata": {
"assurance_level": 3,
"source": "BRREG"
}
}
]
},
{
"external_id": "ct234",
"type": "Contract",
"properties": [
{
"type": "category",
"value": "Insurance"
},
{
"type": "status",
"value": "Active"
},
{
"type": "number",
"value": "hfgrten234",
"metadata": {
"assurance_level": 3,
"source": "BRREG"
}
}
]
},
{
"external_id": "ct985",
"type": "Contract",
"properties": [
{
"type": "category",
"value": "Insurance"
},
{
"type": "status",
"value": "Active"
},
{
"type": "number",
"value": "hfgrten985",
"metadata": {
"assurance_level": 3,
"source": "BRREG"
}
}
]
},
{
"external_id": "car1",
"type": "Vehicle",
"properties": [
{
"type": "category",
"value": "Car"
},
{
"type": "is_active",
"value": true
},
{
"type": "vin",
"value": "rtfhcnvjt471"
}
]
},
{
"external_id": "car2",
"type": "Vehicle",
"properties": [
{
"type": "category",
"value": "Car"
},
{
"type": "is_active",
"value": true
},
{
"type": "vin",
"value": "kdcbfrt178"
}
]
},
{
"external_id": "truck1",
"type": "Vehicle",
"properties": [
{
"type": "category",
"value": "Truck"
},
{
"type": "is_active",
"value": true
},
{
"type": "vin",
"value": "sncnrkcldp"
}
]
},
{
"external_id": "license1",
"type": "LicenseNumber",
"properties": [
{
"type": "status",
"value": "Active"
},
{
"type": "number",
"value": "AX123456",
"metadata": {
"assurance_level": 3,
"source": "BRREG"
}
}
]
},
{
"external_id": "license2",
"type": "LicenseNumber",
"properties": [
{
"type": "status",
"value": "Active"
},
{
"type": "number",
"value": "OL123456",
"metadata": {
"assurance_level": 3,
"source": "BRREG"
}
}
]
},
{
"external_id": "license3",
"type": "LicenseNumber",
"properties": [
{
"type": "status",
"value": "Active"
},
{
"type": "number",
"value": "VN123456",
"metadata": {
"assurance_level": 3,
"source": "BRREG"
}
}
]
},
{
"external_id": "company1",
"type": "Company",
"properties": [
{
"type": "name",
"value": "Company1"
},
{
"type": "registration",
"value": "256314523"
}
]
},
{
"external_id": "company2",
"type": "Company",
"properties": [
{
"type": "name",
"value": "Company2"
},
{
"type": "registration",
"value": "942365123"
}
]
},
{
"external_id": "application1",
"type": "Application",
"properties": [
{
"type": "name",
"value": "Application"
}
]
},
{
"external_id": "application2",
"type": "Application",
"properties": [
{
"type": "name",
"value": "Application2"
}
]
}
]
}Step 1b
Capture initial relationships (Company OWNS Vehicle, Vehicle HAS LicenseNumber).
{
"relationships": [
{
"source": {
"external_id": "ryan",
"type": "Person"
},
"target": {
"external_id": "cb123",
"type": "PaymentMethod"
},
"type": "HAS"
},
{
"source": {
"external_id": "tilda",
"type": "Person"
},
"target": {
"external_id": "kl123",
"type": "PaymentMethod"
},
"type": "HAS"
},
{
"source": {
"external_id": "alice",
"type": "Person"
},
"target": {
"external_id": "cb123",
"type": "PaymentMethod"
},
"type": "HAS"
},
{
"source": {
"external_id": "ryan",
"type": "Person"
},
"target": {
"external_id": "ct123",
"type": "Contract"
},
"type": "ACCEPTED"
},
{
"source": {
"external_id": "tilda",
"type": "Person"
},
"target": {
"external_id": "ct234",
"type": "Contract"
},
"type": "ACCEPTED"
},
{
"source": {
"external_id": "alice",
"type": "Person"
},
"target": {
"external_id": "ct985",
"type": "Contract"
},
"type": "ACCEPTED"
},
{
"source": {
"external_id": "ct123",
"type": "Contract"
},
"target": {
"external_id": "car1",
"type": "Vehicle"
},
"type": "COVERS"
},
{
"source": {
"external_id": "ct985",
"type": "Contract"
},
"target": {
"external_id": "car1",
"type": "Vehicle"
},
"type": "COVERS"
},
{
"source": {
"external_id": "ct234",
"type": "Contract"
},
"target": {
"external_id": "truck1",
"type": "Vehicle"
},
"type": "COVERS"
},
{
"source": {
"external_id": "car1",
"type": "Vehicle"
},
"target": {
"external_id": "license1",
"type": "LicenseNumber"
},
"type": "HAS"
},
{
"source": {
"external_id": "truck1",
"type": "Vehicle"
},
"target": {
"external_id": "license2",
"type": "LicenseNumber"
},
"type": "HAS"
},
{
"source": {
"external_id": "car2",
"type": "Vehicle"
},
"target": {
"external_id": "license3",
"type": "LicenseNumber"
},
"type": "HAS"
},
{
"source": {
"external_id": "company1",
"type": "Company"
},
"target": {
"external_id": "car1",
"type": "Vehicle"
},
"type": "OWNS"
},
{
"source": {
"external_id": "company1",
"type": "Company"
},
"target": {
"external_id": "car2",
"type": "Vehicle"
},
"type": "OWNS"
},
{
"source": {
"external_id": "company1",
"type": "Company"
},
"target": {
"external_id": "truck1",
"type": "Vehicle"
},
"type": "OWNS"
},
{
"source": {
"external_id": "application1",
"type": "Application"
},
"target": {
"external_id": "company1",
"type": "Company"
},
"type": "HAS_AGREEMENT_WITH"
},
{
"source": {
"external_id": "application2",
"type": "Application"
},
"target": {
"external_id": "company1",
"type": "Company"
},
"type": "HAS_AGREEMENT_WITH"
}
]
}Step 2a
Policy JSON allowing _Application to CREATE HAS_AGREEMENT_WITH relationships to Company nodes.
{
"meta": {
"policy_version": "1.0-ciq"
},
"subject": {
"type": "_Application"
},
"condition": {
"cypher": "MATCH (subject:_Application) MATCH (company:Company)-[r2:OWNS]->(vehicle:Vehicle)",
"filter": [
{
"operator": "AND",
"operands": [
{
"attribute": "subject.external_id",
"operator": "=",
"value": "$_appId"
},
{
"attribute": "company.external_id",
"operator": "=",
"value": "$companyID"
}
]
}
]
},
"allowed_upserts": {
"relationships": {
"relationship_types": [
{
"type": "HAS_AGREEMENT_WITH",
"source_node_label": "_Application",
"target_node_label": "Company"
}
]
}
},
"allowed_reads": {
"nodes": [
"company.*",
"subject.*"
]
}
}Step 2b
POST request to create the application linking policy.
{
"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 (company:Company)-[r2:OWNS]->(vehicle:Vehicle)\",\"filter\":[{\"operator\":\"AND\",\"operands\":[{\"attribute\":\"subject.external_id\",\"operator\":\"=\",\"value\":\"$_appId\"},{\"attribute\":\"company.external_id\",\"operator\":\"=\",\"value\":\"$companyID\"}]}]},\"allowed_upserts\":{\"relationships\":{\"relationship_types\":[{\"type\":\"HAS_AGREEMENT_WITH\",\"source_node_label\":\"_Application\",\"target_node_label\":\"Company\"}]}},\"allowed_reads\":{\"nodes\":[\"company.*\",\"subject.*\"]}}",
"status": "ACTIVE",
"tags": []
}Step 2c
GET request to verify the policy was created.
{
"id": "your_policy_configuration_gid"
}Step 3a
Write query JSON that creates _Application -[HAS_AGREEMENT_WITH]-> Company relationship.
{
"nodes": [
"subject.external_id"
],
"relationships": [
"r1"
],
"upsert_relationships": [
{
"name": "r1",
"source": "subject",
"target": "company",
"type": "HAS_AGREEMENT_WITH"
}
]
}Step 3b
POST request to create the application linking query.
{
"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\":[\"subject.external_id\"],\"relationships\":[\"r1\"],\"upsert_relationships\":[{\"name\":\"r1\",\"source\":\"subject\",\"target\":\"company\",\"type\":\"HAS_AGREEMENT_WITH\"}]}",
"status": "ACTIVE"
}Step 3c
GET request to verify the query was created.
{
"id": "your_knowledge_query_configuration_gid"
}Step 4a
Execute the linking query. Creates the relationship in the graph.
{
"id": "ciq_query_gid",
"input_params": {
"companyID": "company1"
}
}Step 4b
Response confirming the HAS_AGREEMENT_WITH relationship was created.
{
"data": [
{
"nodes": {
"subject.external_id": "application_external_id"
},
"relationships": {
"r1": {
"Id": 1152932499723124700,
"ElementId": "5:3a2b09d5-2923-45d7-8453-8b1c698427b0:1152932499723124736",
"StartId": 0,
"StartElementId": "4:3a2b09d5-2923-45d7-8453-8b1c698427b0:0",
"EndId": 15,
"EndElementId": "4:3a2b09d5-2923-45d7-8453-8b1c698427b0:15",
"Type": "HAS_AGREEMENT_WITH",
"Props": {
"create_time": "2025-06-09T15:12:46.374Z",
"id": "48BJHS2CTFKcVpD4cUF8IA",
"update_time": "2025-06-09T15:12:46.374Z"
}
}
}
},
{
"nodes": {
"subject.external_id": "application_external_id"
},
"relationships": {
"r1": {
"Id": 1152932499723124700,
"ElementId": "5:3a2b09d5-2923-45d7-8453-8b1c698427b0:1152932499723124736",
"StartId": 0,
"StartElementId": "4:3a2b09d5-2923-45d7-8453-8b1c698427b0:0",
"EndId": 15,
"EndElementId": "4:3a2b09d5-2923-45d7-8453-8b1c698427b0:15",
"Type": "HAS_AGREEMENT_WITH",
"Props": {
"create_time": "2025-06-09T15:12:46.374Z",
"id": "48BJHS2CTFKcVpD4cUF8IA",
"update_time": "2025-06-09T15:12:46.374Z"
}
}
}
},
{
"nodes": {
"subject.external_id": "application_external_id"
},
"relationships": {
"r1": {
"Id": 1152932499723124700,
"ElementId": "5:3a2b09d5-2923-45d7-8453-8b1c698427b0:1152932499723124736",
"StartId": 0,
"StartElementId": "4:3a2b09d5-2923-45d7-8453-8b1c698427b0:0",
"EndId": 15,
"EndElementId": "4:3a2b09d5-2923-45d7-8453-8b1c698427b0:15",
"Type": "HAS_AGREEMENT_WITH",
"Props": {
"create_time": "2025-06-09T15:12:46.374Z",
"id": "48BJHS2CTFKcVpD4cUF8IA",
"update_time": "2025-06-09T15:12:46.374Z"
}
}
}
}
]
}Step 5a
Policy JSON with allowed_upserts section defining: (1) Can CREATE Contract nodes, (2) Can CREATE COVERS relationships between Contract and Vehicle, (3) Can CREATE ACCEPTED relationships between Person and Contract.
{
"meta": {
"policy_version": "1.0-ciq"
},
"subject": {
"type": "_Application"
},
"condition": {
"cypher": "MATCH (subject:_Application)-[r1:HAS_AGREEMENT_WITH]->(company:Company)-[r2:OWNS]->(vehicle:Vehicle) MATCH (person:Person)",
"filter": [
{
"operator": "AND",
"operands": [
{
"attribute": "subject.external_id",
"operator": "=",
"value": "$_appId"
},
{
"attribute": "vehicle.external_id",
"operator": "=",
"value": "$vehicleID"
},
{
"attribute": "person.external_id",
"operator": "=",
"value": "$personID"
}
]
}
]
},
"allowed_upserts": {
"nodes": {
"node_types": [
"Contract"
]
},
"relationships": {
"relationship_types": [
{
"type": "COVERS",
"source_node_label": "Contract",
"target_node_label": "Vehicle"
},
{
"type": "ACCEPTED",
"source_node_label": "Person",
"target_node_label": "Contract"
}
]
}
},
"allowed_reads": {
"nodes": [
"vehicle.property.*",
"person.property.*"
],
"relationships": []
}
}Step 5b
POST request to create the contract write policy.
{
"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)-[r1:HAS_AGREEMENT_WITH]->(company:Company)-[r2:OWNS]->(vehicle:Vehicle) MATCH (person:Person)\",\"filter\":[{\"operator\":\"AND\",\"operands\":[{\"attribute\":\"subject.external_id\",\"operator\":\"=\",\"value\":\"$_appId\"},{\"attribute\":\"vehicle.external_id\",\"operator\":\"=\",\"value\":\"$vehicleID\"},{\"attribute\":\"person.external_id\",\"operator\":\"=\",\"value\":\"$personID\"}]}]},\"allowed_upserts\":{\"nodes\":{\"node_types\":[\"Contract\"]},\"relationships\":{\"relationship_types\":[{\"type\":\"COVERS\",\"source_node_label\":\"Contract\",\"target_node_label\":\"Vehicle\"},{\"type\":\"ACCEPTED\",\"source_node_label\":\"Person\",\"target_node_label\":\"Contract\"}]}},\"allowed_reads\":{\"nodes\":[\"vehicle.property.*\",\"person.property.*\"],\"relationships\":[]}}",
"status": "ACTIVE",
"tags": []
}Step 5c
GET request to verify the policy was created.
{
"id": "your_policy_configuration_gid"
}Step 6a
Parameterized write query JSON. Uses $contractId and $contractNumber variables for Contract properties. At execution time, actual values replace these placeholders.
{
"nodes": [
"contract.external_id",
"contract.property.number"
],
"relationships": [],
"upsert_nodes": [
{
"name": "contract",
"type": "Contract",
"external_id": "$contract_external_id",
"properties": [
{
"type": "number",
"value": "$contractNumber"
},
{
"type": "status",
"value": "Active"
}
]
}
],
"upsert_relationships": [
{
"name": "r3",
"source": "contract",
"target": "vehicle",
"type": "COVERS"
},
{
"name": "r4",
"source": "person",
"target": "contract",
"type": "ACCEPTED"
}
]
}Step 6b
POST request to create the contract write query.
{
"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\":[\"contract.external_id\",\"contract.property.number\"],\"relationships\":[],\"upsert_nodes\":[{\"name\":\"contract\",\"type\":\"Contract\",\"external_id\":\"$contract_external_id\",\"properties\":[{\"type\":\"number\",\"value\":\"$contractNumber\"},{\"type\":\"status\",\"value\":\"Active\"}]}],\"upsert_relationships\":[{\"name\":\"r3\",\"source\":\"contract\",\"target\":\"vehicle\",\"type\":\"COVERS\"},{\"name\":\"r4\",\"source\":\"person\",\"target\":\"contract\",\"type\":\"ACCEPTED\"}]}",
"status": "ACTIVE"
}Step 6c
GET request to verify the query was created.
{
"id": "your_knowledge_query_configuration_gid"
}Step 7a
Execute the write query with parameter values. Creates: (1) Contract node with specified ID and number, (2) COVERS relationship to Vehicle, (3) ACCEPTED relationship from Person.
{
"id": "knowledge_query_gid",
"input_params": {
"vehicleID": "car2",
"personID": "ryan",
"contract_external_id": "ct853",
"contractNumber": "rbjh853"
}
}Step 7b
Response confirming the Contract node and relationships were created.
{
"data": [
{
"nodes": {
"contract.external_id": "ct853",
"contract.property.number": "rbjh853"
}
}
]
}Step 8a
DELETE request to remove the queries.
{
"id": "your_knowledge_query_configuration_gid"
}Step 8b
DELETE request to remove the policies. Note: The created Contract node and relationships remain in the graph.
{
"id": "your_policy_configuration_gid"
}API Endpoints
/capture/v1/nodes /capture/v1/relationships /configs/v1/authorization-policies /configs/v1/knowledge-queries /contx-iq/v1/execute