AnuraGate Documentation
AnuraGate is a unified AI gateway that sits between your app and every AI provider. Use a single base URL and virtual key to access OpenAI, Anthropic, Google, and more — while AnuraGate automatically enforces security, controls costs, and logs everything.
AI agents can leak PII, run up bills, get stuck in loops, or produce harmful outputs. AnuraGate gives you PII redaction, spend caps, circuit breakers, policy firewalls, and AI-powered audits — all without changing your code. Just swap the base URL.
# Replace your base URL — one key, any model
BASE_URL=https://anuragate.com/v1
# OpenAI
curl $BASE_URL/chat/completions \
-H "Authorization: Bearer gk_your_virtual_key" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}'
# Anthropic
curl $BASE_URL/chat/completions \
-H "Authorization: Bearer gk_your_virtual_key" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-4-20250514","messages":[{"role":"user","content":"Hello"}]}'
# Google
curl $BASE_URL/chat/completions \
-H "Authorization: Bearer gk_your_virtual_key" \
-H "Content-Type: application/json" \
-d '{"model":"gemini-2.5-pro","messages":[{"role":"user","content":"Hello"}]}'Examples
Ready-to-run example apps covering Watcher integrations, security features, and the Financial Gateway. Each example is a self-contained Node.js script with a .env.example and step-by-step README — clone, fill in your keys, and run.
Open-source sample repository — contributions and additional examples welcome.
Watcher — Messaging Integrations
Full AI agent loop per platform: message yourself → AnuraGate proxies the request to any supported model → reply lands back in the same chat. Works with OpenAI, Anthropic, Google, or any provider supported by AnuraGate.
Each example uses selfMessageOnly mode so only messages you send to yourself trigger the agent — your regular conversations are never seen. Remove or disable that flag to have the agent respond to any incoming message, group mentions, or specific contacts.
Security Features
Demonstrates PII redaction, custom policy rules, circuit breakers, and the double-check AI audit — showing exactly what gets blocked, what gets redacted, and what appears in the audit trail.
Financial Gateway
End-to-end walkthrough of the Financial Gateway: intent detection, policy evaluation, human-in-the-loop approval via WhatsApp, virtual card issuance, and the Lithic authorization webhook.
Request Headers
Headers you can send with your proxy requests to control AnuraGate behavior.
AuthorizationrequiredBearer gk_...Your AnuraGate virtual key. Accepts either Authorization: Bearer gk_... or the x-gate-key header. At least one is required.
x-gate-keygk_...Alternative to Authorization: Bearer. If both are present, x-gate-key takes priority.
x-gate-sessionstringAttach a session ID to group requests for circuit breaker tracking, key pinning, and prompt caching. If omitted, each request is independent.
x-gate-snapshottrueForce a git snapshot webhook for this request, even if the key doesn't have snapshots enabled by default.
x-gate-audittrueForce a double-check AI audit for this specific request, regardless of key-level audit config.
x-gate-no-cachetrueBypass the smart cache and always forward to the upstream provider.
Response Headers
Headers AnuraGate adds to every proxy response.
x-gate-cost0.0023Estimated cost of this request in USD, calculated from token usage and the model's pricing.
x-gate-cachedtrue | falseWhether this response was served from AnuraGate's smart cache.
x-gate-provideropenai | anthropic | googleWhich upstream provider handled this request.
x-gate-redacted3Number of PII/secret items redacted from the request. Only present if redaction occurred.
x-gate-policy-blockedtruePresent when a policy rule blocked the request before it reached the LLM.
x-gate-session-killedtruePresent when the request triggered a circuit breaker and the session was terminated.
x-gate-snapshot-idstringThe snapshot ID returned by the webhook, if a snapshot was captured.
x-gate-audit-iddaudit_...The audit result ID. Use this to look up the full audit verdict in the audit trail.
x-gate-audit-risklow | medium | high | criticalRisk level from the double-check AI audit, if one was performed.
x-gate-upstream-ms432Time in ms the upstream provider took to respond. Use this to distinguish provider latency from gateway overhead.
x-gate-overhead-ms18Gateway processing time in ms (auth, redaction, policies). Lower is better.
Error Codes
AnuraGate returns standard HTTP status codes with structured error bodies.
{
"error": {
"message": "Daily spend limit exceeded for this key",
"type": "gate_error",
"code": "budget_exceeded"
}
}| Status | Code | Description |
|---|---|---|
| 401 | invalid_key | Virtual key is missing, invalid, or disabled. |
| 403 | model_not_allowed | The requested model is not in the key's allowed models list. |
| 403 | policy_blocked | A policy rule blocked this request content. |
| 429 | rate_limited | The key has exceeded its RPM (requests per minute) limit. |
| 429 | budget_exceeded | Daily spend cap reached for this virtual key. |
| 429 | session_killed | The session was terminated by a circuit breaker. |
| 451 | audit_blocked | Double-check AI flagged the response as high/critical risk (blocking mode). |
| 502 | provider_error | The upstream provider returned an error. |
| 503 | no_provider_key | No provider API key configured for the requested model's provider. |
Webhook Events
Configure a webhook URL in your dashboard to receive real-time notifications. Pro and Enterprise plans only.
POST https://your-webhook.example.com/gate
Content-Type: application/json
{
"event": "budget.alert",
"teamId": "org_abc123",
"keyName": "my-key",
"data": {
"currentSpend": 4.12,
"dailyLimit": 5.00,
"percentUsed": 82.4
},
"timestamp": "2026-02-18T10:30:00.000Z"
}budget.alertFired when a key reaches 80% of its daily spend limit.
budget.exceededFired when a key hits 100% of its daily spend limit and requests are being blocked.
session.killedFired when a circuit breaker terminates a session (cost, token, duration, or request limit exceeded).
loop.detectedFired when loop detection identifies repeated requests or cost spikes.
policy.blockedFired when a policy rule blocks a request.
audit.flaggedFired when double-check AI flags a response as medium risk or above.
Financial Gateway events (finance.*) are documented in the Financial Gateway section below.
Snapshot Protocol
Git snapshots capture your codebase state at the moment of each AI request. Configure a snapshot endpoint URL in your virtual key settings.
Request (from AnuraGate to your endpoint)
POST https://your-snapshot-endpoint.example.com/snapshot
Content-Type: application/json
{
"action": "snapshot",
"virtualKey": "my-key",
"sessionId": "sess_abc123",
"model": "gpt-4o",
"timestamp": "2026-02-18T10:30:00.000Z"
}Expected Response
{
"snapshotId": "snap_abc123",
"commitHash": "a1b2c3d4",
"branch": "main",
"diffSummary": "+42 -15 across 3 files"
}Your endpoint should create a git stash or commit, then return the snapshot metadata. AnuraGate will store the snapshot ID in the request log and include it in the x-gate-snapshot-id response header.
Audit Headers
When double-check AI runs, these headers are added to the response.
x-gate-audit-iddaudit_1708234567_a1b2c3Unique ID for this audit. Look it up in the Audit Trail dashboard tab.
x-gate-audit-risklow | medium | high | criticalOverall risk assessment from the audit LLM.
x-gate-audit-passedtrue | falseWhether the audit passed. In blocking mode, a failed audit returns HTTP 451.
Blocking vs. Async Mode
In async mode, the audit runs in the background after the response is sent. The audit headers will still be present but the response is never blocked. In blocking mode, AnuraGate waits for the audit to complete before returning the response. If the audit fails (risk = high or critical), the response is replaced with an HTTP 451 error.
Performance
AnuraGate includes latency headers, connection reuse, session-based key pinning, and provider-level prompt caching to minimize overhead for latency-sensitive workloads like real-time chat agents.
Gate Metadata
Every response includes a gate object with performance metrics, cost, and cache statistics.
Non-streaming responses
The gate object is added to the JSON response body alongside the standard OpenAI fields:
{
"id": "chatcmpl-...",
"choices": [...],
"usage": {
"prompt_tokens": 120,
"completion_tokens": 35,
"total_tokens": 155
},
"gate": {
"provider": "openai",
"upstream_ms": 432,
"overhead_ms": 18,
"cost": 0.0023,
"cached_tokens": 80,
"cache_creation_tokens": 0,
"session_id": "agent-session-42",
"session_cost": 0.0150,
"session_requests": 5
}
}Streaming responses
A custom event: gate SSE event is emitted after data: [DONE] with the same fields. First-token timing is also sent as an SSE comment before the first content chunk. Standard SSE parsers ignore comments, so this is fully backwards-compatible.
: x-gate-first-token-ms=523
data: {"id":"chatcmpl-...","choices":[{"delta":{"content":"Hello"}}]}
data: [DONE]
event: gate
data: {"provider":"openai","upstream_ms":432,"overhead_ms":18,"first_token_ms":523,"cost":0.0023,"usage":{"prompt_tokens":120,"completion_tokens":35,"total_tokens":155,"cached_tokens":80,"cache_creation_tokens":0}}Parsing the gate event (JavaScript)
const source = new EventSource(url);
// Normal chunks arrive as "message" events
source.onmessage = (e) => { /* handle content chunks */ };
// Gate metadata arrives as a custom "gate" event
source.addEventListener("gate", (e) => {
const gate = JSON.parse(e.data);
console.log(gate.upstream_ms); // 432
console.log(gate.cost); // 0.0023
console.log(gate.usage); // { prompt_tokens, cached_tokens, ... }
});Latency Headers
The same timing values are also available as response headers for simpler integrations:
x-gate-upstream-ms432Time in milliseconds from when AnuraGate sent the request to the provider until the first byte was received back.
x-gate-overhead-ms18Total gateway processing time in milliseconds (authentication, redaction, policies, etc.) excluding upstream latency.
Session Key Pinning
When you send an x-gate-session header, AnuraGate pins subsequent requests in that session to the same upstream API key. This maximizes provider-side prompt cache hits (e.g. OpenAI's automatic caching) when you make multiple sequential calls with the same prompt prefix.
# All requests in the same session use the same upstream key
curl $BASE_URL/chat/completions \
-H "Authorization: Bearer gk_your_key" \
-H "x-gate-session: agent-session-42" \
-d '{"model":"gpt-4o","messages":[...]}'Prompt Caching
Prompt caching is opt-in. Enable it on your virtual key via the dashboard (Key Settings → Prompt Caching toggle). Once enabled, AnuraGate automatically leverages each provider's native caching mechanism to reduce latency and cost when your agent sends the same system prompt or conversation prefix repeatedly. No code changes are required — just flip the toggle.
OpenAIAutomatic. No changes needed — OpenAI caches identical prompt prefixes on the same API key. AnuraGate preserves cache affinity via session key pinning. Cached token counts are tracked in usage.
AnthropicAnuraGate injects cache_control breakpoints on your system message and conversation prefix. Cached reads are 90% cheaper. Applies when conversation has 4+ messages.
Google GeminiAnuraGate creates context cache resources via the Gemini API and reuses them within a session. Requires the x-gate-session header and at least ~32,000 tokens in the cached prefix (Google's minimum for context caching). Short conversations will not be cached.
Connection Reuse
AnuraGate maintains persistent HTTP connections to upstream providers, eliminating TLS handshake overhead (~100-200ms) on sequential requests. This is especially impactful for agent workflows that make 3+ calls per user message. Connection pooling is automatic and requires no configuration.
Presets API
Apply one-click security presets to configure all your keys at once.
Apply a Preset
POST /api/dashboard/security/presets
Content-Type: application/json
Cookie: (Clerk session)
{
"presetId": "standard",
"keys": ["my-key-1", "my-key-2"] // optional — omit for all keys
}
// Response
{
"success": true,
"presetId": "standard",
"applied": 5,
"skipped": 0,
"errors": []
}relaxedFree tier: Basic PII redaction only. No policies, session tracking, or audit features.
standardPro tier: Full PII + secret detection, default blocklists, circuit breakers with loop detection.
strictEnterprise tier: Maximum protection — response scanning, blocking AI audit, tight session limits, auto-kill.
Tool Integrations API
Connect third-party tools (WhatsApp, Telegram, Slack, GitHub, Jira) to AnuraGate. All events pass through the same security pipeline — redaction, policies, and audit logging — without ever storing user credentials.
Webhook Relay
For services with native webhook support. Configure the third-party service to POST events to your integration's webhook URL.
POST /v1/tools/webhook/{slug}
# Headers set by the third-party service:
X-Slack-Signature: v0=abc... # Slack
X-Hub-Signature-256: sha256=... # GitHub
X-Hub-Signature-256: sha256=... # WhatsApp Business
# AnuraGate verifies the signature, normalizes the event,
# runs security pipeline, and forwards to your forwardUrl.
# Response:
{ "ok": true }Outbound Tool Proxy
Send actions through tools via AnuraGate. For watcher-based tools, actions are queued. For webhook-based tools with token passthrough, requests are proxied directly.
POST /v1/tools/proxy
x-gate-key: gk-your-key
x-gate-tool-token: xoxb-... # Only for direct API calls
{
"tool": "slack",
"action": "send_message",
"params": {
"channel": "#general",
"text": "Hello from AnuraGate!"
},
"integrationId": "ti_..."
}
# Response (watcher-based):
{ "ok": true, "actionId": "act_...", "status": "queued" }
# Response (token passthrough):
{ "ok": true, "data": { ... } }Supported Tools
whatsapp-webWhatsApp Web via AnuraGate Watcher (self-hosted). Events: message.received, message.sent, message.ack, group.join, etc.
whatsapp-businessWhatsApp Business Cloud API via webhook relay. Events: message.text, message.image, message.status.*, etc.
telegram-botTelegram Bot API via webhook relay. Events: message, message.photo, message.document, message.edited, callback_query, channel_post, member.joined, etc.
telegramTelegram personal account via AnuraGate Watcher (self-hosted MTProto). Events: message.received, message.sent, message.edited, message.deleted, chat.action, etc.
slackSlack Events API via webhook relay. Events: message, reaction_added, member_joined_channel, app_mention, etc.
githubGitHub Webhooks via webhook relay. Events: push, pull_request.*, issues.*, issue_comment.created, etc.
jiraJira Cloud via AnuraGate Watcher (self-hosted, API token auth). Events: issue_created, issue_transitioned, issue_assigned, comment_added, priority_changed, sprint_changed, etc.
Tool Webhook Events
Subscribe to these events via the Webhooks dashboard to get notified about tool activity.
tool.event.receivedAn inbound tool event was processed (or blocked) by AnuraGate.
tool.integration.createdA new tool integration was added.
tool.integration.disabledA tool integration was disabled.
tool.integration.deletedA tool integration was deleted.
tool.health.watcher_offlineAn AnuraGate Watcher agent stopped sending heartbeats.
tool.health.error_spikeAn integration's error rate exceeded 50%.
tool.health.staleAn integration hasn't received events for over 1 hour.
Watcher API
The AnuraGate Watcher is a self-hosted daemon that maintains connections to services like WhatsApp Web and Telegram. Session tokens stay on your machine — only events are sent to AnuraGate for security processing.
Heartbeat
POST /v1/tools/watcher/heartbeat
x-gate-key: gk-your-key
{ "integrationId": "ti_..." }
# Response:
{
"ok": true,
"integrationId": "ti_...",
"heartbeat": "2026-02-18T12:00:00.000Z",
"nextHeartbeatIn": 30
}Push Event
POST /v1/tools/watcher/event
x-gate-key: gk-your-key
{
"integrationId": "ti_...",
"event": {
"id": "evt_1",
"tool": "whatsapp-web",
"eventType": "message.received",
"timestamp": "2026-02-18T12:00:00Z",
"source": { "id": "+1234567890", "name": "John", "type": "user" },
"content": { "text": "Hello!", "metadata": {} },
"raw": {}
}
}
# Response:
{
"ok": true,
"blocked": false,
"forwarded": true,
"securityActions": ["redacted:2"],
"latencyMs": 45
}Poll Outbound Actions
GET /v1/tools/watcher/outbound?integrationId=ti_...
x-gate-key: gk-your-key
# Response:
{
"ok": true,
"actions": [
{
"id": "act_...",
"integrationId": "ti_...",
"action": "send_message",
"params": { "chatId": "...", "text": "Hello!" },
"status": "processing",
"createdAt": "2026-02-18T12:00:00Z"
}
]
}Report Action Result
POST /v1/tools/watcher/outbound
x-gate-key: gk-your-key
{
"actionId": "act_...",
"integrationId": "ti_...",
"success": true,
"result": { "messageId": "..." }
}
# Response:
{ "ok": true }Plan Limits
Free1 integration, 100 events/day, 50 outbound/day, no watcher agents
Pro ($29/mo)5 integrations, 5,000 events/day, 2,500 outbound/day, 1 watcher agent
Enterprise ($99/mo)Unlimited integrations, events, outbound actions, and watcher agents
Watcher SDK
The AnuraGate Watcher SDK (@gate/watcher) is a self-hosted package that connects third-party services (WhatsApp Web, Telegram, etc.) to AnuraGate. Session tokens stay on your machine — AnuraGate never stores credentials. You can use it as a CLI tool or embed it directly into your Node.js application with a plug-and-play UI widget.
1. Create an Integration
Go to the AnuraGate Dashboard → Integrations and create a new integration. Select your tool (e.g. WhatsApp Web, Telegram, or Jira) and Watcher as the mode. You will receive an integrationId and your existing virtual key (gk-…) is used to authenticate.
2. Install the SDK
npm install @gate/watcher
3. Backend Setup (Node.js)
Add the watcher to your existing Express / HTTP server. This is all the server-side code you need — five lines:
const express = require("express");
const { GateWatcher, widgetMiddleware } = require("@gate/watcher");
const app = express();
// Serve the widget JS from the SDK
app.use(widgetMiddleware());
// Create the watcher
const watcher = new GateWatcher({
gateKey: "gk-your-virtual-key",
integrationId: "ti_your-integration-id",
});
// Start the server, then attach the watcher
const server = app.listen(3000);
watcher.attach(server);
// Events (optional)
watcher.on("qr", () => console.log("QR ready"));
watcher.on("ready", () => console.log("WhatsApp connected"));
watcher.on("message", (msg) => console.log("Message from", msg.from));
watcher.start();4. Frontend Setup (Any Page)
Drop the widget into any page served by your Express app. No framework required — the SDK provides all styles and logic:
<div id="whatsapp"></div>
<script src="/gate-watcher/widget.js"></script>
<script>GateWatcher.mount('#whatsapp')</script>This renders a card with a "Connect WhatsApp" button. Clicking it opens a modal with a QR code. Once scanned, the card updates to show the connected status.
5. Widget Options
GateWatcher.mount('#whatsapp', {
wsPath: '/ws/whatsapp', // WebSocket path (default)
theme: 'light', // 'light' or 'dark'
})6. React Components
For React apps, import the customer-facing QR component or the full admin panel:
import { GateWatcherQR } from "@gate/watcher/react";
// Clean QR-only flow for end users
<GateWatcherQR
wsUrl="ws://localhost:3000/ws/whatsapp"
onReady={() => console.log("Connected!")}
/>
// Or the full admin panel with event feed
import { GateWatcherPanel } from "@gate/watcher/react";
<GateWatcherPanel wsUrl="ws://localhost:3000/ws/whatsapp" />7. CLI Mode
For quick testing or headless environments, run the watcher from the command line. Create a .env file and run:
# .env GATE_KEY=gk-your-virtual-key GATE_INTEGRATION_ID=ti_your-integration-id # Run npx @gate/watcher
The QR code will be displayed in the terminal. Set WEB_PORT=3001 in your .env to also launch a local web panel for scanning.
How It Works
EventsThe watcher pushes every incoming event (WhatsApp messages, Telegram messages, etc.) to AnuraGate via POST /v1/tools/watcher/event. AnuraGate runs your security pipeline (redaction, policies, audit) and forwards processed events to your configured forward URL.
OutboundTo send messages, your app calls POST /v1/tools/proxy. AnuraGate queues the action, and the watcher polls for it. Execution happens locally — tokens never leave your machine.
HeartbeatThe watcher sends heartbeats every 30s to POST /v1/tools/watcher/heartbeat. If heartbeats stop, AnuraGate marks the integration as offline and fires a tool.health.watcher_offline webhook.
SecurityAll events pass through AnuraGate's security layers: PII redaction, policy enforcement, and audit logging. Blocked events are logged but not forwarded.
Financial Gateway
The Financial Gateway lets AI agents make real-world purchases safely — flights, hotels, software subscriptions — using single-use virtual cards issued on the fly. Instead of giving an agent your real credit card, AnuraGate acts as a programmatic escrow: it detects purchase intent in the proxy stream, optionally asks a human for approval, then issues a Lithic virtual card locked to that exact merchant and amount. The card closes automatically after one use.
This runs entirely inside the existing proxy pipeline. Your agent code changes nothing — just send requests through AnuraGate as normal.
How it fits into AnuraGate
Your App / AI Agent
│
│ POST /v1/chat/completions
│ Authorization: Bearer gk_...
│ x-gate-session: agent-session-42
▼
┌─────────────────────────────────────────┐
│ AnuraGate Proxy │
│ │
│ 1. Auth + rate limiting │
│ 2. PII redaction │
│ 3. Policy enforcement │
│ 4. Inject pending card details ◄───┐ │ ← Financial Gateway
│ 5. Forward to LLM provider │ │
│ 6. Scan response for intent ──────┘ │ ← Financial Gateway (async)
└─────────────────────────────────────────┘
│
▼
Response returned to agent (zero added latency)1. Setup (Dashboard)
All configuration happens in the Dashboard → Finance page. Three things to set up once:
Funding SourceLink your Lithic card token. This is the funding account that backs all issued virtual cards. Raw card data never touches AnuraGate — only the Lithic token is stored.
WalletSet daily, monthly, and per-transaction spend limits. Optionally restrict which merchant categories (flights, hotels, software, etc.) are allowed. The agent can only spend within these limits.
Transaction PolicyDefine rules that determine whether an intent is auto-approved or requires human sign-off. Example: auto-approve software subscriptions under $100, require approval for anything over $500.
2. Intent Detection (Automatic)
After every proxy response, AnuraGate asynchronously scans the conversation for purchase intent. This runs in two tiers so it never adds latency:
Tier 1 — Regex filterFast keyword scan (<1ms). Looks for action words (buy, book, subscribe), amounts ($99, 389 USD), merchant names (United, Notion, Adobe), and card signals (CVV, billing address). If fewer than 2 categories match, intent detection stops here.
Tier 2 — LLM extractionIf Tier 1 passes, a lightweight LLM call extracts structured intent: merchant, amount, currency, category, and a confidence score. Only intents with confidence ≥ 0.7 are created.
3. Policy Evaluation
Once an intent is created, AnuraGate evaluates it against your transaction policies. Policies are rules like:
// Auto-approve SaaS under $200
{ field: "amount", operator: "lte", value: 200 }
{ field: "category", operator: "eq", value: "software" }
requireApproval: false
// Require human approval for flights
{ field: "category", operator: "eq", value: "flight" }
requireApproval: true
approvalTimeout: 300 // 5 minutes
autoDeclineOnTimeout: trueIf no policy matches, the intent is declined. If multiple policies match, the first enabled matching policy wins.
4. Human-in-the-Loop Approval
When a policy sets requireApproval: true, AnuraGate sends an approval request to your configured Watcher (WhatsApp or Slack). The approver simply replies YES or NO.
Purchase Approval Required ───────────────────────── Agent Session: agent-session-42 Merchant: United Airlines Amount: $389.00 USD Category: flight Confidence: 94% Context: "Book me a round-trip flight to NYC next week" Reply YES to approve or NO to decline. Auto-decline in 5 minutes.
Configure your approval recipient in Dashboard → Finance → Gateway Settings. Select a Watcher integration and enter the recipient's phone number or Slack user ID. If no approver is configured and a policy requires approval, the intent is automatically declined.
5. Card Issuance
Once approved, AnuraGate issues a Lithic virtual card locked to the intent:
TypeSINGLE_USE — can only be charged once.
Spend limitSet to the approved amount + 5% buffer for taxes and fees (e.g. $389 → $408.45 limit).
MCC restrictionCard is locked to merchant category codes matching the intent category. A flight card cannot be used at a restaurant.
ExpiryCard closes automatically after the transaction settles, or after 30 minutes if never used.
6. Card Delivery to Agent
On the agent's next proxy request in the same session, AnuraGate injects a system message containing the card details. The agent sees this as part of its context and uses the card for checkout. Raw card data is fetched from Lithic on-demand and never stored in AnuraGate's database.
[GATE FINANCIAL GATEWAY] Your purchase of $389.00 USD at United Airlines has been approved. Use the following card details for checkout: Card Number: 4111 2233 4455 6677 Expiry: 08/27 CVV: 123 Limit: $408.45 (single-use, United Airlines only)
7. Authorization Webhook
When the card is swiped at the merchant, Lithic calls POST /v1/finance/webhook/lithic. AnuraGate validates the transaction in real time and responds with APPROVE or DECLINE:
Amount checkTransaction amount must be ≤ approved amount × 1.05. Covers taxes and rounding, rejects anything significantly over the approved value.
MCC checkMerchant category code must match the intent category. A subscription card used at an airline will be declined.
Wallet limitsDaily and monthly wallet spend is checked atomically. A declined authorization never records spend.
To enable this, register your webhook URL in the Lithic Dashboard and set LITHIC_WEBHOOK_SECRET in your environment.
Intent Lifecycle
detected
│
├─► policy declined ──────────────────────► declined (terminal)
│
├─► pending_approval
│ │
│ ├─► human says NO / timeout ───────► declined (terminal)
│ │
│ └─► human says YES
│
└─► approved
│
└─► card_issued
│
├─► card never used (30 min) ► expired (terminal)
│
└─► authorized
│
├─► settled ──────────► completed (terminal)
│
└─► voided ───────────► voided (terminal)Intent History
Every purchase intent is logged with its full lifecycle in Dashboard → Finance → Intent History. The table shows the merchant, amount, category, current status, and the last 4 digits of the issued card. It auto-refreshes every 30 seconds.
Webhook Events
Subscribe to finance.* events in the Integrations → Outbound Webhooks dashboard to get notified at each stage:
finance.intent.approvedIntent passed policy checks and was approved (auto or human).
finance.intent.declinedIntent was declined by policy, human NO reply, or approval timeout.
finance.intent.expiredIntent timed out waiting for approval and no auto-decline was configured.
finance.card.issuedA single-use virtual card was issued for the approved intent.
finance.card.expiredCard was closed after 30 minutes without being used.
finance.transaction.authorizedCard swiped and all checks passed. Wallet spend recorded.
finance.transaction.declinedCard swipe declined. Reason: amount_exceeded, mcc_mismatch, or wallet_limit.
finance.transaction.settledTransaction settled. Card closed. Intent complete.
finance.transaction.voidedTransaction voided. Wallet spend reversed.
PCI Compliance
AnuraGate uses a Lithic-only PCI strategy. Raw card data (PAN, CVV) is never stored in AnuraGate's database or logs. Card details are fetched from Lithic's PCI-compliant API on-demand, injected into the agent's context, and immediately discarded. Lithic handles all PCI-DSS requirements on their end, so AnuraGate operates with zero PCI scope.
As a secondary defence, the existing security scanner detects and redacts card numbers (Luhn-validated) from any request or response before it reaches the LLM, your logs, or outbound webhooks.