Skip to content

Execution API

These execution endpoints evaluate policy rules and stored resources against JSON data and return the result.

All execution endpoints require a valid API key via the x-api-key header. The key must have at least view scope.

x-api-key: <your-api-key>

When you use an organization-owned API key, the orchestrator resolves tenant context from the key automatically.

Scope checks are enforced by the orchestrator. If the policy engine cannot be reached, authorization fails closed and execution is denied.

POST https://api.policy2.net/run
FieldTypeRequiredDescription
rulestringYesThe policy rule text
dataobjectYesJSON data to evaluate against
Terminal window
curl -X POST https://api.policy2.net/run \
-H "Content-Type: application/json" \
-H "x-api-key: pk_live_example" \
-d '{
"rule": "A **Person** gets approved if __age__ of **Person** is greater than 18.",
"data": {
"Person": { "age": 25 }
}
}'

The API returns a JSON object with the evaluation result:

{
"result": true,
"trace": {
"execution": [
{
"conditions": [
{
"evaluation_details": {
"comparison_result": true,
"left_value": { "type": "number", "value": 25 },
"right_value": { "type": "number", "value": 18 }
},
"operator": "GreaterThan",
"property": { "path": "$.Person.age", "value": 25 },
"result": true,
"selector": { "value": "Person" },
"value": { "type": "number", "value": 18 }
}
],
"outcome": { "value": "approved" },
"result": true,
"selector": { "value": "Person" }
}
]
},
"rule": [
"A **Person** gets approved if __age__ of **Person** is greater than 18."
],
"data": {
"Person": { "age": 25 }
},
"error": null,
"labels": null,
"execution": {
"orchestrator": { "go": "288883", "database": "0", "total": "288883" },
"engine": "7047632",
"total": "7336607"
}
}
FieldTypeDescription
resultbooleanWhether the policy passed (true) or failed (false)
traceobjectExecution trace with detailed condition evaluation
rulestring[]The rule(s) that were evaluated
dataobjectThe data that was evaluated against
errorstring | nullError message if the rule failed to parse, null on success
labelsobject | nullLabels associated with the rule, if any
executionobjectTiming information for the evaluation (in nanoseconds)

If the rule text is invalid or the data is missing required fields, the API returns an error:

{
"result": false,
"error": "Parse error: unexpected token at line 1"
}

Common errors:

  • Parse error — the rule syntax is invalid
  • Missing selector — the data doesn’t contain the referenced selector
  • Missing property — the data doesn’t contain the referenced property

Interactive Example

Policy Rule
Test Data (JSON)

Send multiple rules in a single request. The API evaluates all rules and returns the result of the last rule (the golden rule):

Terminal window
curl -X POST https://api.policy2.net/run \
-H "Content-Type: application/json" \
-H "x-api-key: pk_live_example" \
-d '{
"rule": "A **user** passes age check if __age__ of **user** is at least 18.\n\nA **user** is eligible if the **user** passes age check.",
"data": { "user": { "age": 25 } }
}'

If a policy has been saved through the API, you can execute it by ID instead of sending rule text. Only the data field is required because the API resolves the policy for execution.

Policies are versioned, so there are two ID forms:

  • POST https://api.policy2.net/run/policy/{baseId} uses the base policy ID and resolves to the latest versioned policy, or the draft if no version exists yet.
  • POST https://api.policy2.net/run/policy_version/{policyId} uses the policy version or draft ID directly.

Execution still passes through API access rules:

  • the caller must be allowed to see the stored resource
  • if the base policy has been soft-deleted, execution is denied even when using an exact policyId

Execute a Specific Policy Version or Draft

Section titled “Execute a Specific Policy Version or Draft”

Use the policy record ID when you want to run an exact version or a draft.

Terminal window
curl -X POST https://api.policy2.net/run/policy_version/10759e44-6cad-4eb3-a1e1-9655ced50a76 \
-H "Content-Type: application/json" \
-H "x-api-key: pk_live_example" \
-d '{
"data": {
"drivingTest": {
"person": {
"name": "Bob",
"dateOfBirth": "1990-01-01"
},
"scores": {
"theory": {
"multipleChoice": 45,
"hazardPerception": 75
},
"practical": {
"major": false,
"minor": 13
}
},
"testDates": {
"theory": {
"date": "2026-01-11T11:29:00.594Z",
"center": "Coventry"
},
"practical": {
"date": "2026-01-11T11:31:00.002Z",
"center": "Manchester"
}
}
}
}
}'

Execute the Current Version for a Base Policy

Section titled “Execute the Current Version for a Base Policy”

