Skip to content

Agent Endpoints

AI agents are managed as identities with the type AI_AGENT. They include additional configuration for budget controls, token monitoring, prompt injection detection, and MCP server governance. This page covers agent-specific capabilities and the JIT request endpoints.

Agent Configuration

AI agents are created and managed through the Identity API with the type set to AI_AGENT and an agentConfig object that specifies agent-specific settings.

Agent Config Fields

FieldTypeDescription
modelstringAI model identifier (e.g., gpt-4, claude-3-opus, gemini-pro)
providerstringModel provider (e.g., openai, anthropic, google)
budgetLimitnumberMaximum spend in USD per budget period
budgetPeriodstringBudget period: daily, weekly, monthly
maxTokensPerRequestnumberMaximum tokens allowed per individual request
promptInjectionDetectionbooleanEnable prompt injection detection (default: true)
mcpServersstring[]Allowed MCP server identifiers for tool access
allowedToolsstring[]Allowed tool names (if MCP servers are configured)
blockedToolsstring[]Explicitly blocked tool names

Create an AI Agent

Terminal window
curl -X POST https://app.veraid.io/api/v1/identities \
-H "Authorization: Bearer kd_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"name": "customer-support-agent",
"type": "AI_AGENT",
"description": "Customer support AI agent for ticket triage and response drafting",
"tags": ["ai-agent", "customer-support", "production"],
"agentConfig": {
"model": "gpt-4",
"provider": "openai",
"budgetLimit": 500.00,
"budgetPeriod": "monthly",
"maxTokensPerRequest": 4096,
"promptInjectionDetection": true,
"mcpServers": ["crm-server", "knowledge-base"],
"allowedTools": [
"crm.getTicket",
"crm.updateTicket",
"kb.search",
"kb.getArticle"
],
"blockedTools": [
"crm.deleteCustomer",
"crm.exportData"
]
}
}'

AI Monitoring

VeraID tracks token usage and cost for every AI agent request, providing real-time visibility into agent spending and behavior.

Usage Tracking per Request

Each API call made by an AI agent records:

MetricDescription
promptTokensNumber of tokens in the prompt/input
completionTokensNumber of tokens in the completion/output
totalTokensTotal tokens consumed
costEstimated cost in USD based on model pricing
modelModel used for the request
latencyResponse time in milliseconds
toolCallsTools invoked during the request

Budget Monitoring

Query the budget an AI agent is held to and its spend so far:

Terminal window
curl -X GET https://app.veraid.io/api/v1/agents/id_agent123/budget \
-H "Authorization: Bearer kd_live_abc123..."

Response:

{
"dailyLimit": 100,
"monthlyLimit": 2500,
"dailySpend": 42.17,
"monthlySpend": 612.40,
"dailyUsagePercent": 42.17,
"monthlyUsagePercent": 24.5,
"isExceeded": false,
"dailyRemaining": 9007199254740991,
"monthlyRemaining": 9007199254740991,
"perRequestLimit": 5,
"warningThreshold": 0.8,
"isWarning": false,
"actionOnExceed": "alert"
}

The limits are the agent’s own costBudget, else the organization’s default agent limits (Settings → AI budget). dailyRemaining and monthlyRemaining are how much may still be spent before a request is refused, the organization-wide limits included: under the alert action (the default) nothing is refused, so they read 9007199254740991 (unlimited). warningThreshold is a fraction of the limit. isExceeded is true once spend passes the organization’s block threshold.

Storing secrets for an agent

An agent’s vault holds external secrets an organization admin stores for it (an OpenAI key, a database password). The agent reads them at run time with its own key: the SDKs’ getCredential(name). Values are encrypted, never shown again after they are stored, and never appear in audit logs.

Store a secret: an organization admin, from a signed-in session (the browser’s session cookie; API keys cannot store secrets):

Terminal window
curl -X POST https://app.veraid.io/api/v1/agents/$AGENT_ID/credentials \
-H "Content-Type: application/json" \
-H "Cookie: $VERAID_SESSION_COOKIE" \
-d '{"name": "openai-api-key", "value": "sk-...", "expiresAt": "2027-01-01T00:00:00Z"}'

name is 1-128 letters, digits, dots, dashes or underscores; value is up to 16 KB; expiresAt and scopes are optional (scopes is a label kept with the secret, not checked when it is read). A live secret of the same name must be revoked first (409 SECRET_EXISTS). The answer is the secret’s metadata, without the value.

RouteWhoDoes
GET /api/v1/agents/:id/credentialsany member (viewers included), or the agent’s own keylists names and metadata, never values; expired secrets stay listed until revoked, since they count toward the credential quota
POST /api/v1/agents/:id/credentialsan organization adminstores a secret
DELETE /api/v1/agents/:id/credentials/:credentialIdan organization adminrevokes it (vault secrets also appear among the organization’s credentials, where the agent’s owner can revoke them too)
POST /api/v1/credentials/retrievethe agent’s own key, issued by an organization adminreturns a value: {"name": "openai-api-key"}

