Skip to content

Core Concepts

A flow is a complete integration definition — a YAML file that describes how data moves from a source to one or more targets, with optional transformation, routing, and error handling.

StatusDescription
draftCreated but not deployed. Can be edited freely.
activeDeployed and processing messages.
pausedTemporarily stopped. No new messages processed.
errorRuntime error detected. Requires attention.
stateDiagram-v2
[*] --> draft: create
draft --> active: deploy
active --> paused: pause
paused --> active: resume
active --> error: runtime error
error --> active: fix + redeploy

fyrn supports four flow tiers:

TypeUse caseKey fields
SimpleSource → transform → targetsource, target, mapping
Multi-stepPipelines with conditions, enrichment, routingsource, steps
SagaDistributed transactions with compensationtype: saga, steps with compensate
Fan-outRoute to multiple targets based on payload datatype: fan-out, fan_out

A simple flow example:

flow: shopify-orders-to-erp
version: 1
source:
connector: shopify-production
trigger: webhook
event: orders/create
target:
connector: erp-system
endpoint: /api/sales-orders
method: POST
mapping:
order_id: source.id
total: source.total_price | decimal(2)
customer_email: source.customer.email
on_error:
retry: 3x exponential(30s)
then: dead-letter

Every flow must have a source and at least one of: target (simple flow), steps (multi-step/saga), or fan_out (fan-out).

Every flow has an integer version field. Each deployment creates an immutable snapshot. You can roll back to any previous version.


Steps are the building blocks of multi-step flows. Each step has a name and an optional when condition.

Step typePurposeKey field
tagLabel a message for later condition checkstag: <name>
callInvoke an external API, optionally store the resultcall: <connector>
switchRoute to different targets based on conditionsswitch: [...]
deliverSend data to a target connectortarget: <connector>
notifySend a notification to a channelchannel: + message:
emitFire-and-forget trigger of another flowemit: <flow>
waitPause processing for a duration (max 7 days)wait: <duration>

Example multi-step flow:

flow: order-pipeline
version: 1
source:
connector: shopify
trigger: webhook
event: orders/create
steps:
- name: classify
when: source.total_price > 1000
tag: high-value
- name: enrich-customer
call: crm-api
endpoint: /customers/lookup
params:
email: source.customer.email
store_as: customer_data
- name: route
switch:
- when: source.shipping_address.country == "FI"
target: warehouse-eu
- when: source.shipping_address.country == "US"
target: warehouse-us
- default: true
target: warehouse-international
- name: notify-vip
when: tagged(high-value)
channel: "#big-orders"
message: "New high-value order from {{source.customer.name}}"

The source.trigger field defines how a flow is activated.

TriggerDescriptionExample
webhookInbound HTTP POST from an external systemShopify order webhook
pollPeriodic polling of an external APICheck for new records every 5 min
scheduleCron-based executionRun daily at 6 AM
manualTriggered on-demand via CLI or UIAd-hoc data sync
apiTriggered via a published API endpointPartner submits data via your API
# Webhook trigger
source:
connector: shopify
trigger: webhook
event: orders/create
# Schedule trigger
source:
connector: report-api
trigger: schedule
schedule: "0 6 * * *"
timezone: "Europe/Helsinki"
# Poll trigger with cursor pagination
source:
connector: legacy-system
trigger: poll
poll:
url: https://api.example.com/records
method: GET
headers:
Authorization: "Bearer {{instance.api_key}}"
records_path: data.records
pagination:
strategy: cursor
cursor_path: paging.next.after
cursor_param: after

Transforms map and reshape data between source and target formats using pipe syntax.

<field_reference> | <transform1> | <transform2>(arg)

Transforms chain left-to-right. The output of each feeds into the next.

mapping:
# Simple field access
order_id: source.id
# Transform chain
currency: source.currency | uppercase
total: source.total_price | decimal(2)
display_name: source.raw_name | trim | uppercase
# Literal piped through transform
processed_at: '"" | now'
# Conditional (ternary)
status: source.paid ? "confirmed" : "pending"
# Template string
message: "Order {{source.id}} for {{source.customer.name}}"
  • String: uppercase, lowercase, trim, replace, replace_all, split, join, substring, pad_left, pad_right
  • Numeric: decimal, round, abs, floor, ceil
  • Type conversion: to_integer, to_float, to_boolean
  • Date/time: date, now, timestamp, timezone, date_add, date_sub
  • Null handling: default, coalesce, omit_if_null, required
  • Lookup: lookup(table_name, default?)

