← Back to Documentation

Webhook Integration

Connect your backend to handle reasoning and business logic. VoiceRail sends you the conversation context; you return decisions and state updates.

How It Works

When you configure an assistant with a reasoningWebhook, VoiceRail calls your endpoint after each user utterance. Your webhook receives the full conversation context and returns the assistant's response.

  1. User speaks, VoiceRail transcribes
  2. VoiceRail sends user input + conversation history to your webhook
  3. Your webhook processes and returns a content response
  4. VoiceRail speaks the response back to the caller via TTS

Webhook Request

VoiceRail POSTs JSON to your webhook URL with this structure:

Request
// VoiceRail sends this to your webhook
POST /your-webhook-endpoint
Content-Type: application/json
Authorization: Bearer {your-configured-bearer-token}

{
  "model": "gpt-4o-mini",
  "assistantRole": "You are a helpful banking assistant...",
  "userInput": "What's my account balance?",
  "conversationHistory": [
    { "role": "assistant", "content": "Hi! How can I help you today?" },
    { "role": "user", "content": "What's my account balance?" }
  ],
  "additionalContext": "Call type: inbound\nTurn count: 2",
  "callId": "c9f2a1b3-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
  "organizationId": "org-abc123"
}

Request Fields

  • userInput - What the caller just said (transcribed speech)
  • conversationHistory - Array of { role, content } messages
  • callId - Unique identifier for this call
  • organizationId - Your organization ID
  • model - The model VoiceRail would have used (informational)
  • assistantRole - The assistant's system prompt / role description
  • additionalContext - Extra context (call direction, turn count, beat info)

Authentication: VoiceRail sends your configured bearer token in the Authorization: Bearer header.

Webhook Response

Your webhook returns JSON with the assistant's response:

Response
// Your webhook responds with
{
  "content": "Your current balance is $1,234.56. Is there anything else I can help with?",
  "confidenceScore": 4
}

Response Fields

  • content - (Required) What the assistant should say back to the caller
  • confidenceScore - (Optional) Integer 1-5, defaults to 3. Higher = more confident response
  • tokenUsage - (Optional) Token usage stats: { prompt_tokens, completion_tokens, total_tokens }

If the webhook fails or times out, VoiceRail falls back to its built-in LLM and continues the conversation automatically.

Full Example

A complete webhook handler for a banking assistant:

server.ts
import express from "express";
const app = express();
app.use(express.json());

app.post("/voicerail-webhook", async (req, res) => {
  const { userInput, conversationHistory, callId, organizationId } = req.body;

  // Verify bearer token (from Authorization header)
  const authHeader = req.headers.authorization;
  if (authHeader !== "Bearer your-secret-token") {
    return res.status(401).json({ error: "Unauthorized" });
  }

  // Handle balance inquiry
  if (userInput.toLowerCase().includes("balance")) {
    const balance = await fetchBalance(callId);
    return res.json({
      content: `Your current balance is $${balance.toFixed(2)}. Is there anything else I can help with?`,
      confidenceScore: 4
    });
  }

  // Handle transfer request
  if (userInput.toLowerCase().includes("transfer")) {
    return res.json({
      content: "I can help with that. How much would you like to transfer and to which account?",
      confidenceScore: 4
    });
  }

  // No specific action - return empty content to let VoiceRail's built-in LLM handle it
  return res.json({ content: "", confidenceScore: 1 });
});

app.listen(3000, () => console.log("Webhook running on port 3000"));

Best Practices

Keep it Fast

Your webhook runs async, but faster responses mean smoother conversations. Target under 500ms. Cache frequently accessed data.

Use Conversation History

The conversationHistory array gives you full context. Use it to maintain state across turns without needing external storage for simple use cases.

Graceful Fallback

If your webhook fails or times out, VoiceRail automatically falls back to its built-in LLM. The call never drops — the caller just gets a default response.

Handle Errors Gracefully

If your backend fails, return a helpful message. Don't let exceptions bubble up and break the call.

Timeouts & Retries

  • Timeout: Configurable per assistant (5-30 seconds, default 10s)
  • Retries: 2 automatic retries with exponential backoff (1s, 2s)
  • Circuit breaker: After 5 consecutive failures, the circuit opens for 30 seconds
  • Fallback: If all retries fail, VoiceRail's built-in LLM generates a response automatically

Next steps