Back to all resources
KBAC KBAC Python

KBAC: Batch Authorization with Multiple Evaluations (Boxcarring)

Evaluate multiple authorization decisions in a single API call using the authZEN Access Evaluations endpoint. This pattern, known as 'boxcarring', reduces network overhead when checking many permissions at once.

KBAC: Batch Authorization with Multiple Evaluations (Boxcarring)

This example demonstrates batch authorization using the authZEN Access Evaluations API:

What is boxcarring?

Multiple authorization questions combined into a single API request, reducing network round-trips.

Example batch request:

- "Can Alice drive Car1?"

- "Can Alice ride Bus1?"

- "Can Bob drive Car1?"

All answered in ONE API call.

API reference: https://openid.net/specs/authorization-api-1_0-03.html#name-access-evaluations-api

Request structure:

- Default subject/action can be set at the top level

- Each evaluation in the array can override defaults

- Response contains decision for each evaluation in order

Use case

Scenario: A transportation app needs to check multiple permissions when a user opens the app.

Policies defined:

1. DRIVE policy: Person can DRIVE Car if DRIVES relationship exists

2. RIDE policy: Person can RIDE Bus if HAS_TICKET relationship exists

Single batch request checks:

- Can Alice drive Car1? (uses DRIVE policy)

- Can Alice drive Car2? (uses DRIVE policy)

- Can Alice ride Bus1? (uses RIDE policy)

Response (in order):

- {decision: true}

- {decision: false}

- {decision: true}

Performance benefit: 3 authorization decisions with 1 API call instead of 3.

ikg

Requirements

Prerequisites:

- ServiceAccount credentials: For creating policies (Bearer token)

- AppAgent credentials: For data ingestion and authorization queries (X-IK-ClientKey)

Required API access:

- POST /capture/v1/nodes/ and /capture/v1/relationships/ (graph data)

- POST /configs/v1/authorization-policies (create policies - called twice)

- POST /access/v1/evaluations (batch evaluation endpoint - note plural)

Steps

Step 1: Ingest Graph Data

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

- Action: POST nodes (Person, Car, Bus) and relationships (DRIVES, HAS_TICKET)

- Result: Graph ready for authorization queries

Step 2: Create Multiple KBAC Policies

- Authentication: ServiceAccount credential (Bearer token)

- Action: POST DRIVE policy (Person -[DRIVES]-> Car = can drive)

- Action: POST RIDE policy (Person -[HAS_TICKET]-> Bus = can ride)

- Result: Two policy IDs returned

Step 3: Run Batch Evaluation

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

- Action: POST to /access/v1/evaluations (plural) with array of checks

- Request format:

{

subject: {type: "Person", id: "alice"}, // default subject

evaluations: [

{action: {name: "drive"}, resource: {type: "Car", id: "car1"}},

{action: {name: "drive"}, resource: {type: "Car", id: "car2"}},

{action: {name: "ride"}, resource: {type: "Bus", id: "bus1"}}

]

}

- Result: Array of decisions matching input order

Step 5: Cleanup

- Action: DELETE both 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": "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"
        }
      ]
    }
  ]
}

Capture the relationships needed for this use case.

POST https://eu.api.indykite.com/capture/v1/relationships/Json
{
  "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 2

KBAC Policy which rules that a Person node can drive a car if the Person node has a relation DRIVES with a car in json format.

policy.jsonJson
{
  "meta": {
    "policy_version": "2.0-kbac"
  },
  "subject": {
    "type": "Person"
  },
  "actions": [
    "CAN_DRIVE"
  ],
  "resource": {
    "type": "Car"
  },
  "condition": {
    "cypher": "MATCH (subject:Person)-[:DRIVES]->(resource:Car)"
  }
}

Request to create the KBAC 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\":\"2.0-kbac\"},\"subject\":{\"type\":\"Person\"},\"actions\":[\"CAN_DRIVE\"],\"resource\":{\"type\":\"Car\"},\"condition\":{\"cypher\":\"MATCH (subject:Person)-[:DRIVES]->(resource:Car)\"}}",
  "status": "ACTIVE",
  "tags": []
}

Request to create the KBAC Policy configuration using Python.

policy_request.pyPython

import http.client

conn = http.client.HTTPSConnection("eu.api.indykite.com")

payload = "{"description": "",
  "display_name": "",
  "name": "",
  "policy": "",
  "project_id": "",
  "status": "ACTIVE",
  "tags": [
    ""
  ]}"
headers = {
    'Content-Type': "application/json",
    'Authorization': "YOUR_SECRET_TOKEN"
}

conn.request("POST", "/configs/v1/authorization-policies", payload, headers)
res = conn.getresponse()
data = res.read()

Request to read the KBAC Policy configuration using REST

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

Request to read the KBAC Policy configuration using Python.

policy_request.pyPython

import http.client

conn = http.client.HTTPSConnection("eu.api.indykite.com")
headers = { 'Authorization': "YOUR_SECRET_TOKEN" }
conn.request("GET", "/configs/v1/authorization-policies/{{id}}", headers=headers)
res = conn.getresponse()
data = res.read()

