Skip to main content

Event-Driven Automation

Webhooks turn Maia workflows into intelligent APIs that respond to external events — form submissions, payment notifications, chat messages, and more.
With webhooks, Maia becomes a serverless backend that processes inbound requests with AI-powered logic and returns structured responses.

How Webhooks Work

Basic Flow

1

Create Webhook

Deploy a workflow with webhook triggerMaia generates a unique URL:
https://hooks.modularmind.app/hooks/0nMMaZgKjmOirqosc8ohkeCuw9cV
2

External Event

Another system sends data to your webhook URL
curl -X POST https://webhooks.maia.app/wh_abc123xyz \
  -H "Content-Type: application/json" \
  -d '{"email": "john@example.com", "message": "Interested in demo"}'
3

Maia Processes

Your workflow receives the payload and executes
  • Parse incoming data
  • Run AI analysis, research, or generation
  • Use actions
4

Stream Response

Maia streams back the result via SSE events
event: response
data: {"status":200,"contentType":"application/json","body":"{\"lead_score\":85,\"recommendation\":\"High priority - schedule demo ASAP\"}"}

event: done
data: {}

Creating Webhook-Triggered Workflows

Simple Example: Lead Enrichment

Goal: When a contact form is submitted, enrich the lead data before adding to CRM. Workflow:
1. Receive form data (name, email, company)
2. Research company online (industry, size, funding)
3. Check LinkedIn for person's role
4. Calculate lead score (1-100)
5. Add to CRM with enriched data
6. Return lead score and priority
Deployment:
Maia provides webhook URL: https://hooks.modularmind.app/hooks/L3wKjb7iEMFTwMJFZsroWsSoc731
Usage: Your website form submits to this URL and receives an SSE stream. Once complete, the parsed response body contains:
{
  "lead_id": "CRM_12345",
  "score": 92,
  "priority": "hot",
  "reason": "Decision maker at Series B SaaS company"
}

Inbound Payload: Flexible Schema

Unlike traditional APIs that require strict schemas, Maia webhooks are intelligent.

Maia Understands Context

Send any data format, and Maia figures it out:
{
  "customer_email": "jane@example.com",
  "subject": "Need help with billing",
  "message": "I was charged twice this month"
}
Maia extracts:

Outbound Response: Controlling What Gets Returned

When deploying a webhook, you choose how Maia responds to incoming requests.

Default Response (Immediate)

If you don’t enable “Respond to webhook with data”, Maia returns immediately with one of these standard responses: Success:
{
  "type": "success",
  "message": "Workflow execution triggered successfully."
}
Error (Invalid Endpoint):
{
  "type": "error",
  "code": "invalid_endpoint",
  "message": "Invalid endpoint. Please check the path and try again."
}
Error (Disabled Endpoint):
{
  "type": "error",
  "code": "endpoint_disabled",
  "message": "This endpoint is currently disabled."
}
The workflow executes asynchronously, but the caller doesn’t wait for results.

Custom Data Response (SSE Streaming)

Enable “Respond to webhook with data” to return workflow outputs back to the caller via Server-Sent Events (SSE).
Webhook response configuration
When enabled, you define Body Parameters — exactly like configuring Custom Actions. This tells Maia what data to include in the response.
Maia uses SSE streaming instead of a standard JSON response. This keeps the connection alive while the workflow executes, preventing timeouts on long-running workflows.

Connection Protocol

When a webhook with response data enabled receives a request, the connection follows this lifecycle:
1

SSE Connection Established

The server responds with 200 OK and SSE headers:
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
2

Heartbeats During Processing

While the workflow executes, the server sends periodic heartbeat comments every 15 seconds to keep the connection alive:
: heartbeat
These are SSE comments and should be ignored by your client.
3

Response Event