See the Transforms Guide for the complete reference with input/output examples.

Map over arrays in the source data:

mapping:
line_items:
source.line_items[] -> each:
sku: item.sku
quantity: item.quantity
price: item.price | decimal(2)

Connectors represent external systems. fyrn has two layers:

The connector catalog contains templates for supported systems. Each catalog entry defines the transport type, auth method, and required configuration fields.

fyrn ships with 24 built-in connectors:

CategoryConnectors
E-commerceShopify, WooCommerce
CRM & SalesSalesforce, HubSpot, Dynamics 365, Zendesk
Finance & AccountingStripe, SAP Business One, NetSuite, QuickBooks, Xero
CommunicationSlack, Microsoft Teams, SendGrid
Developer ToolsJira
Warehousing & LogisticsShipStation
DatabasesPostgreSQL, MySQL, MSSQL
Storage & FilesAmazon S3, Google Drive, SFTP
GenericGeneric HTTP, Generic Webhook

A connector instance is a configured, authenticated connection to a specific account or environment. For example:

  • shopify-production — your production Shopify store
  • shopify-staging — your staging store
  • erp-system — your SAP Business One instance

Instances store encrypted credentials (AES-256-GCM) and connection settings. You reference instances by name in flow YAML:

source:
connector: shopify-production # ← connector instance name
trigger: webhook
Terminal window
# Browse available connector types
fyrn connector catalog
# List configured instances
fyrn connector instances
# Test a connection
fyrn connector test <instance-id>

Flows with trigger: api can be exposed as published API endpoints. External consumers call your API, and the flow processes the request.

Published APIs support:

  • Request schema validation — strict or lenient mode
  • Consumer keys — per-consumer API keys for authentication and rate limiting
  • Versioning — deprecate old versions, sunset with notice
  • Response mapping — synchronous mode returns transformed results

See the Published APIs Guide for details.


fyrn supports multiple deployment environments per account (e.g., staging, production). Each environment has:

  • Its own set of connector instances
  • Independent flow deployments
  • Separate message logs and metrics

Flows can be promoted between environments with a promotion checklist that verifies connector availability and configuration compatibility.


fyrn uses a multi-tenant model:

  • Account — top-level workspace. Owns flows, connectors, environments, and all resources.
  • Users — authenticated via Auth0. Can be members of multiple accounts.
  • Roles — per-account roles control access:
RolePermissions
ownerFull access, manage members
adminFull access to all resources
editorCreate and edit flows and connectors
viewerRead-only access

Every flow can define error handling behavior:

on_error:
retry: 3x exponential(30s)
then: dead-letter
StrategyBehavior
exponentialExponential backoff: 30s, 60s, 120s…
linearLinear backoff: 30s, 60s, 90s…
fixedFixed delay: 30s, 30s, 30s…

Format: <attempts>x <strategy>(<base_delay>)

After exhausting retries, the then action runs. dead-letter queues the message for manual review or replay.


Configure at the source level to prevent duplicates and ensure message order:

source:
connector: shopify
trigger: webhook
dedup:
key: source.id
window: 24h
ordering:
key: source.entity_id
mode: strict
  • Dedup: Messages with the same key within the window are dropped. Supports composite keys: key: [source.entity_id, source.event_type]
  • Ordering: Ensures in-order processing per key. strict guarantees order; best-effort attempts ordering without blocking.

Dedup runs first (filters duplicates), then the ordering lock is acquired.

See the Dedup & Ordering Guide for details.


Buffer messages and emit aggregated output based on time windows or count thresholds:

source:
connector: shopify
trigger: webhook
aggregate:
window: 5m
count: 100
group_by: source.customer_id
output:
customer_id: group.key
order_count: count()
total_amount: sum(source.total)

See the Aggregation Guide for details.


Protect sensitive data with field-level policies:

policies:
- pii-mask:
- customer.email
- customer.phone
- pii-encrypt:
- customer.ssn
- pii-strip:
fields:
- customer.ssn
targets:
- analytics

Three policy types: mask (replace with ***), encrypt (AES-256-GCM), strip (remove for specific targets).

See the PII & Data Handling Guide for details.