curl --request POST \
--url https://api.kordio.io/control/v1/agent/actions/simulate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"budget_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"action_type": "payment.create",
"resource": "acme-supplies.example",
"cost_cents": 0,
"metadata": {},
"trace_id": "<string>"
}
'import requests
url = "https://api.kordio.io/control/v1/agent/actions/simulate"
payload = {
"budget_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"action_type": "payment.create",
"resource": "acme-supplies.example",
"cost_cents": 0,
"metadata": {},
"trace_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
budget_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
action_type: 'payment.create',
resource: 'acme-supplies.example',
cost_cents: 0,
metadata: {},
trace_id: '<string>'
})
};
fetch('https://api.kordio.io/control/v1/agent/actions/simulate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.kordio.io/control/v1/agent/actions/simulate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'budget_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'action_type' => 'payment.create',
'resource' => 'acme-supplies.example',
'cost_cents' => 0,
'metadata' => [
],
'trace_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.kordio.io/control/v1/agent/actions/simulate"
payload := strings.NewReader("{\n \"budget_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"action_type\": \"payment.create\",\n \"resource\": \"acme-supplies.example\",\n \"cost_cents\": 0,\n \"metadata\": {},\n \"trace_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.kordio.io/control/v1/agent/actions/simulate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"budget_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"action_type\": \"payment.create\",\n \"resource\": \"acme-supplies.example\",\n \"cost_cents\": 0,\n \"metadata\": {},\n \"trace_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kordio.io/control/v1/agent/actions/simulate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"budget_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"action_type\": \"payment.create\",\n \"resource\": \"acme-supplies.example\",\n \"cost_cents\": 0,\n \"metadata\": {},\n \"trace_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"outcome": "allowed",
"rule": "per_transaction_cap",
"detail": {},
"headroom": {},
"policy_snapshot": [
{}
],
"policy_version": "pv_8f2c1d0a4b6e93571ac2e8d045f7b312",
"frame_hash": "fh_1b9a0c7e5d2f483610badc0ffee1234567890abcdef1234567890abcdef123456",
"remedy": {
"kind": "lower_amount",
"summary": "A per-action cap applies. Retry at $100.00 or less.",
"max_cents": 123,
"retry_after_seconds": 123,
"resource": "<string>",
"action_type": "<string>"
}
}
}{
"error": {
"message": "Agent key is required",
"code": "runtime_key_required"
}
}{
"error": {
"message": "<string>",
"code": "runtime_key_required"
}
}{
"error": {
"message": "Rate limit exceeded",
"code": "rate_limited"
}
}Runs the same evaluation and records nothing: no intent, no reservation, no budget
consumed. Always 200, whatever the outcome.
Use it in tests, and in your own UI to show someone what a policy would do before
they save it. Note that a simulation does write an action.simulated audit event,
so simulations are still visible in the trail.
curl --request POST \
--url https://api.kordio.io/control/v1/agent/actions/simulate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"budget_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"action_type": "payment.create",
"resource": "acme-supplies.example",
"cost_cents": 0,
"metadata": {},
"trace_id": "<string>"
}
'import requests
url = "https://api.kordio.io/control/v1/agent/actions/simulate"
payload = {
"budget_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"action_type": "payment.create",
"resource": "acme-supplies.example",
"cost_cents": 0,
"metadata": {},
"trace_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
budget_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a',
action_type: 'payment.create',
resource: 'acme-supplies.example',
cost_cents: 0,
metadata: {},
trace_id: '<string>'
})
};
fetch('https://api.kordio.io/control/v1/agent/actions/simulate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.kordio.io/control/v1/agent/actions/simulate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'budget_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a',
'action_type' => 'payment.create',
'resource' => 'acme-supplies.example',
'cost_cents' => 0,
'metadata' => [
],
'trace_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.kordio.io/control/v1/agent/actions/simulate"
payload := strings.NewReader("{\n \"budget_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"action_type\": \"payment.create\",\n \"resource\": \"acme-supplies.example\",\n \"cost_cents\": 0,\n \"metadata\": {},\n \"trace_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.kordio.io/control/v1/agent/actions/simulate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"budget_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"action_type\": \"payment.create\",\n \"resource\": \"acme-supplies.example\",\n \"cost_cents\": 0,\n \"metadata\": {},\n \"trace_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.kordio.io/control/v1/agent/actions/simulate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"budget_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\",\n \"action_type\": \"payment.create\",\n \"resource\": \"acme-supplies.example\",\n \"cost_cents\": 0,\n \"metadata\": {},\n \"trace_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"outcome": "allowed",
"rule": "per_transaction_cap",
"detail": {},
"headroom": {},
"policy_snapshot": [
{}
],
"policy_version": "pv_8f2c1d0a4b6e93571ac2e8d045f7b312",
"frame_hash": "fh_1b9a0c7e5d2f483610badc0ffee1234567890abcdef1234567890abcdef123456",
"remedy": {
"kind": "lower_amount",
"summary": "A per-action cap applies. Retry at $100.00 or less.",
"max_cents": 123,
"retry_after_seconds": 123,
"resource": "<string>",
"action_type": "<string>"
}
}
}{
"error": {
"message": "Agent key is required",
"code": "runtime_key_required"
}
}{
"error": {
"message": "<string>",
"code": "runtime_key_required"
}
}{
"error": {
"message": "Rate limit exceeded",
"code": "rate_limited"
}
}Authorizations
An agent API key, krt_live_... or krt_test_..., shown exactly once at creation. Kordio stores only a digest. This credential can ask for authorization and can never write policy.
Body
An active session belonging to this agent.
Lowercase, dot separated.
^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$"payment.create"
The counterparty or target. Matched by allowlists.
"acme-supplies.example"
Minor units. Omit or 0 for an action that spends nothing.
x >= 0Any dot path here is addressable from the condition language as metadata.*.
Yours if you have one, generated otherwise. Links the whole audit trail.
Response
The decision that would have been produced. No id, because no intent exists.
Show child attributes
Show child attributes