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
| Field | Type | Description |
|---|---|---|
model | string | AI model identifier (e.g., gpt-4, claude-3-opus, gemini-pro) |
provider | string | Model provider (e.g., openai, anthropic, google) |
budgetLimit | number | Maximum spend in USD per budget period |
budgetPeriod | string | Budget period: daily, weekly, monthly |
maxTokensPerRequest | number | Maximum tokens allowed per individual request |
promptInjectionDetection | boolean | Enable prompt injection detection (default: true) |
mcpServers | string[] | Allowed MCP server identifiers for tool access |
allowedTools | string[] | Allowed tool names (if MCP servers are configured) |
blockedTools | string[] | Explicitly blocked tool names |
Create an AI Agent
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:
| Metric | Description |
|---|---|
promptTokens | Number of tokens in the prompt/input |
completionTokens | Number of tokens in the completion/output |
totalTokens | Total tokens consumed |
cost | Estimated cost in USD based on model pricing |
model | Model used for the request |
latency | Response time in milliseconds |
toolCalls | Tools invoked during the request |
Budget Monitoring
Query the budget an AI agent is held to and its spend so far:
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):
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.
| Route | Who | Does |
|---|---|---|
GET /api/v1/agents/:id/credentials | any member (viewers included), or the agent’s own key | lists names and metadata, never values; expired secrets stay listed until revoked, since they count toward the credential quota |
POST /api/v1/agents/:id/credentials | an organization admin | stores a secret |
DELETE /api/v1/agents/:id/credentials/:credentialId | an organization admin | revokes it (vault secrets also appear among the organization’s credentials, where the agent’s owner can revoke them too) |
POST /api/v1/credentials/retrieve | the agent’s own key, issued by an organization admin | returns 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:
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-requestsQuery Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status: PENDING, APPROVED, DENIED, EXPIRED |
identityId | string | Filter by requesting identity |
page | number | Page number (default: 1) |
limit | number | Items per page (default: 20) |
Example Request
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-requestsRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
identityId | string | Yes | Identity requesting elevated access |
scopes | string[] | Yes | Scopes being requested |
duration | string | Yes | Requested duration (e.g., 30m, 2h, 1d) |
justification | string | Yes | Reason for the access request |
metadata | object | No | Additional context (ticket ID, incident reference, etc.) |
Example Request
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
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" }}