ContX IQ: Loyalty Program - Retrieve Payment Method from License Plate
This example demonstrates a complex real-world authorization scenario for loyalty programs:
Input: License plate number
Output: Credit card external_id (for authorized requests only)
Authorization conditions checked:
1. The vehicle's license plate must be registered
2. All users of the vehicle must be on the same loyalty plan
3. The application must have valid consent (not expired) from the user
This showcases ContX IQ's ability to enforce business rules through graph relationships and time-based conditions.
Use case
Scenario: A gas station loyalty app wants to auto-charge a registered credit card when a vehicle arrives.
Business rules enforced by the policy:
1. License plate registration: The car owner must have registered the license plate in the system
2. Loyalty plan consistency: All users who can drive the car must be on the same loyalty plan (prevents conflicts)
3. Consent validation: The app must have unexpired consent from the car owner to access payment info
Graph structure:
Vehicle -[HAS]-> LicenseNumber
Person -[OWNS]-> Vehicle
Person -[MEMBER_OF]-> LoyaltyPlan
Person -[GAVE_CONSENT]-> Consent -[TO_APP]-> Application
Person -[HAS]-> CreditCard
Query flow:
1. Find Vehicle by license plate
2. Find Person who owns the Vehicle
3. Verify all Vehicle drivers are on same LoyaltyPlan
4. Check Person's Consent to the requesting App (verify not expired)
5. If all conditions pass, return CreditCard.external_id

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/ (loyalty data)
- POST /configs/v1/authorization-policies (create policy)
- POST /configs/v1/knowledge-queries (create query)
- POST /contx-iq/v1/execute (run query)
Steps
Step 1: Ingest Loyalty Program Graph Data
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action: POST nodes: Person, Vehicle, LicenseNumber, LoyaltyPlan, Consent, CreditCard, Application
- Action: POST relationships: OWNS, HAS, MEMBER_OF, GAVE_CONSENT, TO_APP
- Result: Complete loyalty program graph ready for queries
Step 2: Create Loyalty Authorization Policy
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST policy with conditions:
- Match vehicle by license plate input
- Traverse to owner Person
- Verify loyalty plan consistency across all drivers
- Validate consent exists and is not expired
- Allow READ on CreditCard.external_id if conditions pass
- Result: Policy ID returned
Step 3: Create Loyalty Query
- Authentication: ServiceAccount credential (Bearer token)
- Action: POST query that takes license plate as input and returns credit card ID
- Input parameter: $licensePlate (string)
- Result: Query ID returned
Step 4: Execute Loyalty Query
- Authentication: AppAgent credential (X-IK-ClientKey header)
- Action: POST to /contx-iq/v1/execute with license plate value
- Result: Credit card external_id (if authorized) or empty result (if not authorized)
Step 5: Cleanup
- Action: DELETE query and policy configurations
Step 1a
Capture loyalty program nodes: Person (car owner), Vehicle, LicenseNumber, LoyaltyPlan, Consent (with expiration date), CreditCard, and Application.
{
"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": "ole",
"is_identity": true,
"type": "Person",
"properties": [
{
"type": "email",
"value": "ole@yahoo.co.uk"
},
{
"type": "given_name",
"value": "ole"
},
{
"type": "last_name",
"value": "einar"
}
]
},
{
"external_id": "cb2563",
"type": "PaymentMethod",
"properties": [
{
"type": "payment_name",
"value": "Credit Card Parking"
},
{
"type": "preference",
"value": "Pay as you go"
}
]
},
{
"external_id": "carOle",
"type": "Vehicle",
"properties": [
{
"type": "category",
"value": "Car"
},
{
"type": "is_active",
"value": true
},
{
"type": "vin",
"value": "pcfjnm78"
}
]
},
{
"external_id": "licenseOle",
"type": "LicenseNumber",
"properties": [
{
"type": "status",
"value": "Active"
},
{
"type": "number",
"value": "AL98745",
"metadata": {
"assurance_level": 3,
"source": "BRREG"
}
}
]
},
{
"external_id": "loyalty1",
"type": "Loyalty",
"properties": [
{
"type": "name",
"value": "Parking Loyalty Plan"
}
]
},
{
"external_id": "consent1",
"type": "ConsentPayment",
"properties": [
{
"type": "name",
"value": "Consent Parking"
}
]
},
{
"external_id": "companyParking",
"type": "Company",
"properties": [
{
"type": "name",
"value": "City Parking Inc"
}
]
},
{
"external_id": "applicationParking",
"type": "Application",
"properties": [
{
"type": "name",
"value": "City Mall Parking"
}
]
}
]
}Step 1b
Capture loyalty relationships: Person -[OWNS]-> Vehicle, Vehicle -[HAS]-> LicenseNumber, Person -[MEMBER_OF]-> LoyaltyPlan, Person -[GAVE_CONSENT]-> Consent -[TO_APP]-> Application, Person -[HAS]-> CreditCard.
{
"relationships": [
{
"source": {
"external_id": "ole",
"type": "Person"
},
"target": {
"external_id": "cb2563",
"type": "PaymentMethod"
},
"type": "HAS"
},
{
"source": {
"external_id": "ole",
"type": "Person"
},
"target": {
"external_id": "carOle",
"type": "Car"
},
"type": "OWNS"
},
{
"source": {
"external_id": "ole",
"type": "Person"
},
"target": {
"external_id": "loyalty1",
"type": "Loyalty"
},
"type": "IS_MEMBER"
},
{
"source": {
"external_id": "alice",
"type": "Person"
},
"target": {
"external_id": "loyalty1",
"type": "Loyalty"
},
"type": "IS_MEMBER"
},
{
"source": {
"external_id": "ole",
"type": "Person"
},
"target": {
"external_id": "consent1",
"type": "ConsentPayment"
},
"type": "GRANTED"
},
{
"source": {
"external_id": "carOle",
"type": "Car"
},
"target": {
"external_id": "licenseOle",
"type": "LicenseNumber"
},
"type": "HAS"
},
{
"source": {
"external_id": "consent1",
"type": "ConsentPayment"
},
"target": {
"external_id": "cb2563",
"type": "PaymentMethod"
},
"type": "GRANTED"
},
{
"source": {
"external_id": "companyParking",
"type": "Company"
},
"target": {
"external_id": "applicationParking",
"type": "Application"
},
"type": "OWNS"
},
{
"source": {
"external_id": "applicationParking",
"type": "Application"
},
"target": {
"external_id": "consent1",
"type": "ConsentPayment"
},
"type": "USES"
}
]
}Step 2a
Policy JSON with multi-condition authorization: (1) license plate lookup, (2) loyalty plan consistency check, (3) consent validation with expiration check. Returns READ access to CreditCard.external_id when all conditions pass.
{
"meta": {
"policy_version": "1.0-ciq"
},
"subject": {
"type": "_Application"
},
"condition": {
"cypher": "MATCH (subject:_Application) MATCH (app:Application)-[:USES]->(consentpayment:ConsentPayment)<-[:GRANTED]-(person:Person)-[:HAS]->(paymentmethod:PaymentMethod) MATCH (person)-[:IS_MEMBER]->(loyalty:Loyalty) MATCH (person)-[:OWNS]->(car:Car)-[:HAS]->(ln:LicenseNumber)",
"filter": [
{
"operator": "AND",
"operands": [
{
"attribute": "app.external_id",
"operator": "=",
"value": "$app_external_id"
},
{
"attribute": "subject.external_id",
"operator": "=",
"value": "$_appId"
}
]
}
]
},
"allowed_reads": {
"nodes": [
"ln.*",
"app.*",
"paymentmethod.external_id"
]
}
}Step 2b
POST request to create the loyalty authorization 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 (app:Application)-[:USES]->(consentpayment:ConsentPayment)<-[:GRANTED]-(person:Person)-[:HAS]->(paymentmethod:PaymentMethod) MATCH (person)-[:IS_MEMBER]->(loyalty:Loyalty) MATCH (person)-[:OWNS]->(car:Car)-[:HAS]->(ln:LicenseNumber)\",\"filter\":[{\"operator\":\"AND\",\"operands\":[{\"attribute\":\"app.external_id\",\"operator\":\"=\",\"value\":\"$app_external_id\"},{\"attribute\":\"subject.external_id\",\"operator\":\"=\",\"value\":\"$_appId\"}]}]},\"allowed_reads\":{\"nodes\":[\"ln.*\",\"app.*\",\"paymentmethod.external_id\"]}}",
"status": "ACTIVE",
"tags": []
}Step 2c
GET request to verify the policy was created.
{
"id": "your_policy_configuration_gid"
}Step 3a
Query JSON that takes $licensePlate as input parameter, traverses the loyalty graph, and returns CreditCard.external_id for authorized requests.
{
"nodes": [
"paymentmethod.external_id"
],
"filter": {
"attribute": "ln.property.number",
"operator": "=",
"value": "$license"
}
}Step 3b
POST request to create the loyalty 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\":[\"paymentmethod.external_id\"],\"filter\":{\"attribute\":\"ln.property.number\",\"operator\":\"=\",\"value\":\"$license\"}}",
"status": "ACTIVE"
}Step 3c
GET request to verify the query was created.
{
"id": "your_knowledge_query_configuration_gid"
}Step 4a
Execute the loyalty query with a license plate value. The system checks all authorization conditions before returning the credit card ID.
{
"id": "knowledge_query_gid",
"input_params": {
"license": "AL98745",
"app_external_id": "applicationParking"
}
}Step 4b
Response containing the credit card external_id. Empty result if authorization conditions are not met (e.g., expired consent, inconsistent loyalty plans).
{
"data": [
{
"nodes": {
"paymentmethod.external_id": "cb2563"
}
}
]
}Step 5a
DELETE request to remove the query.
{
"id": "your_knowledge_query_configuration_gid"
}Step 5b
DELETE request to remove the policy.
{
"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