Skip to content

TypeScript SDK

The official VeraID TypeScript SDK provides a type-safe client for managing credentials, monitoring AI agent usage, enforcing budgets, and detecting prompt injection attacks. It includes built-in retry logic, rate limit handling, and integration wrappers for popular AI frameworks.

Installation

Terminal window
npm install @veraid/sdk

Quick Start

import { VeraIDClient } from '@veraid/sdk';
const veraid = new VeraIDClient({
apiKey: process.env.VERAID_API_KEY,
agentId: process.env.VERAID_AGENT_ID,
});
// Fetch a credential
const dbUrl = await veraid.getCredential('production-db-url');
console.log('Connected to:', dbUrl.value);

Initialization

Create a client instance with your API key and optional configuration:

import { VeraIDClient } from '@veraid/sdk';
const veraid = new VeraIDClient({
apiKey: 'kd_live_your_api_key',
agentId: 'id_agent123', // Required for AI agent features
baseUrl: 'https://app.veraid.io', // Optional, defaults to production
debug: false, // Optional, enables verbose logging
retryAttempts: 3, // Optional, default: 3
timeout: 30000, // Optional, request timeout in ms
});

Authentication: the agent’s own key

The SDK authenticates as one AI agent, with a credential issued for that agent’s identity (kd_live_...). Issue a long-lived one with POST /api/v1/credentials ({"identityId": "<the agent's id>", "name": "sdk", "type": "API_KEY"}) while signed in; only an organization admin or the agent’s owner can, and the secret is shown once. Generate Credential on the agent’s page under Identities issues a temporary one (kd_jit_...), which works the same way until it expires.

The key acts for its own agent and nothing else:

  • It reads that agent’s budget (getBudgetStatus, checkBudget) and usage (getStats), and checks text for prompt injection (checkInjection).
  • It records that agent’s usage (recordUsage), and so its spend, only if an organization admin issued it. Any member can create an agent and issue it a key, and recorded spend also counts toward the organization-wide limits, so a key issued by anyone else gets 403 there. A key rotated automatically (with no one starting it) has no issuer: an admin re-issues it.
  • A call naming another agent is refused with 403, even one in the same organization.
  • Revoking the credential, suspending the agent, or the issuer losing admin rights takes effect within a minute.
  • If the agent has an IP allowlist (addresses or CIDR ranges), calls must come from an allowed address.
  • Scopes on the credential are not checked for these calls.
  • A non-admin owner of the agent can rotate its keys but cannot sync (deliver) a key an admin or another member issued: only an organization admin can.

It lists this agent’s vault secrets (listCredentials), and reads their values (getCredential) only if an organization admin issued it.


Credential Management

Secrets an organization admin stores in this agent’s vault (an OpenAI key, a database password), which the agent reads at run time. See Storing secrets for an agent. Reading a value needs the agent’s key to have been issued by an organization admin; listing does not.

getCredential

Read a secret’s value by name (POST /api/v1/credentials/retrieve). Every read is audited.

const openaiKey = await veraid.getCredential('openai-api-key'); // the value, a string

Parameters:

ParameterTypeRequiredDescription
namestringYesThe secret’s name in this agent’s vault

Returns: Promise<string>. Refused with 403 for a key not issued by an admin, 404 for an unknown name, 429 past 300 reads a minute per agent.

listCredentials

List the secrets in this agent’s vault: names and metadata, never values (GET /api/v1/agents/{agentId}/credentials).

for (const secret of await veraid.listCredentials()) {
console.log(`${secret.name}: expires ${secret.expiresAt ?? 'never'}`);
}

Returns: Promise<Credential[]>

interface Credential {
id: string;
name: string;
value?: string; // only from getCredential's route, never here
type?: string;
status?: string;
expiresAt?: string | null;
scopes: string[];
createdAt?: string;
}

Budget Management

getBudgetStatus

Retrieve the current budget status for the AI agent.

const budget = await veraid.getBudgetStatus();
console.log(`Budget: $${budget.used} / $${budget.limit} (${budget.percentUsed}%)`);
console.log(`Status: ${budget.status}`); // 'OK' | 'WARNING' | 'CRITICAL' | 'EXCEEDED'
console.log(`Projected: $${budget.projectedSpend}`);

Returns: Promise<BudgetStatus>

interface BudgetStatus {
limit: number;
used: number;
percentUsed: number;
status: 'OK' | 'WARNING' | 'CRITICAL' | 'EXCEEDED';
period: 'daily' | 'weekly' | 'monthly';
projectedSpend: number;
resetAt: string;
}

checkBudget

Check if a specific cost can be accommodated within the remaining budget. Use this before making an expensive AI call.

const canProceed = await veraid.checkBudget(2.50);
if (canProceed.allowed) {
// Proceed with the AI call
const response = await openai.chat.completions.create({...});
} else {
console.log(`Budget exceeded: ${canProceed.reason}`);
// Fall back to a cheaper model or queue for later
}

Parameters:

ParameterTypeRequiredDescription
costnumberYesEstimated cost in USD

Returns: Promise<BudgetCheck>

interface BudgetCheck {
allowed: boolean;
remainingBudget: number;
reason: string | null;
}

Usage Tracking

recordUsage

Record token and cost usage for an AI agent request. Call this after each AI API call to maintain accurate usage tracking.

await veraid.recordUsage({
promptTokens: 1250,
completionTokens: 847,
totalTokens: 2097,
cost: 0.063,
model: 'gpt-4',
latency: 2340,
metadata: {
taskType: 'ticket-triage',
ticketId: 'TICKET-4521',
},
});

Parameters:

