> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opencompany.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks & HTTP

> HTTP requests and webhook handling nodes

# Webhooks & HTTP

Make HTTP requests to external APIs and receive incoming webhooks.

## Available Nodes

| Node             | Type                  | Purpose                                |
| ---------------- | --------------------- | -------------------------------------- |
| HTTP Request     | Action (also AI tool) | Make outgoing HTTP calls               |
| Webhook Trigger  | Trigger               | Receive incoming HTTP requests         |
| Webhook Response | Action                | Send custom response to webhook caller |

MachinaOs also ships other event-based triggers that start a workflow the same way Webhook Trigger does:

| Trigger        | Fires when                                                   |
| -------------- | ------------------------------------------------------------ |
| Chat Trigger   | A message is sent from the Console panel's chat tab          |
| Task Completed | A delegated child agent finishes its task (success or error) |

<Info>
  Trigger nodes only start firing once a workflow is **deployed**. Deploy from the toolbar; a saved-but-not-deployed workflow does not listen for events.
</Info>

***

## HTTP Request

Make HTTP requests to external APIs and services.

### Parameters

<ParamField path="url" type="string" required>
  The URL to request. Supports template variables.
</ParamField>

<ParamField path="method" type="select" default="GET">
  HTTP method: GET, POST, PUT, DELETE, PATCH
</ParamField>

<ParamField path="headers" type="json">
  Request headers as JSON object
</ParamField>

<ParamField path="body" type="string">
  Request body (JSON object or raw string). Only sent for POST, PUT, and PATCH; ignored for GET and DELETE.
</ParamField>

<ParamField path="timeout" type="number" default="30">
  Request timeout in seconds (1-600)
</ParamField>

<ParamField path="use_proxy" type="boolean" default="false">
  Route the request through a residential proxy provider. When enabled, you can also set `proxy_provider` (default `auto`), `proxy_country` (ISO code), and `session_type` (rotating or sticky).
</ParamField>

### Output

```json theme={null}
{
  "status": 200,
  "data": {
    "result": "response data"
  },
  "headers": {
    "content-type": "application/json"
  },
  "url": "https://api.example.com/users/42",
  "method": "GET",
  "proxied": false
}
```

<Info>
  HTTP Request is also a **dual-purpose tool** — connect it to an AI Agent's tools handle and the agent can make HTTP calls on its own.
</Info>

### Examples

**GET Request:**

```
URL: https://api.example.com/users/{{input.user_id}}
Method: GET
Headers: {"Authorization": "Bearer {{input.token}}"}
```

**POST Request:**

```
URL: https://api.example.com/orders
Method: POST
Headers: {"Content-Type": "application/json"}
Body: {"product": "{{input.product}}", "quantity": {{input.qty}}}
```

**External API Integration:**

```
URL: https://api.openweathermap.org/data/2.5/weather?q={{input.city}}&appid=YOUR_KEY
Method: GET
```

***

## Webhook Trigger

Receive incoming HTTP requests at a dynamic endpoint.

### Parameters

<ParamField path="path" type="string">
  The webhook path (e.g., "orders" creates /webhook/orders)
</ParamField>

<ParamField path="method" type="select" default="POST">
  HTTP method filter: GET, POST, PUT, DELETE, or ALL (ALL accepts any method)
</ParamField>

<ParamField path="response_mode" type="select" default="immediate">
  How to respond to the caller. `immediate` returns 200 OK right away. `responseNode` waits for a downstream Webhook Response node to send the reply.
</ParamField>

<ParamField path="authentication" type="select" default="none">
  Auth method: `none` (no auth) or `header` (require a matching header)
</ParamField>

<ParamField path="header_name" type="string" default="X-API-Key">
  Header name to check (when authentication is `header`)
</ParamField>

<ParamField path="header_value" type="string">
  Expected header value (when authentication is `header`)
</ParamField>

### Webhook URL

Your webhook will be available at:

```
http://localhost:3010/webhook/{path}
```

For production:

```
https://your-domain.com/webhook/{path}
```

### Output

```json theme={null}
{
  "method": "POST",
  "path": "orders",
  "headers": {
    "content-type": "application/json",
    "user-agent": "curl/7.68.0"
  },
  "query": {
    "source": "website"
  },
  "body": "{\"order_id\": \"12345\", \"items\": [\"item1\", \"item2\"]}",
  "json": {
    "order_id": "12345",
    "items": ["item1", "item2"]
  }
}
```

<Info>
  `body` holds the raw request text; `json` holds the parsed object when the request has a JSON content type. Reference either in downstream nodes, e.g. `{{webhookTrigger.json.order_id}}`.
</Info>

### Authentication Options

| Type   | Description                                                                             |
| ------ | --------------------------------------------------------------------------------------- |
| None   | No authentication — any request is accepted                                             |
| Header | Require a matching header. Set the header name (default `X-API-Key`) and expected value |

