ContX IQ: User Consent Management - Grant and Revoke Payment Access
This example demonstrates user-controlled consent management:
Use case: A Person grants a Company permission to charge their payment method, then later revokes it.
Key concepts:
1. User authenticates with their token -> becomes the query subject
2. User can only manage consent for their OWN payment methods
3. GRANTED relationship represents active consent
4. Deleting GRANTED relationship revokes consent
Operations:
- Grant: Create PaymentMethod -[GRANTED]-> Company relationship
- Revoke: Delete PaymentMethod -[GRANTED]-> Company relationship
This pattern supports GDPR consent requirements and user self-service.
Use case
Scenario: Alice wants to let RentalCo charge her credit card for rentals.
Initial graph:
Person(Alice) -[HAS]-> PaymentMethod(AliceCard)
Company(RentalCo)
Grant consent workflow:
1. Alice authenticates (token introspected)
2. Alice executes grant query
3. Result: PaymentMethod(AliceCard) -[GRANTED]-> Company(RentalCo)
Later, Alice revokes consent:
1. Alice authenticates again
2. Alice executes revoke query
3. Result: GRANTED relationship deleted
Authorization ensures:
- Alice can only grant/revoke consent for HER payment methods
- The system verifies Person -[HAS]-> PaymentMethod relationship
- Other users cannot modify Alice's consents