ParameterTypeRequiredDescription
usageUsageRecordYesUsage data to record
interface UsageRecord {
promptTokens: number;
completionTokens: number;
totalTokens: number;
cost: number;
model: string;
latency?: number;
toolCalls?: string[];
metadata?: Record<string, unknown>;
}

Returns: Promise<void>


Prompt Security

checkInjection

Analyze a prompt for potential injection attacks (POST /api/v1/ai-monitoring/check-injection).

const result = await veraid.checkInjection(userPrompt);
if (result.isInjection) {
console.error(`Injection detected: ${result.summary}`);
console.error(`Score: ${result.score}, confidence: ${result.confidence}`);
console.error(`Patterns: ${result.patterns.join(', ')}`);
// Block the request or sanitize the input
}

Parameters:

ParameterTypeRequiredDescription
promptstringYesThe prompt to analyze

Returns: Promise<InjectionCheckResult>

interface InjectionCheckResult {
isInjection: boolean;
score: number; // 0 to 1
confidence: 'low' | 'medium' | 'high';
method: 'pattern' | 'ml' | 'combined';
patterns: string[]; // detected pattern categories
summary: string;
details?: InjectionDetail[];
highRiskPatterns?: InjectionDetail[]; // the high and critical matches
recommendations?: string[]; // when an injection was detected
}
interface InjectionDetail {
category: string;
pattern: string;
risk: 'low' | 'medium' | 'high' | 'critical';
description: string;
matchedText?: string;
}

guardPrompt

A convenience method that checks for injection and throws an error if one is detected. Use this as a guard at the beginning of your prompt processing pipeline.

try {
const safePrompt = await veraid.guardPrompt(userPrompt);
// safePrompt is the original prompt, returned only if safe
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: safePrompt }],
});
} catch (error) {
if (error instanceof VeraIDInjectionError) {
console.error(`Blocked: ${error.category} (${error.confidence})`);
// Return a safe response to the user
}
}

Parameters:

ParameterTypeRequiredDescription
promptstringYesThe prompt to guard

Returns: Promise<string> (the original prompt if safe)

Throws: VeraIDInjectionError if injection is detected


Analytics

getStats

Retrieve this agent’s usage over a period: the current day, week or month (UTC).

const stats = await veraid.getStats('week'); // 'day' (default), 'week' or 'month'
console.log(`Total requests: ${stats.totalRequests}`);
console.log(`Total cost: $${stats.totalCost}`);
console.log(`Average latency: ${stats.avgLatencyMs}ms`);
console.log(`Injections detected: ${stats.injectionDetections}`);

Returns: Promise<AgentStats>, from GET /api/v1/ai-monitoring/{agentId}?period=daily|weekly|monthly

interface UsageBreakdown { requests: number; tokens: number; cost: number }
interface AgentStats {
period: 'daily' | 'weekly' | 'monthly';
periodStart: string; // ISO 8601
periodEnd: string;
totalRequests: number;
successfulRequests: number;
failedRequests: number;
totalInputTokens: number;
totalOutputTokens: number;
totalTokens: number;
totalCost: number; // USD
avgLatencyMs: number;
maxLatencyMs: number;
byModel: Record<string, UsageBreakdown>;
byAction: Record<string, UsageBreakdown>;
injectionDetections: number;
}

OpenAI Integration

The SDK provides a wrapper for the OpenAI client that automatically monitors all API calls, tracks token usage and costs, checks budgets, and detects prompt injection.

import OpenAI from 'openai';
import { VeraIDClient } from '@veraid/sdk';
import { wrapOpenAI } from '@veraid/sdk/openai';
const veraid = new VeraIDClient({
apiKey: process.env.VERAID_API_KEY,
agentId: process.env.VERAID_AGENT_ID,
});
const openai = wrapOpenAI(new OpenAI(), veraid);
// All calls are now automatically monitored
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Summarize this document...' }],
});
// Usage is automatically recorded:
// - Token counts (prompt + completion)
// - Cost estimate based on model pricing
// - Latency
// - Budget check before each call
// - Prompt injection detection on user messages

The wrapper intercepts:

FeatureBehavior
Budget checkVerifies budget availability before each API call
Usage recordingAutomatically records tokens, cost, and latency after each call
Injection detectionScans user messages for prompt injection before sending to OpenAI
Error handlingCaptures and reports errors to VeraID for anomaly tracking

Error Handling

The SDK provides typed error classes for different failure modes:

import {
VeraIDClient,
VeraIDError,
VeraIDAuthError,
VeraIDRateLimitError,
VeraIDBudgetExceededError,
VeraIDInjectionError,
} from '@veraid/sdk';
try {
const credential = await veraid.getCredential('my-secret');
} catch (error) {
if (error instanceof VeraIDAuthError) {
console.error('Invalid API key');
} else if (error instanceof VeraIDRateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
} else if (error instanceof VeraIDBudgetExceededError) {
console.error(`Budget exceeded: ${error.limit} / ${error.used}`);
} else if (error instanceof VeraIDInjectionError) {
console.error(`Injection: ${error.category} (${error.confidence})`);
} else if (error instanceof VeraIDError) {
console.error(`VeraID error: ${error.message}`);
}
}

Environment Variables

The SDK reads the following environment variables as defaults:

VariableDescriptionRequired
VERAID_API_KEYAPI key for authenticationYes
VERAID_AGENT_IDAgent identity ID (for AI agent features)For agent features
VERAID_BASE_URLBase URL override (default: https://app.veraid.io)No
VERAID_DEBUGEnable debug logging (true / false)No
Terminal window
export VERAID_API_KEY="kd_live_your_api_key"
export VERAID_AGENT_ID="id_agent123"
export VERAID_DEBUG="false"