rtrvr.ai logo
rtrvr.ai
Blog
Book Demo
Pricing
API Docs

Getting Started

  • Introduction
  • Quick Start

Capabilities

  • Web Agent
  • Sheets Workflows

API

  • API Overview
  • Agent API
  • Scrape API
  • Browser as API/MCP

Advanced

  • Tool Calling
  • Recordings
  • Webhooks
    • Webhook Events
    • Setting Up
    • Payload Format
    • Security
    • Verifying Webhooks
    • Retry Logic
    • Use Cases
  • Schedules
DocsWebhooks

Webhooks

Inbound triggers from external services and outbound notifications on workflow completion.

3 min read

rtrvr.ai supports both inbound webhooks (receive triggers from Zapier, Make, n8n, etc.) and outbound webhooks (send results to your server when workflows complete).

Inbound Webhooks (Zapier, Make, n8n → rtrvr)

Your mcp.rtrvr.ai endpoint is already webhook-ready. Any service that can send an HTTP POST can trigger rtrvr.ai workflows—no special configuration needed.

This is the same endpoint used for MCP and direct API calls. It accepts JSON payloads with tool + params and routes them to your browser or our cloud infrastructure.

Webhook Endpoint

text
POST https://mcp.rtrvr.ai

Headers:
  Authorization: Bearer rtrvr_your_api_key
  Content-Type: application/json

Body:
{
  "tool": "planner" | "extract" | "act" | "crawl" | "replay_workflow" | ...,
  "params": { ... tool-specific parameters ... },
  "deviceId": "optional_device_id",
  "webhookUrl": "https://your-server.com/callback"  // Optional: receive results here
}

Zapier Integration

Use Zapier's 'Webhooks by Zapier' action to trigger rtrvr.ai workflows from any Zapier trigger (new email, form submission, calendar event, etc.).

  • Add a 'Webhooks by Zapier' action to your Zap
  • Select 'POST' as the method
  • Set URL to: https://mcp.rtrvr.ai
  • Add header: Authorization = Bearer rtrvr_your_api_key
  • Add header: Content-Type = application/json
  • Set Data to your JSON payload (tool + params)
json
// Example Zapier payload: Extract data when a new row is added to Google Sheets
{
  "tool": "extract",
  "params": {
    "user_input": "Extract the company name, employee count, and funding info",
    "tab_urls": ["{{Google Sheets Row URL}}"]
  },
  "webhookUrl": "https://hooks.zapier.com/hooks/catch/123/abc/"
}

Make (Integromat) Integration

Use Make's HTTP module to call rtrvr.ai:

  • Add an 'HTTP > Make a request' module
  • URL: https://mcp.rtrvr.ai
  • Method: POST
  • Headers: Authorization (Bearer token), Content-Type (application/json)
  • Body type: Raw, Content type: JSON
  • Request content: Your tool + params JSON

n8n Integration

json
// n8n HTTP Request node configuration
{
  "method": "POST",
  "url": "https://mcp.rtrvr.ai",
  "authentication": "genericCredentialType",
  "genericAuthType": "httpHeaderAuth",
  "options": {
    "headers": {
      "Content-Type": "application/json"
    }
  },
  "body": {
    "tool": "planner",
    "params": {
      "user_input": "{{ $json.task_description }}",
      "tab_urls": ["{{ $json.target_url }}"]
    },
    "webhookUrl": "{{ $node.Webhook.url }}"
  }
}

Available Tools for Inbound Webhooks

ToolUse CaseExecution
plannerComplex multi-step tasks from natural languageBrowser (local or cloud)
extractStructured data extraction with optional schemaBrowser (local or cloud)
actPage interactions (click, type, navigate)Browser (local or cloud)
crawlMulti-page crawling with extractionBrowser (local or cloud)
replay_workflowRe-run a previous workflow by ID or shared URLBrowser (local or cloud)
get_browser_tabsList open tabs (local browser only)Local browser
execute_javascriptRun JS in browser sandboxLocal browser
For local browser tools, ensure your Chrome extension is online. For cloud execution, tools run on rtrvr.ai's infrastructure—no extension needed.