KBAC Policy which rules that a Person node can ride a bus if the Person node has a ticket for the bus in json format.

policy.jsonJson
{
  "meta": {
    "policy_version": "2.0-kbac"
  },
  "subject": {
    "type": "Person"
  },
  "actions": [
    "CAN_RIDE"
  ],
  "resource": {
    "type": "Bus"
  },
  "condition": {
    "cypher": "MATCH (subject)-[:HAS]->(ticket:Ticket)-[:FOR]->(resource)"
  }
}

Request to create the KBAC 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\":\"2.0-kbac\"},\"subject\":{\"type\":\"Person\"},\"actions\":[\"CAN_RIDE\"],\"resource\":{\"type\":\"Bus\"},\"condition\":{\"cypher\":\"MATCH (subject)-[:HAS]->(ticket:Ticket)-[:FOR]->(resource)\"}}",
  "status": "ACTIVE",
  "tags": []
}

Request to create the KBAC Policy configuration using Python.

policy_request.pyPython

import http.client

conn = http.client.HTTPSConnection("eu.api.indykite.com")

payload = "{"description": "",
  "display_name": "",
  "name": "",
  "policy": "",
  "project_id": "",
  "status": "ACTIVE",
  "tags": [
    ""
  ]}"
headers = {
    'Content-Type': "application/json",
    'Authorization': "YOUR_SECRET_TOKEN"
}

conn.request("POST", "/configs/v1/authorization-policies", payload, headers)
res = conn.getresponse()
data = res.read()

Request to read the KBAC Policy configuration using REST.

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

Request to read the KBAC Policy configuration using Python.

policy_request.pyPython

import http.client

conn = http.client.HTTPSConnection("eu.api.indykite.com")
headers = { 'Authorization': "YOUR_SECRET_TOKEN" }
conn.request("GET", "/configs/v1/authorization-policies/{{id}}", headers=headers)
res = conn.getresponse()
data = res.read()

Step 3

Json to run KBAC access multi-evaluations.

The elements outside evaluations are the default values.

Here we have a default value for subject and for action.

If a top-level key is designated in the evaluations array then the value of that will take precedence over the default value.

POST https://eu.api.indykite.com/access/v1/evaluationsJson
{
  "subject": {
    "type": "Person",
    "id": "karel"
  },
  "action": {
    "name": "CAN_DRIVE"
  },
  "evaluations": [
    {
      "subject": {
        "type": "Person",
        "id": "knightrider"
      },
      "resource": {
        "type": "Car",
        "id": "kitt"
      }
    },
    {
      "subject": {
        "type": "Person",
        "id": "knightrider"
      },
      "resource": {
        "type": "Car",
        "id": "caddilacv16"
      }
    },
    {
      "resource": {
        "type": "Bus",
        "id": "harmonika"
      },
      "action": {
        "name": "CAN_RIDE"
      }
    },
    {
      "resource": {
        "type": "Bus",
        "id": "harmonika"
      }
    }
  ]
}

Response to the KBAC Evaluations endpoint request.

Response 200Json
{
  "evaluations": [
    {
      "decision": true
    },
    {
      "decision": false
    },
    {
      "decision": true
    },
    {
      "decision": false
    }
  ]
}

Request to run the KBAC Evaluations endpoint.

evaluations.pyPython

import http.client

conn = http.client.HTTPSConnection("eu.api.indykite.com")

payload = "{
    "subject": {"type": "Person",
        "id": "karel"}, 
    "action": {"name": "CAN_DRIVE"},
    "evaluations": [
        {
          	"subject": {"type": "Person",
                "id": "knightrider"}, 
            "resource": {"type": "Car",
                "id": "kitt"}
        },
        {
          	"subject": {"type": "Person",
                "id": "knightrider"}, 
            "resource": {"type": "Car",
                "id": "caddilacv16"}
        },
        {
          	"resource": {"type": "Bus",
                "id": "harmonika"},
            "action": {"name": "CAN_RIDE"}
        },
        {
          	"resource": {"type": "Bus",
                "id": "harmonika"}
        }
    ]
}"

headers = {
    'Content-Type': "application/json",
    'X-IK-ClientKey': ""
}

conn.request("POST", "/access/v1/evaluations", payload, headers)

res = conn.getresponse()
data = res.read()

Step 5

Delete the KBAC Policies.

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

Request to delete the KBAC Policies.

del.pyPython

import http.client

conn = http.client.HTTPSConnection("eu.api.indykite.com")

headers = { 'Authorization': "Bearer ...", 'Content-Type': "application/json" }

conn.request("DELETE", "/configs/v1/authorization-policies/{id}", headers=headers)

res = conn.getresponse()
data = res.read()

API Endpoints

/capture/v1/nodes
/capture/v1/relationships
/configs/v1/authorization-policies
/kbac/v1/is-authorized
View OpenAPI docs

Tags

KBAC Policy authZEN Batch Evaluation Boxcarring Multi-Evaluation Performance Optimization