rtrvr.ai logo
rtrvr.ai
PricingBlogDashboard

Core Agent

Getting StartedWeb AgentSheets Workflows

Building Blocks

Recordings & GroundingTool CallingKnowledge Base (RAG)

Platform Access

CLI & SDKAPI OverviewAgent APIScrape APIBrowser as API/MCP

Automation

ShortcutsTriggersWebhooksSchedules

Account & Security

Cookie SyncPermissions & Privacy
DocsWebhooks

Webhooks

Trigger workflows from external systems and receive async completion callbacks with signatures and retries.

4 min read

Webhooks let external systems trigger rtrvr workflows via HTTP POST and let rtrvr send completion/failure callbacks back to your infrastructure. Use this for Zapier, Make, n8n, backend jobs, and server-to-server pipelines.

n8n + Extension Integration

Cloud Browser API from n8n

Need browser push-notification based automation instead? See /docs/triggers.

Platform Compatibility

PlatformHTTP TimeoutCompatibilityRecommended Approach
n8n100s (Cloud)ExcellentDirect calls work for most tasks
Make.comUp to 300sExcellentSet timeout to 120s+
Zapier30s fixedUse callbacksProvide webhookUrl for async results

Inbound Webhooks (Zapier, Make, n8n → rtrvr)

Any service that can send an HTTP POST can trigger rtrvr.ai workflows. Use the MCP endpoint to control your logged-in browser, or the /agent endpoint for cloud browser execution.

MCP Endpoint (Your Browser)

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
}

Agent Endpoint (Cloud Browser)

bash
POST https://api.rtrvr.ai/agent

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

Body:
{
  "input": "Extract company info and contact details",
  "urls": ["https://example.com"],
  "webhookUrl": "https://your-server.com/callback",
  "response": { "verbosity": "final" }
}

n8n Integration

n8n Cloud has a 100-second timeout — comfortably above most rtrvr task durations. Use either endpoint depending on whether you need your logged-in browser or a cloud browser.

json
// n8n → MCP (your logged-in browser)
{
  "method": "POST",
  "url": "https://mcp.rtrvr.ai",
  "body": {
    "tool": "planner",
    "params": {
      "user_input": "{{ $json.task_description }}",
      "tab_urls": ["{{ $json.target_url }}"]
    },
    "webhookUrl": "{{ $node.Webhook.url }}"
  }
}

// n8n → /agent (cloud browser)
{
  "method": "POST",
  "url": "https://api.rtrvr.ai/agent",
  "sendHeaders": true,
  "headerParameters": {
    "parameters": [
      { "name": "Authorization", "value": "Bearer {{ $credentials.rtrvrApiKey }}" },
      { "name": "Content-Type", "value": "application/json" }
    ]
  },
  "sendBody": true,
  "bodyParameters": {
    "parameters": [
      { "name": "input", "value": "={{ $json.taskDescription }}" },
      { "name": "urls", "value": "={{ [$json.targetUrl] }}" }
    ]
  }
}

Make (Integromat) Integration

Make's default timeout is 30 seconds. Click "Show advanced settings" and set Timeout to 120 seconds for reliable results.
  • 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

Zapier Integration

Zapier has a fixed 30-second HTTP timeout. Use the webhook pattern: Zap 1 triggers rtrvr with a webhookUrl pointing to a Catch Hook in Zap 2, which receives and processes the results.

  • Add a "Webhooks by Zapier" action to your Zap
  • Select "POST" as the method
  • Set URL to: https://mcp.rtrvr.ai
  • Add headers: Authorization = Bearer rtrvr_your_api_key, Content-Type = application/json
  • Set Data to your JSON payload (tool + params)
  • Set webhookUrl to a Catch Hook URL in a second Zap
json
// Example: 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/"
}

Available Tools

ToolUse CaseExecution
plannerComplex multi-step tasks from natural languageLocal or cloud browser
extractStructured data extraction with optional schemaLocal or cloud browser
actPage interactions (click, type, navigate)Local or cloud browser
crawlMulti-page crawling with extractionLocal or cloud browser
replay_workflowRe-run a previous workflow by ID or URLLocal or cloud browser
get_browser_tabsList open tabsLocal browser only
execute_javascriptRun JS in browser sandboxLocal browser only

Outbound Webhooks (rtrvr → Your Server)

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

Enabling Outbound Webhooks

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 Payloads

Success Payload

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