Outbound Webhooks (rtrvr → Your Server)

Include a webhookUrl in your request to receive results when the workflow completes. rtrvr.ai will POST the full response to your endpoint.

Enabling Outbound Webhooks

Add webhookUrl to any API request:

bash
curl -X POST "https://mcp.rtrvr.ai" \
  -H "Authorization: Bearer rtrvr_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "planner",
    "params": {
      "user_input": "Find pricing for iPhone 16 Pro on Apple.com",
      "tab_urls": ["https://apple.com"]
    },
    "webhookUrl": "https://your-server.com/rtrvr-callback",
    "webhookSecret": "your_hmac_secret"
  }'

Webhook Payload Format

Your endpoint will receive a POST with this structure:

json
{
  "event": "workflow.completed",
  "timestamp": "2025-01-15T12:00:00.000Z",
  "requestId": "req_abc123xyz",
  "success": true,
  "data": {
    // Tool-specific response data
    "taskCompleted": true,
    "output": { ... },
    "extractedData": [ ... ],
    "creditsUsed": 5
  },
  "metadata": {
    "tool": "planner",
    "deviceId": "dj75mmaTWP0",
    "executionTime": 15234,
    "creditsRemaining": 9995
  },
  "originalRequest": {
    "tool": "planner",
    "params": { ... }
  }
}

Error Payloads

json
{
  "event": "workflow.failed",
  "timestamp": "2025-01-15T12:00:00.000Z",
  "requestId": "req_abc123xyz",
  "success": false,
  "error": {
    "message": "Device offline: no available browser extensions",
    "code": "DEVICE_UNAVAILABLE",
    "details": { ... }
  },
  "metadata": {
    "tool": "planner",
    "executionTime": 1234
  }
}

Verifying Webhook Signatures

If you provide a webhookSecret, rtrvr.ai signs the payload with HMAC-SHA256. Verify it to ensure authenticity:

typescript
// Express.js example
import crypto from 'crypto';

app.post('/rtrvr-callback', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-rtrvr-signature'] as string;
  const timestamp = req.headers['x-rtrvr-timestamp'] as string;
  
  // Verify timestamp is recent (prevent replay attacks)
  const age = Date.now() - parseInt(timestamp);
  if (age > 300000) { // 5 minutes
    return res.status(400).json({ error: 'Timestamp too old' });
  }
  
  // Verify HMAC signature
  const payload = timestamp + '.' + req.body.toString();
  const expected = crypto
    .createHmac('sha256', process.env.RTRVR_WEBHOOK_SECRET!)
    .update(payload)
    .digest('hex');
  
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  const data = JSON.parse(req.body.toString());
  console.log('Verified webhook:', data);
  
  res.status(200).json({ received: true });
});
python
# Flask example
import hmac
import hashlib
import time
from flask import Flask, request, jsonify

app = Flask(__name__)
WEBHOOK_SECRET = os.environ['RTRVR_WEBHOOK_SECRET']

