Middleware Nodes
Middleware Nodes call your external system while a visitor is moving through a funnel. FunnelFlux waits for the response, evaluates the middleware routes, then follows the matched or default funnel connection.
Use Middleware Nodes when an external system must make a live routing decision. If you only need to notify another system and let the funnel continue, use a Webhook Node instead.
Middleware vs Webhooks
Middleware Nodes and Webhook Nodes both send funnel context to an external URL, but they have different runtime contracts:
| Feature | Middleware Node | Webhook Node |
|---|---|---|
| Runtime behavior | Synchronous decision point | Asynchronous pass-through dispatch |
| Funnel waits for response | Yes | No |
| Response affects routing | Yes | No |
| Main event type | middleware_request | node_execution, on_action, conversion_triggered, or custom_event_triggered |
| Typical use | Lead validation, fraud check, CRM decision, host-and-post | Notifications, logging, background automation |
Because middleware runs in the live routing path, endpoint latency and reliability directly affect the visitor. Always configure a safe default route.
API Workflow
Middleware configs are reusable assets. A funnel Middleware Node references one middleware config, then connects each navigable route to later funnel nodes.
The usual flow is:
- Create or update a middleware config through the Assets API.
- Add a Middleware Node to the funnel and reference that config.
- Connect every middleware route through
connectionMiddlewareParams.onRouteId. - Connect the
defaultroute as the fallback route. - Send test traffic and check middleware logs/reporting.
See the Middleware Configs API for endpoint and schema details.
Use the Middleware Function Templates when building a receiver endpoint.
Request Delivery
Middleware destination settings control the URL, method, timeout, headers, auth, and signing.
POST requests send a JSON body. GET requests send no body.
For GET requests with HMAC signing enabled, FunnelFlux signs the resolved URL. For POST requests with HMAC signing enabled, FunnelFlux signs the JSON body.
Middleware requests include these FunnelFlux headers:
| Header | Description |
|---|---|
X-FunnelFlux-Schema-Version | Same value as body schema_version, currently 1.0. |
X-FunnelFlux-Request-ID | Request correlation ID. Same value as body request_id for POST. |
X-FunnelFlux-Signature | Optional base64 HMAC-SHA256 signature when the config has an HMAC secret. |
Configured custom headers are also sent. If basic auth is configured, FunnelFlux sets the standard Authorization header.
FunnelFlux token placeholders are plaintext-only for middleware destination URLs. They are not expanded inside custom header values.
Destination Secrets
Middleware config read APIs sanitize stored secrets:
headersare returned with their stored values.basicAuth.usernameis returned.basicAuth.passwordis never returned as the real stored value.hmacSecretis never returned as the real stored value.hasBasicAuthPasswordis true when a non-blank basic-auth password is stored. In that case,basicAuth.passwordis returned as the fixed placeholder********.hasHmacSecretis true when a non-blank HMAC secret is stored. In that case,hmacSecretis returned as the fixed placeholder********.
When saving an existing middleware config, clients can preserve hidden secret values by sending the corresponding hasBasicAuthPassword or hasHmacSecret flag as true while omitting the secret field, sending it blank, or sending the unchanged ******** placeholder.
To replace a stored secret, send a real non-blank basicAuth.password or hmacSecret.
To clear the stored HMAC secret, send hasHmacSecret: false with hmacSecret omitted, null, or blank. To clear only the basic-auth password while keeping the username, send hasBasicAuthPassword: false with the password omitted or blank. To clear basic auth entirely, remove basicAuth from the config.
Node Destination Overrides
Funnel middleware nodes can override selected destination settings from the referenced middleware config through nodeMiddlewareRefParams.destinationOverrides.
Supported node-level overrides are:
headersbasicAuth.usernamebasicAuth.passwordhmacSecrethasBasicAuthPasswordhasHmacSecret
Node-level headers replace middleware config headers with the same name and add any new header names. Node overrides do not change the destination URL, method, or destination type.
REST read responses mask node-level basicAuth.password and hmacSecret the same way they mask middleware config secrets: set secrets return ******** plus the corresponding hasBasicAuthPassword or hasHmacSecret flag. On save, send the unchanged ******** placeholder, a blank value, or omit the secret field while keeping the matching flag true to preserve the stored node-level secret. Send a real non-blank value to replace it. Send the matching flag false with the secret omitted or blank to clear it.
POST Payload
POST middleware requests use JSON field names in snake_case.
| Field | Type | Description |
|---|---|---|
schema_version | string | Current body version, currently 1.0. |
event_type | string | Always middleware_request. |
request_id | string | Correlates the outbound request, headers, route decision, and logs. |
timestamp | integer | UTC Unix timestamp in milliseconds. |
execute_timeout_ms | integer | Effective Edge execution budget for this request, after defaults and clamping. Return before this deadline and keep your own safety buffer. |
is_action | boolean | Whether the middleware run follows an action request. |
action_number | integer | Present when is_action is true. |
visitor | object | Visitor, geo, device, browser, and connection context when available. |
funnel | object | Current funnel and middleware node identifiers/names. |
traffic_source | object | Traffic source ID and name when available. |
hit | object | Unified hit context when a hit exists. Treat this object and all nested fields as optional. |
session | object | Live Edge session identifiers and current-hit timestamps when available. |
tracking_fields | object | Entrance tracking fields captured from the traffic source URL. |
url_buffer | object | Current accumulated URL/action params. |
action_data | object | Non-system params from the current action plus origin fields. |
visitor_tags | array | Visitor tag IDs snapshot when available. |
Use url_buffer for accumulated URL and action parameters.
Middleware POST requests can include both a top-level hit object and session identifiers. Treat both as optional. Do not fail the request because either object is empty or missing.
Visitor Fields
Common visitor keys:
Code
Session Fields
Common session keys:
Code
visitor.visitor_id identifies the visitor. session.visitor_id comes from the live Edge session and can repeat that visitor value. Use session.hit_id, session.entrance_id, and session.reference_hit_id for current hit and entrance routing context.
Action Data
action_data contains non-system action query/body values plus action origin metadata. It does not duplicate top-level is_action or action_number.
Common origin metadata keys:
| Field | Description |
|---|---|
origin_node_id | Node ID that originated the action. |
origin_node_name | Origin node name. |
origin_node_type | Origin node type. |
origin_page_id | Resolved origin page ID when available. |
origin_page_name | Resolved origin page name when available. |
Example POST Payload
Code
Response Evaluation
FunnelFlux captures the response status and up to 64 KiB of response body. It then evaluates non-default routes in ascending priority order.
Exactly one default route is required. If no non-default route matches, or if runtime delivery fails, FunnelFlux uses the default route.
Routes can evaluate these fields:
| Field | Description |
|---|---|
status_code | HTTP status code from the middleware response. Values must be integer HTTP codes from 100 to 599. |
body_text | Response body as text. Supports text operators. |
body_json.<path> | JSON response value by dot path, such as body_json.decision or body_json.items.9.score. |
Supported operators:
Code
body_json.<path> paths use dot segments only. Brackets, quoted JSONPath syntax, spaces, empty segments, trailing dots, leading dots, and double-dot segments are rejected.
status_code condition values must be strict integer HTTP codes from 100 through 599; signs, decimals, padding, and spaces are rejected. contains and not_contains are case-insensitive. Numeric comparisons require finite numeric values and apply to status_code and body_json.<path>.
Route Keys
Middleware routes use stable route keys:
| Field | Description |
|---|---|
idRoute | Lowercase route key and user-facing route label. Use a-z, 0-9, and _, up to 64 characters. |
priority | Evaluation order. The default route uses 0; non-default routes use 1 through 255. |
isDefault | Marks the fallback route. Exactly one route must be default. |
The reserved fallback route is idRoute: "default" with priority: 0. Non-default routes are evaluated by ascending priority.
Funnel connections leaving a Middleware Node use connectionMiddlewareParams.onRouteId. Set it to the matching route key, such as approved, review, or default.
Example Response
Your middleware endpoint might return:
Code
A middleware config could then route:
| Route | Condition | Result |
|---|---|---|
approved | body_json.decision is approved | Continue through the approved funnel connection. |
review | body_json.score less_than 50 | Continue through a review/reject path. |
default | fallback | Continue through the safe fallback connection. |
Middleware routes always continue through funnel connections. A broken route binding or missing target node is a funnel configuration error.
Timeouts and Fallback
timeoutMs accepts 1 through 30000; runtime clamps to 30 seconds and defaults to 5 seconds.
POST payloads include execute_timeout_ms, the effective timeout budget Edge is enforcing for that specific request. Your endpoint should finish external API calls below execute_timeout_ms - 250 and return a fallback JSON response before the Edge deadline.
The default route is used for request-local failures, including:
- missing, inactive, or unavailable middleware config
- billing denial
- invalid destination
- unsupported method
- timeout
- request failure
- no matching non-default route
- missing
defaultroute binding from the funnel node
There is no sticky circuit breaker or pod-wide disablement. A failure falls back for that request only.
Destination Restrictions
In production, middleware destinations must be public HTTPS endpoints. HTTP is accepted only in development environments. FunnelFlux revalidates the resolved host at execution time and blocks loopback, private, link-local, metadata, and reserved IP ranges.
Use a hosted endpoint or a public tunnel for local testing. Do not rely on localhost, private VPC IPs, or metadata service addresses.
Common Mistakes
- Using Middleware Nodes for simple notifications. Use Webhook Nodes when the response should not affect routing.
- Forgetting to wire the
defaultroute. - Building slow middleware endpoints. This is live redirect-path work.
- Changing middleware route keys without checking existing funnel connections.
- Hardcoding local/private URLs for production traffic.