Use the base policy ID when you want the API to resolve the current executable policy automatically.

Terminal window
curl -X POST https://api.policy2.net/run/policy/3b7d4b2a-9aa0-4b6d-a1b4-9dcf11ce12ab \
-H "Content-Type: application/json" \
-H "x-api-key: pk_live_example" \
-d '{
"data": {
"drivingTest": {
"person": {
"name": "Bob",
"dateOfBirth": "1990-01-01"
},
"scores": {
"theory": {
"multipleChoice": 45,
"hazardPerception": 75
},
"practical": {
"major": false,
"minor": 13
}
},
"testDates": {
"theory": {
"date": "2026-01-11T11:29:00.594Z",
"center": "Coventry"
},
"practical": {
"date": "2026-01-11T11:31:00.002Z",
"center": "Manchester"
}
}
}
}
}'

Flows execute with the same input data model as policies: you send one JSON payload, and each node in the flow evaluates that data in its own way.

Flows are also versioned, so there are two ID forms:

  • POST https://api.policy2.net/run/flow/{baseId} uses the base flow ID and resolves to the latest versioned flow, or the draft if no version exists yet.
  • POST https://api.policy2.net/run/flow_version/{flowId} uses the flow version or draft ID directly.

As with policies:

  • the caller must have access to the stored flow
  • if the base flow has been soft-deleted, execution is denied even when using an exact flowId
Terminal window
curl --request POST \
--url https://api.policy2.net/run/flow_version/9745d7ba-c96c-435e-a97a-dea7db645b74 \
--header 'content-type: application/json' \
--header 'x-api-key: pk_live_example' \
--data '{
"drivingTest": {
"person": {
"dateOfBirth": "1990-01-01",
"name": "Bob"
},
"scores": {
"practical": {
"major": false,
"minor": 13
},
"theory": {
"hazardPerception": 75,
"multipleChoice": 45
}
},
"testDates": {
"practical": {
"center": "Manchester",
"date": "2026-02-11T10:31:00.002Z"
},
"theory": {
"center": "Coventry",
"date": "2026-01-11T10:29:00.594Z"
}
}
}
}'
{
"nodeId": "start-1",
"nodeName": "Start",
"result": true,
"executionPath": [],
"finalOutcome": true,
"errors": [],
"nodeResponses": [
{
"nodeId": "start-1",
"nodeType": "start",
"response": {
"result": true,
"trace": { "execution": ["..."] },
"rule": ["# Driving Test Example", "..."],
"data": { "drivingTest": { "..." : "..." } },
"error": null,
"labels": null
},
"execution": {
"database": "215016798",
"engine": "145541065",
"total": "360782263"
}
}
]
}

The response format is identical to the inline rule endpoint:

{
"result": false,
"trace": {
"execution": [
{
"conditions": [
{
"referenced_rule_outcome": "the age test",
"result": true,
"rule_name": "passes the age test",
"selector": { "value": "driver" }
},
{
"referenced_rule_outcome": "the test requirements",
"result": true,
"rule_name": "passes the test requirements",
"selector": { "value": "driver" }
},
{
"referenced_rule_outcome": "taken the test in the time period",
"result": false,
"rule_name": "has taken the test in the time period",
"selector": { "value": "driver" }
},
{
"referenced_rule_outcome": "did their test at a valid center",
"result": true,
"rule_name": "did their test at a valid center",
"selector": { "value": "driver" }
}
],
"outcome": { "value": "a driving licence" },
"result": false,
"selector": { "value": "driver" }
}
]
},
"rule": [
"# Driving Test Example",
"",
"A **driver** gets a driving licence",
" if the **driver** passes the age test",
" and the **driver** passes the test requirements",
" and the **driver** has taken the test in the time period",
" and the **driver** did their test at a valid center."
],
"data": {
"drivingTest": {
"person": { "dateOfBirth": "1990-01-01", "name": "Bob" },
"scores": {
"practical": { "major": false, "minor": 13 },
"theory": { "hazardPerception": 75, "multipleChoice": 45 }
},
"testDates": {
"practical": { "center": "Manchester", "date": "2026-01-11T11:31:00.002Z" },
"theory": { "center": "Coventry", "date": "2026-01-11T11:29:00.594Z" }
}
}
},
"error": null,
"labels": null,
"execution": {
"orchestrator": { "go": "722743", "database": "164656209", "total": "165378952" },
"engine": "3383943",
"total": "168763084"
}
}

The response includes only the golden rule (top-level rule) in the trace. The result is false here because the practical test date is outside the 30-day window required by the policy.