Admin Console
AI Calling Agent Guide
Backend integration guide for admin-controlled recovery agents with language-specific examples.
1. Find caller by account number, partner user id, or email.
2. Send OTP to registered email from agent backend.
3. Verify OTP in agent backend.
4. Auto-generate visual reset link and auto-email it to user.
5. Track each step in audit logs.
Configure AI calling agent from backend only using admin-auth APIs.
GET /api/settings/ai-agent?partnerId=<partnerId> PUT /api/settings/ai-agent GET /api/settings/ai-agent/public?partnerId=<partnerId> # partner-key scoped
Config input fields:
[ "partnerId", "providerName", "agentBaseUrl", "findUserPath", "sendOtpPath", "verifyOtpPath", "adminResetPath", "webhookUrl", "callbackBaseUrl", "inputSchemaUrl", "authType", "outboundSecret", "customHeaders", "supportedLanguages", "enableAutoResetEmail", "enableAdminReset", "enabled" ]
Always build full API URLs from environment variables so production URL changes do not require code changes.
Environment keys used in this project:
[ "BACKEND_API_BASE_URL", "NEXT_PUBLIC_API_BASE_URL", "VISUAL_BACKEND_API_BASE_URL", "DEMO_BANK_URL", "NEXT_PUBLIC_DEMO_BANK_URL", "VISUAL_VERIFY_ORIGIN", "DEMO_BANK_PUBLIC_ORIGIN", "VISUAL_PARTNER_ID", "VISUAL_API_KEY" ]
Example .env (Production Only)
BACKEND_API_BASE_URL=https://api.yourbank.com/api NEXT_PUBLIC_API_BASE_URL=https://api.yourbank.com/api VISUAL_BACKEND_API_BASE_URL=https://api.yourbank.com/api DEMO_BANK_URL=https://agent.yourbank.com NEXT_PUBLIC_DEMO_BANK_URL=https://agent.yourbank.com VISUAL_VERIFY_ORIGIN=https://console.yourbank.com DEMO_BANK_PUBLIC_ORIGIN=https://agent.yourbank.com VISUAL_PARTNER_ID=hdfc_bank VISUAL_API_KEY=<secure-partner-api-key>
Full URL Build Pattern (Provider Agnostic, No Localhost Fallback)
// Node.js
const requireEnv = (name) => {
const value = process.env[name];
if (!value || !value.trim()) {
throw new Error(name + " is required in production");
}
return value.trim();
};
const apiBase = requireEnv("VISUAL_BACKEND_API_BASE_URL");
const agentBase = requireEnv("DEMO_BANK_URL");
const fullUrls = {
dashboardStats: apiBase + "/dashboard/stats",
aiSettings: apiBase + "/settings/ai-agent",
findUser: agentBase + "/api/demo-bank/agent/find-user",
sendOtp: agentBase + "/api/demo-bank/agent/send-otp",
verifyOtp: agentBase + "/api/demo-bank/agent/verify-otp",
adminReset: agentBase + "/api/demo-bank/agent/admin-reset",
};Runtime Guard (Reject Localhost in Production)
if (process.env.NODE_ENV === "production") {
const blocked = ["localhost", "127.0.0.1"];
const values = [process.env.BACKEND_API_BASE_URL, process.env.DEMO_BANK_URL];
for (const value of values) {
if (value && blocked.some((item) => value.includes(item))) {
throw new Error("Production URL cannot use localhost/127.0.0.1");
}
}
}cURL with env values
# Linux/macOS
export API_BASE="https://api.yourbank.com/api"
export AGENT_BASE="https://agent.yourbank.com"
curl "$API_BASE/settings/ai-agent?partnerId=hdfc_bank" \
-H "Authorization: Bearer <ADMIN_JWT>"
curl -X POST "$AGENT_BASE/api/demo-bank/agent/send-otp" \
-H "Content-Type: application/json" \
-d '{"partnerUserId":"customer-bank-001","agentName":"Agent-01"}'Recommendation: store only base URLs in env and compose endpoint paths in backend config. Never hardcode production hostnames in app source, and never keep localhost fallback in production builds.
Use Twilio Studio/Functions to collect caller inputs, then call your backend endpoints for lookup, OTP, and verify.
Setup Template
{
"providerName": "twilio",
"partnerId": "hdfc_bank",
"agentBaseUrl": "https://voice.yourbank.com",
"findUserPath": "/api/demo-bank/agent/find-user",
"sendOtpPath": "/api/demo-bank/agent/send-otp",
"verifyOtpPath": "/api/demo-bank/agent/verify-otp",
"adminResetPath": "/api/demo-bank/agent/admin-reset",
"webhookUrl": "https://voice.yourbank.com/twilio/events",
"callbackBaseUrl": "https://voice.yourbank.com/twilio/callbacks",
"inputSchemaUrl": "https://voice.yourbank.com/schemas/recovery-input.json",
"authType": "API_KEY",
"customHeaders": ["x-call-provider: twilio", "x-workflow: visual-recovery"],
"supportedLanguages": ["nodejs", "java", "php", "golang", "aspnet"],
"enableAutoResetEmail": true,
"enableAdminReset": true,
"enabled": true
}Request Schema
POST /api/demo-bank/agent/verify-otp
{
"requestId": "9f67d267-b0f1-4f74-9a77-bf59c9b1ec11",
"otp": "123456",
"agentName": "Twilio-Agent-01"
}Response Schema
200 OK
{
"ok": true,
"message": "Identity verified! Reset link sent to registered email.",
"emailSent": true,
"emailMasked": "su***@mail.com",
"linkExpiresInMinutes": 15,
"enrollUrl": "https://..."
}const res = await fetch("https://api.example.com/api/demo-bank/agent/verify-otp", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ requestId, otp, agentName: "Agent-01" })
});
const data = await res.json();HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/api/demo-bank/agent/send-otp"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());$ch = curl_init($baseUrl . '/api/demo-bank/agent/find-user'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['query' => $query])); $response = curl_exec($ch);
payload := []byte('{"requestId":"' + requestId + '","otp":"' + otp + '"}')
req, _ := http.NewRequest("POST", baseURL+"/api/demo-bank/agent/verify-otp", bytes.NewBuffer(payload))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)var payload = new { requestId, otp, agentName = "Agent-01" };
var response = await httpClient.PostAsJsonAsync(
"/api/demo-bank/agent/verify-otp",
payload
);
var result = await response.Content.ReadFromJsonAsync<object>();1. Keep admin token and partner key only in backend services.
2. Never expose outboundSecret to browser clients.
3. Enforce HTTPS for all callback and webhook URLs.
4. Keep admin-reset endpoint disabled unless needed.
5. Log agent name, request id, and timestamp for audits.