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
npm install @veraid/sdkQuick Start
import { VeraIDClient } from '@veraid/sdk';
const veraid = new VeraIDClient({ apiKey: process.env.VERAID_API_KEY, agentId: process.env.VERAID_AGENT_ID,});
// Fetch a credentialconst 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 gets403there. 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 stringParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
cost | number | Yes | Estimated 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
usage | UsageRecord | Yes | Usage 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | The 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | The 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 monitoredconst 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 messagesThe wrapper intercepts:
| Feature | Behavior |
|---|---|
| Budget check | Verifies budget availability before each API call |
| Usage recording | Automatically records tokens, cost, and latency after each call |
| Injection detection | Scans user messages for prompt injection before sending to OpenAI |
| Error handling | Captures 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:
| Variable | Description | Required |
|---|---|---|
VERAID_API_KEY | API key for authentication | Yes |
VERAID_AGENT_ID | Agent identity ID (for AI agent features) | For agent features |
VERAID_BASE_URL | Base URL override (default: https://app.veraid.io) | No |
VERAID_DEBUG | Enable debug logging (true / false) | No |
export VERAID_API_KEY="kd_live_your_api_key"export VERAID_AGENT_ID="id_agent123"export VERAID_DEBUG="false"