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

# HTTP Node

> Make outbound HTTP requests to external services

The `http` node makes HTTP requests to external APIs. It supports all standard HTTP methods, custom headers, query parameters, and request bodies.

## Configuration

```json theme={null}
{
  "id": "fetch_user",
  "type": "http",
  "config": {
    "method": "GET",
    "url": "https://api.example.com/users/{{user_id}}",
    "headers": {
      "Authorization": "Bearer {{env.API_KEY}}"
    },
    "timeout": 10000
  }
}
```

## Config Fields

| Field          | Type   | Required | Default   | Description                                         |
| -------------- | ------ | -------- | --------- | --------------------------------------------------- |
| `url`          | string | Yes      | -         | Request URL (supports templates)                    |
| `method`       | string | No       | `"GET"`   | HTTP method                                         |
| `headers`      | object | No       | -         | Request headers                                     |
| `query`        | object | No       | -         | Query string parameters                             |
| `body`         | any    | No       | -         | Request body                                        |
| `body_type`    | string | No       | `"json"`  | Body format: `"json"`, `"form"`, or `"multipart"`   |
| `files`        | array  | No       | -         | Files to upload (auto-sets body\_type to multipart) |
| `timeout`      | number | No       | `30000`   | Timeout in milliseconds (max 60000)                 |
| `content_type` | string | No       | auto      | Content-Type header                                 |
| `on_error`     | string | No       | `"abort"` | Error handling: `"abort"` or `"continue"`           |

## HTTP Methods

