Decisions API
Query, aggregate, and log validation decisions — the audit trail for every tool call.
Every tool call validated by Veto produces a decision record. These endpoints let you query, aggregate, and log decisions.
GET /v1/decisions
List decisions with pagination and filtering.
Headers
| Header | Required | Description |
|---|---|---|
X-Veto-API-Key or Authorization | Yes | API key or Bearer JWT |
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Results per page (1–100) |
offset | number | 0 | Skip this many results |
projectId | string (UUID) | — | Filter by project |
toolName | string | — | Filter by tool name |
decision | "allow" | "deny" | — | Filter by decision |
startDate | ISO 8601 date | — | Filter from this date |
endDate | ISO 8601 date | — | Filter until this date |
Response
{
"data": [
{
"id": "d7f2a1b3-4c5e-6f78-9a0b-1c2d3e4f5a6b",
"toolName": "transfer_funds",
"arguments": { "amount": 500, "to": "vendor-123" },
"context": { "session_id": "sess_abc123", "source": "client" },
"decision": "allow",
"mode": "deterministic",
"reason": "All constraints passed",
"failedArgument": null,
"matchedException": null,
"validations": null,
"latencyMs": 2,
"createdAt": "2025-01-15T10:30:00Z"
}
],
"pagination": {
"total": 1247,
"limit": 50,
"offset": 0,
"hasMore": true
}
}GET /v1/decisions/stats
Aggregated decision statistics over a time period.
Headers
| Header | Required | Description |
|---|---|---|
X-Veto-API-Key or Authorization | Yes | API key or Bearer JWT |
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
days | number | 7 | Lookback period (1–90) |
projectId | string (UUID) | — | Filter by project |
Response
{
"period": { "days": 7 },
"summary": {
"total": 1247,
"allowed": 1180,
"denied": 67,
"deterministic": 1100,
"llm": 147
},
"breakdown": [
{
"date": "2025-01-15",
"allowed": 180,
"denied": 12,
"deterministic": 160,
"llm": 32
}
]
}GET /v1/decisions/:id
Get a single decision by ID.
Headers
| Header | Required | Description |
|---|---|---|
X-Veto-API-Key or Authorization | Yes | API key or Bearer JWT |
Path parameters
| Parameter | Type | Description |
|---|---|---|
id | string (UUID) | Decision ID |
Response
Same shape as individual items in the GET /v1/decisions data array.
Errors
| Status | Description |
|---|---|
| 400 | Invalid UUID format |
| 404 | Decision not found |
POST /v1/decisions
Log a client-side validation decision. Keeps the dashboard audit trail complete when the SDK validates locally.
Called automatically by the SDK — you do not need to call this directly.
Headers
| Header | Required | Description |
|---|---|---|
X-Veto-API-Key | Yes | API key scoped to a project |
Content-Type | Yes | application/json |
Body
{
"tool_name": "transfer_funds",
"arguments": { "amount": 500, "to": "vendor-123" },
"decision": "allow",
"reason": "All constraints passed",
"mode": "deterministic",
"latency_ms": 2,
"source": "client",
"context": {
"session_id": "sess_abc123",
"agent_id": "agent_1"
}
}| Field | Type | Required | Description |
|---|---|---|---|
tool_name | string | Yes | Name of the tool that was validated |
arguments | object | Yes | Arguments that were validated |
decision | "allow" | "deny" | Yes | Validation result |
reason | string | No | Explanation of the decision |
mode | "deterministic" | Yes | Validation mode used |
latency_ms | number | Yes | Client-side validation time in milliseconds |
source | "client" | Yes | Must be "client" |
context | object | No | Additional metadata (session_id, agent_id, etc.) |
Response (201)
{
"success": true,
"id": "d7f2a1b3-4c5e-6f78-9a0b-1c2d3e4f5a6b"
}Errors
| Status | Code | Description |
|---|---|---|
| 400 | missing_project | API key must be scoped to a project |
Rate limiting
120 requests per 60 seconds per API key.
SDK behavior
The SDK calls POST /v1/decisions automatically after every client-side deterministic validation. The call is fire-and-forget — errors are silently swallowed so they never block tool execution.
Both TypeScript and Python SDKs use the same behavior:
// TypeScript — called internally by tryLocalDeterministic()
client.logDecision({
tool_name: 'send_email',
arguments: { to: 'user@example.com' },
decision: 'allow',
mode: 'deterministic',
latency_ms: 2,
source: 'client',
});# Python — called internally by try_local_deterministic()
client.log_decision({
"tool_name": "send_email",
"arguments": {"to": "user@example.com"},
"decision": "allow",
"mode": "deterministic",
"latency_ms": 2,
"source": "client",
})Decisions logged via this endpoint appear in the dashboard alongside server-side decisions. They are marked with source: "client" in the context field.