Reading a value is refused for a browser session (people manage secrets, they do not read them back), for a key of another agent, and for a key that an admin did not issue: any member can create an agent and issue it a key, and an admin’s secret must not reach whoever does. Reads are audited (credential.vault_read, naming the key) and limited to 300 a minute per key and per agent. A vault secret is never synced to a target or returned by the organization-key fetch route (which hands out no credential of an AI agent at all, 403 AGENT_CREDENTIAL: an admin-issued agent key reads the vault), and generic rotation refuses it (VAULT_SECRET): store the new value and revoke the old one instead. Emergency rotation and containment revoke it.

The same rule protects admin-issued agent keys: a member who is not an admin can deliver (sync) an agent’s key only if they issued it themselves or nobody did, as after an automatic rotation (403 otherwise; other identities’ owners deliver their credentials as before), and an admin’s emergency rotation of a key a member issued, which copies that key’s sync targets, does not make the new key admin-issued.

Usage History

Query historical usage data for an AI agent:

Terminal window
curl -X GET "https://app.veraid.io/api/v1/identities/id_agent123/usage?period=7d&granularity=1h" \
-H "Authorization: Bearer kd_live_abc123..."

Response:

{
"identityId": "id_agent123",
"period": "7d",
"granularity": "1h",
"dataPoints": [
{
"timestamp": "2026-03-19T09:00:00Z",
"cost": 12.45,
"tokens": 623400,
"requests": 412
},
{
"timestamp": "2026-03-19T10:00:00Z",
"cost": 15.22,
"tokens": 761000,
"requests": 503
}
],
"summary": {
"totalCost": 247.83,
"totalTokens": 12456789,
"totalRequests": 8432,
"peakHourlyCost": 28.91,
"peakHourlyRequests": 892
}
}

JIT Request Endpoints

Just-in-time (JIT) access requests allow agents and other identities to request temporary elevated permissions with human approval.

List JIT Requests

GET /api/v1/jit-requests

Query Parameters

ParameterTypeDescription
statusstringFilter by status: PENDING, APPROVED, DENIED, EXPIRED
identityIdstringFilter by requesting identity
pagenumberPage number (default: 1)
limitnumberItems per page (default: 20)

Example Request

Terminal window
curl -X GET "https://app.veraid.io/api/v1/jit-requests?status=PENDING" \
-H "Authorization: Bearer kd_live_abc123..."

Example Response

{
"data": [
{
"id": "jit_abc123",
"identityId": "id_agent456",
"identityName": "customer-support-agent",
"status": "PENDING",
"requestedScopes": ["crm.writeTicket", "crm.escalate"],
"duration": "2h",
"justification": "Customer escalation requires write access to update ticket priority and assign to tier-2 support",
"requestedAt": "2026-03-19T10:15:00Z",
"expiresAt": null,
"approver": null,
"approvedAt": null,
"metadata": {
"ticketId": "TICKET-4521",
"customerId": "cust_xyz"
}
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 3,
"totalPages": 1,
"hasMore": false
}
}

Create JIT Request

POST /api/v1/jit-requests

Request Body

FieldTypeRequiredDescription
identityIdstringYesIdentity requesting elevated access
scopesstring[]YesScopes being requested
durationstringYesRequested duration (e.g., 30m, 2h, 1d)
justificationstringYesReason for the access request
metadataobjectNoAdditional context (ticket ID, incident reference, etc.)

Example Request

Terminal window
curl -X POST https://app.veraid.io/api/v1/jit-requests \
-H "Authorization: Bearer kd_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"identityId": "id_agent456",
"scopes": ["crm.writeTicket", "crm.escalate"],
"duration": "2h",
"justification": "Customer escalation requires write access to update ticket priority and assign to tier-2 support",
"metadata": {
"ticketId": "TICKET-4521",
"customerId": "cust_xyz"
}
}'

Example Response

{
"id": "jit_def789",
"identityId": "id_agent456",
"identityName": "customer-support-agent",
"status": "PENDING",
"requestedScopes": ["crm.writeTicket", "crm.escalate"],
"duration": "2h",
"justification": "Customer escalation requires write access to update ticket priority and assign to tier-2 support",
"requestedAt": "2026-03-19T10:30:00Z",
"notificationsSent": ["slack:#access-approvals", "email:security-team@company.com"],
"metadata": {
"ticketId": "TICKET-4521",
"customerId": "cust_xyz"
}
}

Get JIT Request

GET /api/v1/jit-requests/{id}

Example Request

Terminal window
curl -X GET https://app.veraid.io/api/v1/jit-requests/jit_def789 \
-H "Authorization: Bearer kd_live_abc123..."

Example Response

{
"id": "jit_def789",
"identityId": "id_agent456",
"identityName": "customer-support-agent",
"status": "APPROVED",
"requestedScopes": ["crm.writeTicket", "crm.escalate"],
"duration": "2h",
"justification": "Customer escalation requires write access to update ticket priority and assign to tier-2 support",
"requestedAt": "2026-03-19T10:30:00Z",
"approver": {
"id": "usr_admin001",
"name": "Bob Smith",
"email": "bob@company.com"
},
"approvedAt": "2026-03-19T10:32:00Z",
"credential": {
"id": "cred_jit_abc",
"expiresAt": "2026-03-19T12:32:00Z"
},
"expiresAt": "2026-03-19T12:32:00Z",
"metadata": {
"ticketId": "TICKET-4521",
"customerId": "cust_xyz"
}
}