@app.route('/rtrvr-callback', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Rtrvr-Signature')
    timestamp = request.headers.get('X-Rtrvr-Timestamp')
    
    # Verify timestamp
    if abs(time.time() * 1000 - int(timestamp)) > 300000:
        return jsonify({'error': 'Timestamp too old'}), 400
    
    # Verify signature
    payload = f"{timestamp}.{request.data.decode()}"
    expected = hmac.new(
        WEBHOOK_SECRET.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    
    if not hmac.compare_digest(signature, expected):
        return jsonify({'error': 'Invalid signature'}), 401
    
    data = request.json
    print(f"Verified webhook: {data}")
    
    return jsonify({'received': True})

Retry Logic

If your endpoint fails to respond with 2xx, rtrvr.ai retries with exponential backoff:

  • Attempt 1: Immediate
  • Attempt 2: After 5 seconds
  • Attempt 3: After 30 seconds
  • Attempt 4: After 2 minutes
  • Attempt 5: After 10 minutes (final)
Respond with 200 OK as quickly as possible. Process the webhook payload asynchronously to avoid timeouts.

Common Webhook Patterns

Zapier → rtrvr → Zapier (Round-trip)

Trigger a workflow from Zapier, then catch the results in another Zap:

  • Zap 1: New Google Form submission → Webhooks by Zapier POST to mcp.rtrvr.ai (include webhookUrl pointing to Zap 2)
  • Zap 2: Catch Hook receives results → Add row to Google Sheets

Slack Command → rtrvr → Slack Message

typescript
// Your server receives Slack slash command
app.post('/slack/commands', async (req, res) => {
  const { text, response_url } = req.body;
  
  // Acknowledge immediately (Slack requires < 3s response)
  res.status(200).json({ text: '🔄 Running extraction...' });
  
  // Trigger rtrvr.ai with Slack's response_url as webhook
  await fetch('https://mcp.rtrvr.ai', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer rtrvr_xxx',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      tool: 'extract',
      params: {
        user_input: text,
        tab_urls: [extractUrlFromText(text)],
      },
      webhookUrl: 'https://your-server.com/slack-callback',
      webhookMetadata: { response_url }, // Pass through for callback
    }),
  });
});

// Receive results and post to Slack
app.post('/slack-callback', async (req, res) => {
  const { data, originalRequest } = req.body;
  const { response_url } = originalRequest.webhookMetadata;
  
  await fetch(response_url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      text: `✅ Extracted: ${JSON.stringify(data.extractedData, null, 2)}`,
    }),
  });
  
  res.status(200).json({ received: true });
});

Scheduled Monitoring with Webhooks

Combine schedules with webhooks to build monitoring pipelines:

json
// Schedule configuration (via Cloud dashboard or API)
{
  "name": "Competitor Price Monitor",
  "schedule": "0 9 * * *",
  "request": {
    "tool": "extract",
    "params": {
      "user_input": "Extract all product prices",
      "tab_urls": ["https://competitor.com/products"],
      "schema": {
        "fields": [
          { "name": "product", "type": "string" },
          { "name": "price", "type": "number" }
        ]
      }
    },
    "webhookUrl": "https://your-server.com/price-monitor"
  }
}

Best Practices

  • Always verify webhook signatures in production
  • Respond with 200 immediately, process async
  • Store a requestId mapping to correlate requests with callbacks
  • Use webhookMetadata to pass through context you'll need in the callback
  • Implement idempotency—you may receive the same webhook twice on retries
  • Set up alerting for failed webhook deliveries
  • Use HTTPS endpoints only (HTTP will be rejected)
Webhooks enable powerful async workflows. Combine inbound triggers from Zapier/Make with outbound callbacks to build end-to-end automation without polling.
Previous
Tool Calling
Next
Schedules

Ready to automate?

Join teams using rtrvr.ai to build playful, powerful web automation workflows.

rtrvr.ai logo
rtrvr.ai

Retrieve, Research, Robotize the Web

By subscribing, you agree to receive marketing emails from rtrvr.ai. You can unsubscribe at any time.

Product

  • API & MCPNEW
  • Browser Extension
  • Cloud Platform
  • Templates
  • WhatsApp Bot
  • RoverSOON

Use Cases

  • Vibe Scraping
  • Lead Enrichment
  • Agentic Form Filling
  • Web Monitoring
  • Social Media
  • Job Applications
  • Data Migration
  • AI Web Context
  • Agentic Checkout

Compare

  • rtrvr vs Apify
  • rtrvr vs Bardeen
  • rtrvr vs Browserbase
  • rtrvr vs Browser Use
  • rtrvr vs Clay
  • rtrvr vs Claude
  • rtrvr vs Comet
  • rtrvr vs Firecrawl

Resources

  • Documentation
  • Blog
  • Changelog
  • Integrations
  • Pricing
  • Book Demo
  • Affiliate Program

Company

  • Team
  • Contact
  • GCP Partner
  • Privacy Policy
  • Terms of Service
  • Security Brief
support@rtrvr.ai

© 2026 rtrvr.ai. All rights reserved.

Made withfor the automation community