When the workflow completes, the server sends a response event containing the result:
event: response
data: {"status":200,"contentType":"application/json","body":"{...}"}
For text-based responses (application/json, text/*), the body field contains the raw string. For binary responses (images, PDFs, ZIPs), the body is base64-encoded and an encoding: "base64" field is included.
4

Done Event

A done event signals the stream is complete:
event: done
data: {}
The connection closes after this event.

Error Handling

If the workflow fails to trigger, the server sends an error event instead:
event: error
data: {"type":"workflow_trigger_failed","message":"Failed to trigger workflow execution."}

Client Implementation Example

const eventSource = new EventSource('https://hooks.modularmind.app/hooks/your_hook_id', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'john@example.com' })
});

// Note: EventSource only supports GET requests.
// For POST requests, use fetch with a manual SSE parser:

const response = await fetch('https://hooks.modularmind.app/hooks/your_hook_id', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'john@example.com' })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const text = decoder.decode(value);
  const lines = text.split('\n');

  for (const line of lines) {
    if (line.startsWith('event: ')) {
      const eventName = line.slice(7);
      // Next data: line contains the payload
    }
    if (line.startsWith('data: ')) {
      const data = JSON.parse(line.slice(6));
      // Handle event data
    }
  }
}

Supported Response Types

Maia can return:
  • Text data in JSON format (structured responses) — delivered as-is in the body field
  • Images (JPEG, PNG) — base64-encoded in the body field with encoding: "base64"
  • Text files — delivered as-is in the body field
  • PDFs — base64-encoded in the body field with encoding: "base64"
  • ZIP files — base64-encoded in the body field with encoding: "base64"
Data, including files, can be generated throughout the workflow or downloaded from external sources.

Defining Response Parameters

For each parameter you want to return, specify: Name: The field name in the response (e.g., lead_score, generated_image, report_pdf) Description: Natural language explanation of what this field contains and where Maia should get the value from. This helps Maia understand which workflow outputs map to this response field. Type: The type of data (text, file, etc.)
Response parameter definitions work identically to body parameters in Custom Actions. See that section for detailed parameter configuration guidance.

Example: Lead Scoring Response

Configuration:
Body Parameters:
- Name: lead_id
  Description: The CRM record ID assigned to this lead

- Name: score
  Description: Calculated lead score from 1-100 based on company research

- Name: priority
  Description: Priority level (hot/warm/cold) based on the score

- Name: next_action
  Description: Recommended follow-up action for the sales team
SSE Stream:
: heartbeat

: heartbeat

event: response
data: {"status":200,"contentType":"application/json","body":"{\"lead_id\":\"CRM_54321\",\"score\":88,\"priority\":\"hot\",\"next_action\":\"Schedule demo within 24 hours\"}"}

event: done
data: {}
Parsed Response Body:
{
  "lead_id": "CRM_54321",
  "score": 88,
  "priority": "hot",
  "next_action": "Schedule demo within 24 hours"
}

Example: Document Generation Response

Configuration:
Body Parameters:
- Name: report_pdf
  Description: The generated PDF report file created by the workflow
  Type: File (base64)

- Name: summary
  Description: Brief text summary of the report contents
SSE Stream:
: heartbeat

: heartbeat

: heartbeat

event: response
data: {"status":200,"contentType":"application/json","body":"{\"report_pdf\":\"base64EncodedPdfData...\",\"summary\":\"Q4 2025 Sales Report - 23% growth, top performer: Enterprise segment\"}","encoding":"base64"}

event: done
data: {}
Parsed Response Body:
{
  "report_pdf": "base64EncodedPdfData...",
  "summary": "Q4 2025 Sales Report - 23% growth, top performer: Enterprise segment"
}

Real-World Webhook Examples

Example 1: Intelligent Chatbot Backend

Setup: Website chat widget → Maia webhook Workflow:
  1. Receive visitor message
  2. Search knowledge base using custom action
  3. If found: Generate helpful response
  4. If not found: Create support ticket via custom action, send notification
  5. Return response to chat widget
Request from caller:
{
  "visitor_id": "vis_123",
  "message": "What's your refund policy?",
  "page_url": "/pricing"
}
SSE stream received by caller:
: heartbeat

event: response
data: {"status":200,"contentType":"application/json","body":"{\"response\":\"We offer a 30-day money-back guarantee on all plans. If you're not satisfied, contact support@company.com for a full refund.\",\"confidence\":0.92,\"escalate\":false,\"source\":\"Help Center: Refund Policy\"}"}

event: done
data: {}
Parsed response body:
{
  "response": "We offer a 30-day money-back guarantee on all plans...",
  "confidence": 0.92,
  "escalate": false,
  "source": "Help Center: Refund Policy"
}
Result: Instant, accurate responses powered by AI, with human fallback.

Example 2: Invoice Processing

Setup: Email automation → Maia webhook Workflow:
  1. Receive invoice PDF as attachment
  2. Extract data (vendor, amount, due date, line items)
  3. Validate against purchase order using custom action
  4. Add to accounting system via custom action
  5. If > $5000, create approval request via custom action
  6. Return processing summary
Request from caller:
{
  "from": "vendor@supplier.com",
  "subject": "Invoice #12345",
  "attachment_url": "https://storage.../invoice.pdf"
}
SSE stream received by caller:
: heartbeat

: heartbeat

event: response
data: {"status":200,"contentType":"application/json","body":"{\"status\":\"processed\",\"invoice_number\":\"12345\",\"vendor\":\"ABC Supplier\",\"amount\":3250.00,\"due_date\":\"2026-01-15\",\"accounting_id\":\"INV_789\",\"approval_required\":false,\"line_items\":[{\"description\":\"Widget A\",\"quantity\":100,\"price\":25.00},{\"description\":\"Widget B\",\"quantity\":50,\"price\":15.00}]}"}

event: done
data: {}
Parsed response body:
{
  "status": "processed",
  "invoice_number": "12345",
  "vendor": "ABC Supplier",
  "amount": 3250.00,
  "due_date": "2026-01-15",
  "accounting_id": "INV_789",
  "approval_required": false,
  "line_items": [
    {"description": "Widget A", "quantity": 100, "price": 25.00},
    {"description": "Widget B", "quantity": 50, "price": 15.00}
  ]
}
Result: Automated invoice processing with data extraction and validation.

Example 3: Product Review Aggregator

Setup: Product review form → Maia webhook Workflow:
  1. Receive review text and rating
  2. Analyze sentiment (positive/negative/neutral)
  3. Extract key themes (quality, pricing, support, etc.)
  4. Check for spam/fake reviews
  5. If legitimate, publish to website via custom action
  6. If mentions bug/issue, create support ticket via custom action
  7. Return analysis
Request from caller:
{
  "product_id": "prod_456",
  "rating": 4,
  "review": "Great product! Works as advertised. Customer 
             support was responsive when I had a question 
             about setup. Only issue: shipping took longer 
             than expected.",
  "reviewer_email": "customer@example.com"
}
SSE stream received by caller:
: heartbeat

event: response
data: {"status":200,"contentType":"application/json","body":"{\"approved\":true,\"spam_score\":0.05,\"sentiment\":\"positive\",\"themes\":{\"product_quality\":\"positive\",\"customer_support\":\"positive\",\"shipping_speed\":\"negative\"},\"action_items\":[{\"type\":\"feedback\",\"category\":\"shipping\",\"message\":\"Customer experienced slow shipping\"}],\"published_url\":\"https://site.com/reviews/rev_123\"}"}

event: done
data: {}
Parsed response body:
{
  "approved": true,
  "spam_score": 0.05,
  "sentiment": "positive",
  "themes": {
    "product_quality": "positive",
    "customer_support": "positive",
    "shipping_speed": "negative"
  },
  "action_items": [
    {
      "type": "feedback",
      "category": "shipping",
      "message": "Customer experienced slow shipping"
    }
  ],
  "published_url": "https://site.com/reviews/rev_123"
}
Result: Intelligent review moderation with actionable insights.

Next: Security & Privacy

Learn how Maia protects your data and credentials