Requirements
Prerequisites:
- ServiceAccount credentials: For creating policies and queries (Bearer token)
- AppAgent credentials: For data ingestion and query execution (X-IK-ClientKey)
- User access token: JWT for the Person granting/revoking consent
How to pass user token:
- Header: Authorization: Bearer {user_access_token}
- The token identifies the Person and scopes operations to their data
Steps
Step 1: Ingest Person, PaymentMethod, and Company Data
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action: POST Person, PaymentMethod, Company nodes
- Action: POST Person -[HAS]-> PaymentMethod relationship
- Result: Graph ready for consent management
Step 2: Create Consent Grant Policy
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST policy allowing authenticated Person to:
- UPSERT GRANTED relationship from their PaymentMethod to a Company
- Authorization path: Subject -[HAS]-> PaymentMethod -[GRANTED]-> Company
- Result: Policy ID returned
Step 3: Create Consent Grant Query
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST query that creates PaymentMethod -[GRANTED]-> Company
- Parameters: $companyId (which company to grant access to)
- Result: Query ID returned
Step 4: Execute Consent Grant (as Alice)
- Authentication: AppAgent credential + Alice's token (Bearer header)
- Action: POST to /contx-iq/v1/execute with companyId parameter
- Result: AliceCard -[GRANTED]-> RentalCo relationship created
Step 5: Create Consent Revoke Policy
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST policy allowing authenticated Person to:
- DELETE GRANTED relationship from their PaymentMethod to a Company
- Result: Policy ID returned
Step 6: Create Consent Revoke Query
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST query that deletes PaymentMethod -[GRANTED]-> Company
- Parameters: $companyId (which company to revoke access from)
- Result: Query ID returned
Step 7: Execute Consent Revoke (as Alice)
- Authentication: AppAgent credential + Alice's token (Bearer header)
- Action: POST to /contx-iq/v1/execute with companyId parameter
- Result: AliceCard -[GRANTED]-> RentalCo relationship deleted
Step 1
Capture the nodes needed for this use case.
{
"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": "bob",
"type": "Person",
"is_identity": true,
"properties": [
{
"type": "email",
"value": "bob@email.com"
},
{
"type": "given_name",
"value": "Bob"
}
]
},
{
"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": "Parking"
},
{
"type": "status",
"value": "Active"
}
]
},
{
"external_id": "ct234",
"type": "Contract",
"properties": [
{
"type": "category",
"value": "Parking"
},
{
"type": "status",
"value": "Active"
}
]
},
{
"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": "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": "companyParking",
"type": "Company",
"properties": [
{
"type": "name",
"value": "City Parking Inc"
}
]
}
]
}Capture the relationships needed for this use case.
{
"relationships": [
{
"source": {
"external_id": "bob",
"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": "alice",
"type": "Person"
},
"target": {
"external_id": "ct123",
"type": "Contract"
},
"type": "ACCEPTED"
},
{
"source": {
"external_id": "bob",
"type": "Person"
},
"target": {
"external_id": "ct234",
"type": "Contract"
},
"type": "ACCEPTED"
},
{
"source": {
"external_id": "ct123",
"type": "Contract"
},
"target": {
"external_id": "car1",
"type": "Vehicle"
},
"type": "COVERS"
},
{
"source": {
"external_id": "ct234",
"type": "Contract"
},
"target": {
"external_id": "car2",
"type": "Vehicle"
},
"type": "COVERS"
},
{
"source": {
"external_id": "car1",
"type": "Vehicle"
},
"target": {
"external_id": "license1",
"type": "LicenseNumber"
},
"type": "HAS"
},
{
"source": {
"external_id": "car2",
"type": "Vehicle"
},
"target": {
"external_id": "license2",
"type": "LicenseNumber"
},
"type": "HAS"
},
{
"source": {
"external_id": "companyParking",
"type": "Company"
},
"target": {
"external_id": "ct234",
"type": "Contract"
},
"type": "OFFERS"
},
{
"source": {
"external_id": "companyParking",
"type": "Company"
},
"target": {
"external_id": "ct123",
"type": "Contract"
},
"type": "OFFERS"
}
]
}Step 2
Create a CIQ Policy which designates a relationship between a PaymentMethod and a Company can be upserted.
{
"meta": {
"policy_version": "1.0-ciq"
},
"subject": {
"type": "Person"
},
"condition": {
"cypher": "MATCH (company:Company)-[:OFFERS]->(contract:Contract)<-[:ACCEPTED]-(subject:Person)-[:HAS]->(payment:PaymentMethod), (contract)-[:COVERS]->(vehicle:Vehicle)-[: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": [
"company.*",
"subject.*",
"payment.*"
]
},
"allowed_upserts": {
"relationships": {
"relationship_types": [
{
"type": "GRANTED",
"source_node_label": "Company",
"target_node_label": "PaymentMethod"
}
]
}
}
}Request to create the CIQ Policy configuration using REST.
{
"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 (company:Company)-[:OFFERS]->(contract:Contract)<-[:ACCEPTED]-(subject:Person)-[:HAS]->(payment:PaymentMethod), (contract)-[:COVERS]->(vehicle:Vehicle)-[: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\":[\"company.*\",\"subject.*\",\"payment.*\"]},\"allowed_upserts\":{\"relationships\":{\"relationship_types\":[{\"type\":\"GRANTED\",\"source_node_label\":\"Company\",\"target_node_label\":\"PaymentMethod\"}]}}}",
"status": "ACTIVE",
"tags": []
}Request to read the CIQ Policy configuration using REST.
{
"id": "your_policy_configuration_gid"
}Step 3
Create a CIQ Query in the context of the policy to create a GRANTED relationship between a company and a payment method.
{
"nodes": [
"company.external_id",
"subject.external_id",
"payment.external_id"
],
"upsert_relationships": [
{
"name": "newRel",
"source": "company",
"target": "payment",
"type": "GRANTED"
}
]
}Request to create a CIQ Query configuration using REST.
{
"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\":[\"company.external_id\",\"subject.external_id\",\"payment.external_id\"],\"upsert_relationships\":[{\"name\":\"newRel\",\"source\":\"company\",\"target\":\"payment\",\"type\":\"GRANTED\"}]}",
"status": "ACTIVE"
}Read the CIQ Query Configuration.
{
"id": "your_knowledge_query_configuration_gid"
}Step 4
Run a CIQ Execution to create a GRANTED relationship from the Person access token.
{
"id": "knowledge_query_gid",
"input_params": {
"subject_external_id": "alice",
"token_sub": "alice_user_external_id"
},
"page_token": 1
}CIQ Execution response.
{
"data": [
{
"nodes": {
"company.external_id": "companyParking",
"payment.external_id": "cb123",
"subject.external_id": "alice"
}
}
]
}Step 5
Create a CIQ Policy which designates a relationship between a PaymentMethod and a Company can be deleted.
{
"meta": {
"policy_version": "1.0-ciq"
},
"subject": {
"type": "Person"
},
"condition": {
"cypher": "MATCH (company:Company)-[g1:GRANTED]->(payment:PaymentMethod)<-[:HAS]-(subject:Person)",
"filter": [
{
"operator": "AND",
"operands": [
{
"attribute": "subject.external_id",
"operator": "=",
"value": "$subject_external_id"
},
{
"attribute": "$token.sub",
"operator": "=",
"value": "$token_sub"
}
]
}
]
},
"allowed_reads": {
"nodes": [
"company.*",
"subject.*",
"payment.*"
]
},
"allowed_deletes": {
"relationships": [
"g1"
]
}
}Json to create the CIQ Policy configuration using REST.
{
"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 (company:Company)-[g1:GRANTED]->(payment:PaymentMethod)<-[:HAS]-(subject:Person)\",\"filter\":[{\"operator\":\"AND\",\"operands\":[{\"attribute\":\"subject.external_id\",\"operator\":\"=\",\"value\":\"$subject_external_id\"},{\"attribute\":\"$token.sub\",\"operator\":\"=\",\"value\":\"$token_sub\"}]}]},\"allowed_reads\":{\"nodes\":[\"company.*\",\"subject.*\",\"payment.*\"]},\"allowed_deletes\":{\"relationships\":[\"g1\"]}}",
"status": "ACTIVE",
"tags": []
}Json to read the CIQ Policy configuration using REST.
{
"id": "your_policy_configuration_gid"
}Step 6
Create a CIQ Query in the context of the policy to delete a GRANTED relationship between a company and a payment method.
{
"nodes": [
"company.external_id",
"subject.external_id",
"payment.external_id"
],
"delete_relationships": [
"g1"
]
}Json to create a CIQ Query configuration using REST.
{
"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\":[\"company.external_id\",\"subject.external_id\",\"payment.external_id\"],\"delete_relationships\":[\"g1\"]}",
"status": "ACTIVE"
}Read the CIQ Query Configuration.
{
"id": "your_knowledge_query_configuration_gid"
}Step 7
Run a CIQ Execution to delete a GRANTED relationship from the Person access token.
{
"id": "knowledge_query_gid",
"input_params": {
"subject_external_id": "alice",
"token_sub": "alice_user_external_id"
},
"page_token": 1
}CIQ Execution response.
{
"data": [
{
"nodes": {
"company.external_id": "companyParking",
"payment.external_id": "cb123",
"subject.external_id": "alice"
}
}
]
}
API Endpoints
/capture/v1/nodes /capture/v1/relationships /configs/v1/authorization-policies /configs/v1/knowledge-queries /contx-iq/v1/execute