Admin SDK
Full API reference for the VetoAdmin management client — programmatic control over policies, decisions, approvals, tools, API keys, and more.
Overview
VetoAdmin is a management client for controlling your entire Veto setup programmatically. While the core Veto class handles runtime validation (wrapping tools, guarding calls), VetoAdmin talks to the Veto management API to create policies, review decisions, resolve approvals, manage MCP upstreams, rotate API keys, and stream events.
All requests are authenticated with your API key via the X-Veto-API-Key header.
Installation
npm install veto-sdkConstructor
import { VetoAdmin } from 'veto-sdk';
const admin = new VetoAdmin({
apiKey: 'veto_abc123...',
});Options
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Required. Your Veto API key |
baseUrl | string | "https://api.veto.so" | API base URL (for self-hosted deployments) |
timeout | number | 30000 | Request timeout in milliseconds |
const admin = new VetoAdmin({
apiKey: 'veto_abc123...',
baseUrl: 'https://veto.internal.corp.com',
timeout: 10_000,
});Policies
Full CRUD over tool policies, plus activation control and bulk export.
listPolicies(opts?)
const policies = await admin.listPolicies();
// Filter by project
const projectPolicies = await admin.listPolicies({ projectId: 'proj_abc' });Returns Policy[].
getPolicy(toolName)
const policy = await admin.getPolicy('send_email');Returns a Policy:
interface Policy {
_id: string;
toolName: string;
mode: 'deterministic' | 'llm';
version: number;
isActive: boolean;
constraints?: Constraint[];
outputRules?: OutputRule[];
llmConfig?: LlmConfig;
sessionConstraints?: SessionConstraints;
projectId?: string;
createdAt: string;
}createPolicy(input)
const policy = await admin.createPolicy({
toolName: 'wire_transfer',
mode: 'deterministic',
constraints: [
{ argumentName: 'amount', enabled: true, maximum: 10_000, action: 'deny' },
{ argumentName: 'recipient', enabled: true, enum: ['vendor-a', 'vendor-b'] },
],
});updatePolicy(toolName, input)
const updated = await admin.updatePolicy('wire_transfer', {
mode: 'deterministic',
constraints: [
{ argumentName: 'amount', enabled: true, maximum: 50_000, action: 'require_approval' },
],
});deletePolicy(toolName)
await admin.deletePolicy('wire_transfer');activatePolicy(toolName) / deactivatePolicy(toolName)
Toggle a policy on or off without deleting it.
await admin.deactivatePolicy('send_email');
// ... later
await admin.activatePolicy('send_email');exportPolicies(opts?)
Export all policies as a string (JSON or YAML).
const json = await admin.exportPolicies();
const yaml = await admin.exportPolicies({ format: 'yaml' });
const projectExport = await admin.exportPolicies({ projectId: 'proj_abc', format: 'json' });Decisions
Query the audit log of validation decisions. Supports pagination, filtering, aggregation, and export.
listDecisions(query?)
const result = await admin.listDecisions({
limit: 50,
offset: 0,
toolName: 'send_email',
decision: 'deny',
startDate: '2026-01-01',
endDate: '2026-03-31',
});
console.log(result.data); // Decision[]
console.log(result.pagination); // { total, limit, offset, hasMore }getDecision(id)
const decision = await admin.getDecision('dec_abc123');Returns a Decision:
interface Decision {
_id: string;
toolName: string;
arguments: Record<string, unknown>;
decision: 'allow' | 'deny' | 'require_approval';
mode: string;
reason?: string;
latencyMs: number;
createdAt: string;
}getDecisionStats(opts?)
const stats = await admin.getDecisionStats({
projectId: 'proj_abc',
startDate: '2026-01-01',
endDate: '2026-03-31',
});
// { total: 1200, allowed: 1050, denied: 130, requireApproval: 20 }exportDecisions(opts?)
const csv = await admin.exportDecisions({ format: 'csv', startDate: '2026-01-01' });
const json = await admin.exportDecisions({ format: 'json', projectId: 'proj_abc' });Approvals
List, inspect, and resolve human-in-the-loop approval requests.
listApprovals(opts?)
const all = await admin.listApprovals();
const denied = await admin.listApprovals({ status: 'denied' });listPendingApprovals()
Convenience method that returns only pending approvals.
const pending = await admin.listPendingApprovals();getApproval(id)
const approval = await admin.getApproval('apr_abc123');Returns an Approval:
interface Approval {
_id: string;
toolName: string;
arguments?: Record<string, unknown>;
status: 'pending' | 'approved' | 'denied' | 'expired';
expiresAt: string;
resolvedBy?: string;
resolvedAt?: string;
createdAt: string;
}resolveApproval(id, action, resolvedBy)
const resolved = await admin.resolveApproval('apr_abc123', 'approve', 'user@company.com');batchResolveApprovals(approvals)
Resolve multiple approvals in a single request.
const result = await admin.batchResolveApprovals([
{ id: 'apr_abc123', action: 'approve', resolvedBy: 'user@company.com' },
{ id: 'apr_def456', action: 'deny', resolvedBy: 'user@company.com' },
]);
for (const item of result.data) {
if (item.error) {
console.error(`Failed to resolve ${item.id}: ${item.error}`);
}
}Tools
Registered tool definitions. Tools are auto-registered when the SDK calls registerTools() during validation.
listTools()
const tools = await admin.listTools();Returns Tool[]:
interface Tool {
_id: string;
name: string;
description?: string;
arguments: Record<string, unknown>[];
}deleteTool(name)
await admin.deleteTool('deprecated_tool');Policy Drafts
AI-generated or manually created policy drafts that go through a review workflow before becoming active policies.
listPolicyDrafts(opts?)
const drafts = await admin.listPolicyDrafts();
const pending = await admin.listPolicyDrafts({ status: 'pending_review' });
const projectDrafts = await admin.listPolicyDrafts({ projectId: 'proj_abc' });createPolicyDraft(input)
const draft = await admin.createPolicyDraft({
name: 'email-sending-policy',
description: 'Restrict outbound email to verified domains',
rules: [
{ tool: 'send_email', constraint: 'regex', argument: 'to', value: '.*@company\\.com$' },
],
status: 'pending_review',
createdByAgentId: 'agent-7',
});getPolicyDraft(id)
const draft = await admin.getPolicyDraft('draft_abc123');Returns a PolicyDraft:
interface PolicyDraft {
_id: string;
name: string;
description?: string;
status: 'draft' | 'pending_review' | 'approved' | 'rejected';
createdByAgentId?: string;
rules: Record<string, unknown>[];
createdAt: string;
}approvePolicyDraft(id)
const approved = await admin.approvePolicyDraft('draft_abc123');rejectPolicyDraft(id, reason?)
const rejected = await admin.rejectPolicyDraft('draft_abc123', 'Too permissive on file access');MCP Gateway
Manage upstream MCP servers connected through the Veto gateway.
listUpstreams()
const upstreams = await admin.listUpstreams();Returns McpUpstream[]:
interface McpUpstream {
_id: string;
slug: string;
name: string;
transport: 'mcp-sse' | 'mcp-stdio';
url?: string;
command?: string;
enabled: boolean;
}createUpstream(input)
// SSE transport
const upstream = await admin.createUpstream({
name: 'Internal Tools Server',
transport: 'mcp-sse',
url: 'https://tools.internal.corp.com/sse',
timeoutMs: 15_000,
});
// Stdio transport
const local = await admin.createUpstream({
name: 'Local MCP Server',
transport: 'mcp-stdio',
command: 'npx',
args: ['-y', '@company/mcp-tools'],
});deleteUpstream(id)
await admin.deleteUpstream('ups_abc123');testUpstream(id)
Verify connectivity to an upstream server.
const result = await admin.testUpstream('ups_abc123');
if (result.status === 'ok') {
console.log(`Connected in ${result.latencyMs}ms`);
} else {
console.error(`Connection failed: ${result.error}`);
}Returns an UpstreamTestResult:
interface UpstreamTestResult {
status: 'ok' | 'error';
latencyMs?: number;
error?: string;
}API Keys
Manage API keys for your organization.
listApiKeys()
const keys = await admin.listApiKeys();Returns ApiKeyInfo[]:
interface ApiKeyInfo {
_id: string;
name: string;
keyPrefix: string;
isRevoked: boolean;
projectId?: string;
lastUsedAt?: string;
createdAt: string;
}createApiKey(input)
The full key is only returned once at creation time. Store it securely.
const created = await admin.createApiKey({
name: 'CI Pipeline Key',
projectId: 'proj_abc',
});
console.log(created.key); // "veto_abc123..." — save this, it won't be shown againReturns ApiKeyCreated:
interface ApiKeyCreated {
_id: string;
name: string;
key: string;
keyPrefix: string;
}revokeApiKey(id)
await admin.revokeApiKey('key_abc123');Events
Real-time event streaming over SSE. Two interfaces: callback-based and async iterable.
onEvent(type, callback)
Subscribe to events with a callback. Returns an EventSubscription with an unsubscribe() method.
const subscription = admin.onEvent('decision.created', (event) => {
console.log(`New decision: ${event.data.toolName} → ${event.data.decision}`);
});
// Listen for multiple event types
const sub = admin.onEvent(['decision.created', 'approval.resolved'], (event) => {
console.log(`${event.type}: ${JSON.stringify(event.data)}`);
});
// Stop listening
subscription.unsubscribe();subscribeEvents(opts?)
Async iterable interface for structured consumption. Works with for await...of.
for await (const event of admin.subscribeEvents({ types: ['decision.created'] })) {
console.log(event.type, event.data);
}Event shape:
interface VetoAdminEvent {
type: string;
data: Record<string, unknown>;
}Organizations and Projects
Read-only access to organization and project metadata scoped to your API key.
listOrganizations()
const orgs = await admin.listOrganizations();listProjects(opts?)
const projects = await admin.listProjects();
const filtered = await admin.listProjects({ organizationId: 'org_abc' });Error handling
All API errors throw a VetoAdminError with the HTTP status code attached.
import { VetoAdminError } from 'veto-sdk';
try {
await admin.getPolicy('nonexistent_tool');
} catch (error) {
if (error instanceof VetoAdminError) {
console.error(error.message); // "GET /policies/nonexistent_tool failed (404): ..."
console.error(error.statusCode); // 404
}
}Timeouts throw a VetoAdminError with statusCode: 0:
try {
await admin.listDecisions();
} catch (error) {
if (error instanceof VetoAdminError && error.statusCode === 0) {
console.error('Request timed out');
}
}Full example
Putting it together — a script that audits recent denials and auto-approves low-risk pending approvals:
import { VetoAdmin, VetoAdminError } from 'veto-sdk';
const admin = new VetoAdmin({ apiKey: process.env.VETO_API_KEY! });
// Pull denied decisions from the last 7 days
const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
const denied = await admin.listDecisions({
decision: 'deny',
startDate: weekAgo,
limit: 100,
});
console.log(`${denied.pagination.total} denials in the last 7 days`);
// Auto-approve pending read_file approvals
const pending = await admin.listPendingApprovals();
const readFileApprovals = pending.filter((a) => a.toolName === 'read_file');
if (readFileApprovals.length > 0) {
const result = await admin.batchResolveApprovals(
readFileApprovals.map((a) => ({
id: a._id,
action: 'approve' as const,
resolvedBy: 'ops-bot',
}))
);
console.log(`Resolved ${result.data.length} read_file approvals`);
}