← Back to Documentation

Webhook Integration

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

How It Works

When you configure an assistant with reasoning_mode: "webhook", Aployee calls your endpoint after each user utterance. Your webhook runs asynchronously while the conversation agent keeps the dialogue flowing.

  1. User speaks, Aployee transcribes
  2. Aployee sends utterance + state + context to your webhook
  3. Your webhook processes and returns a reply + updated state
  4. Aployee blends the reply into the next natural turn

Webhook Request

Aployee POSTs JSON to your webhook URL with this structure:

Request
// Aployee sends this to your webhook
POST /your-webhook-endpoint
Content-Type: application/json

{
  "call_id": "call_abc123",
  "assistant_id": "asst_xyz789",
  "utterance": "What's my account balance?",
  "state": {
    "userId": "user_12345",
    "authenticated": true,
    "lastAction": "greeting"
  },
  "context": [
    { "role": "assistant", "content": "Hi! How can I help you today?" },
    { "role": "user", "content": "What's my account balance?" }
  ],
  "timestamp": "2024-01-15T10:30:00Z"
}

Request Fields

  • call_id - Unique identifier for this call
  • assistant_id - The assistant handling the call
  • utterance - What the user just said
  • state - JSON object persisted across the call
  • context - Recent dialogue history
  • timestamp - When the utterance was captured

Webhook Response

Your webhook returns JSON with an optional reply and updated state:

Response
// Your webhook responds with
{
  "reply": "Your current balance is $1,234.56. Is there anything else I can help with?",
  "state": {
    "userId": "user_12345",
    "authenticated": true,
    "lastAction": "balance_lookup",
    "lastBalance": 1234.56
  }
}

Response Fields

  • reply - (Optional) What the assistant should say
  • state - Updated state for the next turn

If you omit reply, Aployee's conversation agent generates a response based on the assistant's personality.

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("/aployee-webhook", async (req, res) => {
  const { utterance, state, context, call_id } = req.body;

  // Authentication check
  if (!state.authenticated) {
    return res.json({
      reply: "I'll need to verify your identity first. What's your account number?",
      state: { ...state, awaitingAccountNumber: true }
    });
  }

  // Handle balance inquiry
  if (utterance.toLowerCase().includes("balance")) {
    const balance = await fetchBalance(state.userId);
    return res.json({
      reply: `Your current balance is $${balance.toFixed(2)}. Anything else?`,
      state: { ...state, lastBalance: balance, lastAction: "balance_lookup" }
    });
  }

  // Handle transfer request
  if (utterance.toLowerCase().includes("transfer")) {
    return res.json({
      reply: "I can help with that. How much would you like to transfer and to which account?",
      state: { ...state, awaitingTransferDetails: true }
    });
  }

  // No specific action - let Aployee's conversation agent handle it
  return res.json({ state });
});

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 State Wisely

Store only what you need in state. For heavy data, store IDs and fetch from your database when needed.

Let Aployee Handle Small Talk

Don't return replies for greetings, confirmations, or chitchat. Omit reply and let the conversation agent handle it.

Handle Errors Gracefully

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

Timeouts & Retries

  • Timeout: Webhooks must respond within 10 seconds
  • Retries: No automatic retries. If your webhook fails, the conversation agent continues without your input
  • Fallback: If no reply is returned, the assistant responds naturally based on personality

Next steps