POST /v1/validate
Core validation endpoint — validates a tool call against policies.
The validation endpoint is the primary API for tool call validation. In cloud mode, the SDK calls this endpoint for every tool call that can't be resolved locally.
As of SDK v1.4.0, deterministic policies are cached client-side. When the SDK has a fresh cached policy, validation runs locally (~1-5ms) and this endpoint is not called. Decisions from local validation are logged asynchronously via POST /v1/decisions.
Request
POST /v1/tools/validateHeaders
| Header | Required | Description |
|---|---|---|
X-Veto-API-Key | Yes | API key for authentication |
Content-Type | Yes | application/json |
Body
{
"tool_name": "send_email",
"arguments": {
"to": "user@example.com",
"subject": "Hello",
"body": "..."
}
}| Field | Type | Required | Description |
|---|---|---|---|
tool_name | string | Yes | Name of the tool being called |
arguments | object | Yes | Arguments passed to the tool |
context | object | No | Additional metadata (call_id, session_id, etc.) |
Response
Allowed
{
"decision": "allow",
"latency_ms": 45
}Denied
{
"decision": "deny",
"reason": "Rule limit-transfers: amount 5000 exceeds limit of 1000",
"failed_constraints": [
{
"parameter": "amount",
"constraint_type": "range",
"expected": 1000,
"actual": 5000,
"message": "amount 5000 exceeds maximum of 1000"
}
],
"latency_ms": 12
}Requires approval
{
"decision": "require_approval",
"reason": "This tool call requires human review",
"approval_id": "apr_abc123def456",
"latency_ms": 30
}When the SDK receives require_approval, it automatically begins polling GET /v1/approvals/:id until the approval is resolved. See Approvals.
Response fields
| Field | Type | Description |
|---|---|---|
decision | "allow" | "deny" | "require_approval" | Validation result |
reason | string? | Explanation when denied or escalated |
failed_constraints | array? | Details of constraint violations |
approval_id | string? | Approval record ID (only with require_approval) |
metadata | object? | Additional metadata from the server |
latency_ms | number | Server-side processing time |
Authentication
The API key is created in the Veto dashboard or via the POST /v1/api-keys endpoint. Each key is scoped to an organization and project.
curl -X POST https://api.runveto.com/v1/tools/validate \
-H "X-Veto-API-Key: veto_abc123..." \
-H "Content-Type: application/json" \
-d '{
"tool_name": "transfer_funds",
"arguments": { "amount": 500, "to": "vendor-123" }
}'Rate limiting
The endpoint is rate-limited per API key. Default limits:
| Plan | Requests/min |
|---|---|
| Free | 60 |
| Team | 600 |
| Business | 600 |
| Enterprise | Custom |
Rate limit headers are included in every response:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1706140800