Admin Console

AI Calling Agent Guide

Backend integration guide for admin-controlled recovery agents with language-specific examples.

Recovery Flow

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.

Backend Settings API (No UI Required)

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"
]
Connect to Backend API with Environment URLs

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.

Production Integrations (Click Provider)

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://..." 
}
More software connections coming soon: Five9, NICE CXone, Vonage Contact Center, Cisco Webex Contact Center, and custom SIP bridges.
Node.js Example
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();
Java Example
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());
PHP Example
$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);
Go Example
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)
ASP.NET Example
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>();
Required Security Rules

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.