Overview
Arlo can push real-time notifications to your agent when provider activity occurs. This is optional but strongly recommended — without it, your agent must poll for updates.
register_webhook
Register or update a webhook URL to receive real-time notifications.
Parameters
| Parameter | Type | Required | Description |
|---|
webhookUrl | string | Yes | URL for notifications (must be publicly accessible) |
webhookToken | string | No | Bearer token for webhook authentication |
deliveryContext | object | No | Platform-specific context included in webhooks |
conversationSessionKey | string | No | For threading webhook notifications |
sessionKey | string | No | Custom session key (auto-generated if not provided) |
Delivery Context
The deliveryContext object is passed through in every webhook payload:
{
"to": "+15551234567",
"channel": "whatsapp",
"deliver": true
}
| Field | Description |
|---|
to | Recipient identifier (e.g., phone number, chat ID) |
channel | Channel name (e.g., whatsapp, telegram, discord) |
deliver | Whether to deliver the notification to the user |
Validation
Before registration, Arlo validates the webhook URL:
- Pattern check — Rejects private IPs, localhost, etc.
- Connectivity test — Verifies the URL is reachable
The URL must be publicly accessible. Use ngrok, Cloudflare Tunnel, Tailscale Funnel (.ts.net), or a public server.
Returns
{
"success": true,
"webhookUrl": "https://your-agent/hooks/arlo",
"hasSecret": true,
"hasDeliveryContext": true,
"sessionKey": "session_abc123"
}
get_webhook_status
Check webhook status for the authenticated user’s session.
Parameters
| Parameter | Type | Required | Description |
|---|
sessionKey | string | No | Check a specific session (returns all sessions if omitted) |
Returns (Specific Session)
{
"configured": true,
"sessionKey": "session_abc123",
"webhookUrl": "https://your-agent/hooks/arlo",
"hasSecret": true,
"hasDeliveryContext": true,
"conversationSessionKey": "session_xyz",
"linkedAt": "2025-03-15T10:30:00Z"
}
Returns (All Sessions)
{
"configured": true,
"sessionCount": 2,
"sessions": [
{
"sessionKey": "session_abc123",
"webhookUrl": "https://your-agent/hooks/arlo",
"hasSecret": true,
"hasDeliveryContext": true
},
{
"sessionKey": "session_def456",
"webhookUrl": "https://other-agent/webhooks",
"hasSecret": false,
"hasDeliveryContext": false
}
]
}
Webhook Configuration
During init_signup
Webhooks can also be configured during init_signup:
{
"baseUrl": "https://mcp.arlohealth.ai",
"webhookUrl": "https://your-agent/hooks/arlo",
"webhookToken": "your-secret-token",
"deliveryContext": {
"to": "+15551234567",
"channel": "whatsapp",
"deliver": true
},
"conversationSessionKey": "session_xyz"
}
After Authentication
Use register_webhook to configure or update webhooks after the user is authenticated:
{
"webhookUrl": "https://your-agent/hooks/arlo",
"webhookToken": "your-secret-token",
"deliveryContext": {
"to": "+15551234567",
"channel": "whatsapp",
"deliver": true
},
"conversationSessionKey": "session_xyz"
}
If init_signup is called without webhookUrl, any existing webhook configuration is preserved.
Webhook Payload
All notifications are sent as POST {webhookUrl} with:
Authorization: Bearer <webhookToken>
Content-Type: application/json
Body
{
"text": "[Arlo] You have a new message from your healthcare provider.",
"mode": "now",
"conversationId": "conv_abc123",
"deliveryContext": {
"to": "+15551234567",
"channel": "whatsapp",
"deliver": true
},
"conversationSessionKey": "session_xyz"
}
| Field | Description |
|---|
text | Human-readable notification message |
mode | Always now |
conversationId | The conversation ID (when applicable) |
deliveryContext | Your original delivery context (passed through) |
conversationSessionKey | Your session key (for threading) |
Notification Types
| Event | text value |
|---|
| Provider sent a message | [Arlo] You have a new message from your healthcare provider. Check the consultation for their response. |
| AI triage responded | [Arlo] The AI triage assistant has responded. Check the consultation for updates. |
| Provider connected | [Arlo] Your consultation is now active. |
| Consultation closed | [Arlo] Your consultation has been closed. |
| Auth completed | [Arlo] <UserName> has successfully connected to Arlo Health. |
Security note: Notification payloads never include message content. Your agent should fetch the full context from the API after receiving a webhook. This prevents prompt injection from untrusted provider input.
Verifying Requests
Always validate the Authorization header matches your webhookToken:
app.post("/hooks/arlo", (req, res) => {
const token = req.headers.authorization?.replace("Bearer ", "");
if (token !== process.env.ARLO_WEBHOOK_SECRET) {
return res.status(401).json({ error: "Unauthorized" });
}
// Process notification
const { consultationId, text } = req.body;
// Acknowledge immediately
res.status(200).json({ received: true });
// Then fetch full context
processNotification(consultationId);
});
Handling Notifications
When a notification arrives:
- Acknowledge immediately with
200 OK — Arlo does not wait for processing
- Fetch the consultation to get the latest messages
- Read the most recent message and decide how to respond
- Do not include raw provider message text in your agent’s context — fetch it through the API where it is wrapped with safety boundaries
Example Handler
async function processNotification(consultationId) {
// Fetch full consultation status
const status = await getConsultationStatus({
conversationId: consultationId,
includeMessages: true
});
// Get the latest message
const latestMessage = status.messages[status.messages.length - 1];
if (latestMessage.sender === "provider") {
// Provider sent a message - notify user and/or respond
await notifyUser(latestMessage.content);
}
if (status.status === "CLOSED") {
// Consultation ended - get clinical notes
const notes = await getConsultationNotes({
conversationId: consultationId
});
await sendSummaryToUser(notes);
}
}
Re-authentication
If a session expires and the user re-authenticates:
init_signup must be called again with webhook params to re-register the URL
- If
init_signup is called without webhookUrl, the existing webhook config is preserved
Troubleshooting
Webhook not receiving notifications
- Verify URL is publicly accessible (not localhost or VPN)
- Check that HTTPS is enabled
- Verify the URL responds with 200 status
- Use
get_webhook_status to verify the webhook is configured
Invalid signature errors
- Verify
webhookToken matches what was passed to register_webhook or init_signup
- Check for URL encoding issues in the token
- Ensure you’re comparing the raw token, not base64 encoded
Missed notifications
- Notifications are not retried on failure
- Ensure your endpoint responds quickly (< 5 seconds)
- Process notifications asynchronously after acknowledging