***

## Webhook Response

Send a custom response back to the webhook caller.

### Parameters

<ParamField path="status_code" type="number" default="200">
  HTTP status code to return (100-599)
</ParamField>

<ParamField path="body" type="string">
  Response body. Supports template variables like `{{input.key}}` and `{{nodeType.key}}` resolved from connected node outputs. When left empty, the first connected output is returned as JSON.
</ParamField>

<ParamField path="content_type" type="string" default="application/json">
  Content-Type header (e.g., `application/json`, `text/plain`, `text/html`)
</ParamField>

<ParamField path="headers" type="json">
  Additional response headers as a JSON object
</ParamField>

<Warning>
  For Webhook Response to actually reach the caller, set the Webhook Trigger's **Response Mode** to `responseNode`. In `immediate` mode the trigger returns 200 OK right away and any downstream response is ignored.
</Warning>

### Example Responses

**Success Response:**

```
Status Code: 200
Body: {"success": true, "message": "Order received", "id": "{{generated.id}}"}
Content Type: application/json
```

**Error Response:**

```
Status Code: 400
Body: {"error": "Invalid request", "details": "{{validation.error}}"}
Content Type: application/json
```

**HTML Response:**

```
Status Code: 200
Body: <html><body><h1>Thank you!</h1></body></html>
Content Type: text/html
```

***

## Common Workflows

### API Endpoint

Create a simple API endpoint:

```
[Webhook Trigger] --> [Python Executor] --> [Webhook Response]
     (path: api)        (process data)       (return result)
```

**Test:**

```bash theme={null}
curl -X POST http://localhost:3010/webhook/api \
  -H "Content-Type: application/json" \
  -d '{"action": "calculate", "value": 100}'
```

### Third-Party Integration

Receive events from external services:

```
[Webhook Trigger] --> [HTTP Request] --> [WhatsApp Send]
   (stripe/github)     (fetch details)     (notify admin)
```

### Data Pipeline

Forward data to multiple destinations:

```
[Webhook Trigger] --> [HTTP Request #1] (Database API)
                  |
                  --> [HTTP Request #2] (Analytics)
                  |
                  --> [WhatsApp Send] (Notification)
```

### AI-Powered API

Create an AI endpoint:

```
[Webhook Trigger] --> [AI Agent] --> [Webhook Response]
                          ^
                    [Chat Model]
```

**Prompt:** `{{webhookTrigger.json.prompt}}`

**Response:** `{{aiAgent.response}}`

<Tip>
  Wire a chat model node (OpenAI, Anthropic, Gemini, and more — see [AI Models](/nodes/ai-models)) into the AI Agent's model handle to power the endpoint.
</Tip>

***

## Testing Webhooks

### Using curl

```bash theme={null}
# GET request
curl http://localhost:3010/webhook/test

# POST with JSON
curl -X POST http://localhost:3010/webhook/orders \
  -H "Content-Type: application/json" \
  -d '{"item": "Widget", "quantity": 5}'

# With authentication
curl -X POST http://localhost:3010/webhook/secure \
  -H "Authorization: Bearer your-token" \
  -d '{"data": "value"}'
```

### Using HTTPie

```bash theme={null}
http POST localhost:3010/webhook/test item=Widget quantity:=5
```

### External Testing

Use services like:

* [webhook.site](https://webhook.site) - Test outgoing webhooks
* [ngrok](https://ngrok.com) - Expose local webhooks publicly

***

## Tips

<Tip>
  Use **meaningful paths** that describe the purpose: `/webhook/orders`, `/webhook/stripe-events`
</Tip>

<Tip>
  Always **validate incoming data** before processing with Python Executor or similar.
</Tip>

<Tip>
  Return **appropriate status codes**: 200 (success), 400 (bad request), 500 (server error)
</Tip>

<Warning>
  In production, always enable authentication on webhooks that modify data.
</Warning>

***

## Troubleshooting

<Accordion title="Webhook not receiving requests">
  * Verify workflow is **deployed** (not just saved)
  * Check the path is correct (no leading slash)
  * Ensure backend is running on correct port
  * Check firewall/network settings
</Accordion>

<Accordion title="HTTP Request fails">
  * Verify URL is correct and accessible
  * Check headers (especially Content-Type)
  * Look for CORS issues if calling from browser
  * Check timeout setting for slow APIs
</Accordion>

<Accordion title="Response not sent">
  * Ensure Webhook Response is connected to workflow
  * Verify template variables resolve correctly
  * Check status code is valid (100-599)
</Accordion>

***

## Related

<CardGroup cols={2}>
  <Card title="Quick Start" icon="rocket" href="/quickstart">
    Build a webhook workflow
  </Card>

  <Card title="Tools" icon="code" href="/nodes/tools">
    Process webhook data with Python and other tools
  </Card>
</CardGroup>