Supported methods: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`

```json theme={null}
{ "method": "GET" }
{ "method": "POST" }
{ "method": "PUT" }
{ "method": "DELETE" }
{ "method": "PATCH" }
```

## Output

```json theme={null}
{
  "status_code": 200,
  "headers": {
    "content-type": "application/json",
    "x-request-id": "abc123"
  },
  "body": {
    "id": 1,
    "name": "John Doe"
  },
  "latency_ms": 150,
  "success": true,
  "error": null
}
```

| Field         | Type    | Description                                      |
| ------------- | ------- | ------------------------------------------------ |
| `status_code` | number  | HTTP status code                                 |
| `headers`     | object  | Response headers                                 |
| `body`        | any     | Response body (auto-parsed if JSON)              |
| `latency_ms`  | number  | Request duration in milliseconds                 |
| `success`     | boolean | `true` if status is 2xx                          |
| `error`       | string  | Error message (only with `on_error: "continue"`) |

## Examples

### GET Request

```json theme={null}
{
  "id": "get_user",
  "type": "http",
  "config": {
    "method": "GET",
    "url": "https://api.example.com/users/{{request.query.user_id}}"
  }
}
```

### GET with Query Parameters

```json theme={null}
{
  "id": "search_users",
  "type": "http",
  "config": {
    "method": "GET",
    "url": "https://api.example.com/users",
    "query": {
      "search": "{{request.query.q}}",
      "limit": "10",
      "offset": "{{request.query.page | multiply:10}}"
    }
  }
}
```

### POST with JSON Body

```json theme={null}
{
  "id": "create_user",
  "type": "http",
  "config": {
    "method": "POST",
    "url": "https://api.example.com/users",
    "headers": {
      "Authorization": "Bearer {{env.API_KEY}}",
      "Content-Type": "application/json"
    },
    "body": {
      "name": "{{request.body.name}}",
      "email": "{{request.body.email}}",
      "role": "user"
    }
  }
}
```

### PUT Request

```json theme={null}
{
  "id": "update_user",
  "type": "http",
  "config": {
    "method": "PUT",
    "url": "https://api.example.com/users/{{user_id}}",
    "body": {
      "name": "{{request.body.name}}",
      "updated_at": "{{now}}"
    }
  }
}
```

### DELETE Request

```json theme={null}
{
  "id": "delete_user",
  "type": "http",
  "config": {
    "method": "DELETE",
    "url": "https://api.example.com/users/{{request.body.user_id}}"
  }
}
```

### With Custom Headers

```json theme={null}
{
  "id": "api_call",
  "type": "http",
  "config": {
    "method": "POST",
    "url": "https://api.example.com/webhook",
    "headers": {
      "Authorization": "Bearer {{env.API_TOKEN}}",
      "X-Request-ID": "{{request_id}}",
      "X-Timestamp": "{{now}}",
      "Accept": "application/json"
    },
    "body": "{{payload}}"
  }
}
```

### With Timeout

```json theme={null}
{
  "id": "slow_api",
  "type": "http",
  "config": {
    "url": "https://slow-api.example.com/process",
    "timeout": 60000
  }
}
```

## Error Handling

### `on_error: "abort"` (default)

If the request fails (network error, timeout, non-2xx status), the flow stops immediately.

```json theme={null}
{
  "id": "critical_api",
  "type": "http",
  "config": {
    "url": "https://api.example.com/critical",
    "on_error": "abort"
  }
}
```

### `on_error: "continue"`

Errors are captured in the output instead of failing the flow:

```json theme={null}
{
  "id": "optional_api",
  "type": "http",
  "config": {
    "url": "https://api.example.com/optional",
    "on_error": "continue"
  }
}
```

Then check the result:

```json theme={null}
{
  "id": "check_result",
  "type": "condition",
  "config": {
    "conditions": [
      {
        "if": "{{optional_api.output.success}} == true",
        "then": ["process_data"]
      }
    ],
    "else": ["use_fallback"]
  }
}
```

## Body Handling

### JSON Body (default)

Objects are automatically serialized as JSON:

```json theme={null}
{
  "body": {
    "name": "John",
    "age": 30
  }
}
```

### Form URL Encoded

Use `body_type: "form"` to send `application/x-www-form-urlencoded` data. Common for OAuth token requests:

```json theme={null}
{
  "id": "oauth_token",
  "type": "http",
  "config": {
    "method": "POST",
    "url": "https://oauth.example.com/token",
    "body_type": "form",
    "body": {
      "grant_type": "client_credentials",
      "client_id": "{{env.CLIENT_ID}}",
      "client_secret": "{{env.CLIENT_SECRET}}"
    }
  }
}
```

The body is encoded as: `grant_type=client_credentials&client_id=xxx&client_secret=yyy`

### Multipart File Upload

Use `body_type: "multipart"` or add a `files` array to upload files:

```json theme={null}
{
  "id": "upload_file",
  "type": "http",
  "config": {
    "method": "POST",
    "url": "https://api.example.com/upload",
    "body": {
      "description": "Monthly report",
      "category": "reports"
    },
    "files": [
      {
        "field": "document",
        "filename": "report.pdf",
        "content": "base64:JVBERi0xLjQK..."
      }
    ]
  }
}
```

**File Config:**

| Field      | Type   | Required | Description                                     |
| ---------- | ------ | -------- | ----------------------------------------------- |
| `field`    | string | Yes      | Form field name for the file                    |
| `filename` | string | Yes      | Filename to send                                |
| `content`  | string | Yes      | File content (prefix with `base64:` for binary) |

**Multiple Files:**

```json theme={null}
{
  "files": [
    {
      "field": "document",
      "filename": "report.pdf",
      "content": "base64:JVBERi0xLjQK..."
    },
    {
      "field": "thumbnail",
      "filename": "preview.png",
      "content": "base64:iVBORw0KGgo..."
    }
  ]
}
```

### String Body

Strings are sent as-is:

```json theme={null}
{
  "body": "raw string content",
  "content_type": "text/plain"
}
```

### Template Body

Use templates for dynamic content:

```json theme={null}
{
  "body": "{{prepared_payload}}"
}
```

## Response Parsing

* **JSON responses** are automatically parsed into objects
* **Other responses** are returned as strings
* Check `Content-Type` header to determine response format

## URL Templates

The URL supports template expressions:

```
"url": "https://api.example.com/users/{{user_id}}/posts/{{post_id}}"  # Path parameters
"url": "https://{{env.API_HOST}}/v1/users"                            # Dynamic host
"url": "https://api.example.com/{{api_version}}/users"                # Conditional path
```

## Common Patterns

### Authenticated Request

```json theme={null}
{
  "id": "authenticated_call",
  "type": "http",
  "config": {
    "url": "https://api.example.com/protected",
    "headers": {
      "Authorization": "Bearer {{auth_token}}"
    }
  }
}
```

### OAuth Token Exchange

```json theme={null}
{
  "id": "get_token",
  "type": "http",
  "config": {
    "method": "POST",
    "url": "https://oauth.example.com/token",
    "body_type": "form",
    "body": {
      "grant_type": "client_credentials",
      "client_id": "{{env.CLIENT_ID}}",
      "client_secret": "{{env.CLIENT_SECRET}}",
      "scope": "read write"
    }
  }
}
```

Then use the token in subsequent requests:

```json theme={null}
{
  "id": "api_call",
  "type": "http",
  "config": {
    "url": "https://api.example.com/data",
    "headers": {
      "Authorization": "Bearer {{get_token.output.body.access_token}}"
    }
  }
}
```

### Pagination

```json theme={null}
{
  "id": "fetch_page",
  "type": "http",
  "config": {
    "url": "https://api.example.com/items",
    "query": {
      "page": "{{current_page}}",
      "per_page": "50"
    }
  }
}
```

### Webhook Call

```json theme={null}
{
  "id": "send_webhook",
  "type": "http",
  "config": {
    "method": "POST",
    "url": "{{webhook_url}}",
    "headers": {
      "X-Webhook-Secret": "{{env.WEBHOOK_SECRET}}"
    },
    "body": {
      "event": "order.created",
      "data": "{{order}}"
    }
  }
}
```

### File Upload

```json theme={null}
{
  "id": "upload_document",
  "type": "http",
  "config": {
    "method": "POST",
    "url": "https://api.example.com/documents",
    "headers": {
      "Authorization": "Bearer {{env.API_KEY}}"
    },
    "body": {
      "title": "{{request.body.title}}",
      "folder_id": "{{request.body.folder_id}}"
    },
    "files": [
      {
        "field": "file",
        "filename": "{{request.body.filename}}",
        "content": "{{request.body.file_content}}"
      }
    ]
  }
}
```

## Related

* [Transform Node](/nodes/transform) - Process response data
* [Condition Node](/nodes/condition) - Check response status
* [Try Node](/nodes/try) - Handle request failures
