How matching works
When a business event fires inside Fire, every active flow whose criteria match the event is selected: A flow is selected when all of these are true:| Field | Match rule |
|---|---|
accountId | Equals the account that owns the entity |
vendorId | Equals the brand/vendor that owns the store |
triggerType | Equals the event type (order.completed, order.cancelled, order.invoiced, order.reversed) |
kind | 'store' (scoped by storeCodes) or 'channel' (scoped by channelCodes) |
storeCodes | kind='store' only: empty (matches all stores) or contains the event’s store code |
channelCodes | kind='channel' only: contains the channel code of the event’s order |
isActive | true |
Scope: store vs channel
The same event is published through one of two scoping mechanisms, depending on the flow’skind:
- Store flow (
kind='store') — matches bystoreCodes(empty = all stores of the vendor). The classic choice for backoffice integrations: ERP, analytics, printing, fiscal. - Channel flow (
kind='channel') — matches bychannelCodes, the order’s originating channel. Use it to echo back to the channel/aggregator: when an order from a channel (a kiosk, a marketplace) changes state, the event returns to that channel’s endpoint.
Building a flow
A flow runs like a small pipeline: the trigger starts it when a matching event fires, then each connected node runs in turn — log a step, call your endpoint over HTTP, branch on a condition, or reshape data — until the flow finishes. You build a flow visually in the dashboard: start from a trigger node and connect the nodes that should run after it. Each node has a type and its own configuration, and downstream nodes can read the trigger context.Trigger node
The starting point. Its only relevant config istriggerType:
HTTP node
This is the node that reaches your endpoint. Its config controls the entire request:method and url. body, headers, and auth are evaluated as templates against the trigger context.
Signed Webhook node (HMAC)
The Webhook node is an HTTP node that also signs the body with HMAC-SHA256. Use it when the receiver (typically a channel/aggregator) needs to verify the payload comes from Fire and was not tampered with. It has the same configuration as the HTTP node (URL, method, headers, body, status routes, transport auth) plus a shared secret. The signature is independent of transport auth (Bearer / API key / OAuth2): auth identifies the transport; the HMAC signature guarantees body integrity and anti-replay. They are complementary. Headers Fire adds:| Header | Value |
|---|---|
X-Fire-Signature | v1= + hex(HMAC-SHA256(secret, "{timestamp}.{rawBody}")) |
X-Fire-Timestamp | Unix timestamp in seconds |
Recompute
Compute
v1=hex(HMAC-SHA256(secret, timestamp + "." + rawBody)) over the raw body (do not re-serialize the JSON).The secret is shared out-of-band: you configure it on the flow node and on your receiver. On an invalid signature, respond
401; on success, 200.Other node types
Beyond trigger and HTTP, flows can include:| Type | Purpose |
|---|---|
condition | Branch on a {{trigger.data.*}} expression — different paths for different cases |
log | Emit a log line for traceability (visible in Settings → Integration Flows → Executions) |
transform | Reshape data with JavaScript before passing to a downstream node |
Trigger context
Every node template can reference the trigger context, available when the flow runs:{{}} mustache syntax: {{trigger.event.id}}, {{trigger.data.orderId}}, {{trigger.data.store.code}}, {{flow.name}}, {{queue.attempt}}.
Path resolution walks the trigger context as a JavaScript object. Array indexing works ({{trigger.data.payments.totals[0].total}}). For arrays of unknown length, use {{trigger.data.orderLines.length}}.
Body templates
Thebody field on the HTTP node is the only thing that determines what your endpoint receives. Fire substitutes {{...}} paths from the trigger context and POSTs the result.
There is no fixed Fire envelope enforced by the system. However, the dashboard ships with a canonical example template that most teams start from:
When a template path resolves to an object or array (e.g.
"{{trigger.data}}"), the runtime preserves the JSON type rather than serializing to a string. So "data": "{{trigger.data}}" produces a real nested JSON object on the wire, not a string blob.Authentication
Authenticate by configuring credentials on the flow’s HTTP node:| Auth type | Use when |
|---|---|
bearer | A static or rotating Bearer token your endpoint validates. |
api_key | A header-based API key (e.g. x-api-key). |
oauth2_client_credentials | Your endpoint is behind OAuth2; Fire fetches and caches access tokens automatically, refreshing on expiry. |
none | No auth (only acceptable if your endpoint is otherwise protected, e.g. mTLS, VPC). |
Status routes
The HTTP node can fan out to different downstream nodes based on the response status:statusCode matches by digit prefix: 2 matches all 2xx, 4 matches all 4xx, 200 matches only 200. Each route can pull values out of the response body via responseMapping and expose them to downstream nodes.
Per-tenant isolation
Every flow is scoped to your account and vendor. Fire never runs a flow across tenants — when you configure a flow it is bound to your tenant by default, and you cannot subscribe to another account’s events.Activation, versioning, and dry-run
- Flows can be toggled active or inactive — pause or resume receiving events without deleting the flow.
- Each save creates a new version; past versions are kept for audit, and only the latest active version runs.
- The dashboard’s Probar Flujo (Test Flow) button runs a flow against a synthetic sample payload (a country-specific scenario) without affecting real data — perfect for verifying body templates before going live.
Common patterns
- One flow per consumer. If you have three downstream services (ERP, analytics, message broker), use three flows with the same trigger and three HTTP nodes pointing to each. Adding/removing a consumer becomes a dashboard change, not a code change.
- Conditional fan-out. Use a
conditionnode after the trigger to branch on{{trigger.data.store.locationInfo.country.code}}and route Brazilian orders to a fiscal-aware endpoint while sending other countries to a generic one. - Per-store routing. Set
storeCodeson the flow to scope it to specific stores, or use the dashboard’s store filter to limit firing. - Event mapping. If your system uses different event names, transform the type in the body template:
"event_name": "fire.{{trigger.event.type}}".
Next
Events overview
The full event-driven model and envelope.
Delivery & retries
Timeouts, retries, dead-letter, idempotency.
Handle order events
Walkthrough: build a webhook handler in 10 minutes.
order.completed
The full V4 order snapshot reference.