Error Payload

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
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;

  // Reject stale timestamps (> 5 minutes)
  if (Date.now() - parseInt(timestamp) > 300000) {
    return res.status(400).json({ error: 'Timestamp too old' });
  }

  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());
  // Process asynchronously — respond 200 immediately
  res.status(200).json({ received: true });
  processWebhook(data);
});
python
# Flask
import hmac, hashlib, time, os
from flask import Flask, request, jsonify

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')

    if abs(time.time() * 1000 - int(timestamp)) > 300000:
        return jsonify({'error': 'Timestamp too old'}), 400

    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
    return jsonify({'received': True})  # Process async

Retry Behavior

Failed deliveries are retried 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 immediately. Process webhook payloads asynchronously to avoid timeouts.

Common Patterns

Lead Enrichment Pipeline

New lead in CRM → rtrvr extracts company data → webhook returns enriched info → update CRM record.

json
// Trigger: New HubSpot contact
// Action: POST to https://api.rtrvr.ai/agent
{
  "input": "Visit this company website and extract: company size, industry, tech stack, and key contacts",
  "urls": ["{{contact.company_website}}"],
  "webhookUrl": "https://hooks.zapier.com/catch/123/enrich/",
  "response": { "verbosity": "final" }
}
// Webhook receives enriched data → Update CRM

Browser Trigger → Sheet Log (Zero Server)

The simplest pattern: monitor a site for notifications and log events to Google Sheets. No server, no API, no webhook endpoint needed.

  • Create a workflow that extracts data from the site and appends to a Google Sheet
  • Set up a Browser Trigger on that site with appropriate filters
  • Configure sheet output to "Append to same sheet on each run"
  • Every matching notification adds a row — building a running log automatically

Scheduled Price Monitoring

Cron schedule → rtrvr checks competitor prices → compare with previous data → alert if changed.

json
// Schedule: Daily at 9am via n8n Cron node
// Action: POST to https://api.rtrvr.ai/scrape
{
  "urls": [
    "https://competitor1.com/pricing",
    "https://competitor2.com/pricing"
  ]
}
// Compare extracted prices with yesterday's data
// If changed → Send Slack/email notification

Browser Trigger + Outbound Webhook (Hybrid)

text
Flow:
  1. Browser Trigger monitors slack.com for "deployment failed" notifications
  2. Trigger fires → workflow extracts error details from the Slack thread
  3. Workflow calls your server via rtrvr.ai API with webhookUrl set
  4. Server receives error details → creates a Jira ticket automatically

Result: Slack notification → browser extraction → server-side ticket creation
        No Slack API required — the browser does the heavy lifting

Authenticated Data Sync (MCP)

Your app triggers → rtrvr uses your logged-in browser via MCP → data synced to your database.

json
// Trigger: Webhook from your application
// Action: POST to https://mcp.rtrvr.ai
{
  "tool": "extract",
  "params": {
    "user_input": "Export my order history from the last 30 days",
    "tab_urls": ["https://vendor-portal.com/orders"]
  },
  "webhookUrl": "https://your-app.com/api/orders/sync"
}
// Your browser navigates using your login session
// Results sent to webhook → stored in database

Zapier → rtrvr → Zapier (Round-trip)

  • Zap 1: New Google Form submission → 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
app.post('/slack/commands', async (req, res) => {
  const { text, response_url } = req.body;
  res.status(200).json({ text: '🔄 Running extraction...' }); // Ack < 3s

  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 },
    }),
  });
});

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 });
});

Choosing the Right Approach

ApproachTrigger SignalBest ForAvailability
Browser TriggersPush notification in a tabSites without APIs — social media, chat, SaaS dashboardsWhile Chrome is open
SchedulesCron / interval timerPeriodic collection, monitoring, recurring reportsChrome or 24/7 cloud
Inbound WebhooksHTTP POST from external serviceZapier / Make / n8n, CI/CD, server-to-server24/7 cloud
All three approaches can output to Google Sheets, call custom tools, chain multi-step workflows, and include recordings for grounding. Mix and match.

Best Practices

  • Verify signatures on every callback in production
  • Implement idempotency to handle retries safely
  • Use HTTPS-only endpoints
  • Pass webhookMetadata for correlation IDs and routing context
Previous
Triggers
Next
Schedules

On this page

Platform CompatibilityInbound Webhooks (Zapier, Make, n8n → rtrvr)Outbound Webhooks (rtrvr → Your Server)Webhook PayloadsVerifying Webhook SignaturesRetry BehaviorCommon PatternsChoosing the Right ApproachBest Practices

Ready to automate?

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