Skip to content

App Nodes

App Nodes are integration-specific nodes provided by registered applications (Shopify, FedEx, WooCommerce, etc.). They are dynamically loaded based on which apps are installed.


App nodes are divided into two distinct types based on their role in a flow:

Action Nodes

Perform operations on external systems. Require a connection for authentication.

Trigger Nodes (Webhooks)

Start flows when external events occur. Require a webhook configuration.


Action nodes execute operations against external APIs (create order, get product, update shipment, etc.).

{app_prefix}.{action_name}
// Examples:
app.shopify.create_order
app.fedex.get_rates
tenant.app.custom_integration.sync_inventory
HandleTypePositionDescription
inputtargetleftData from previous node
outputsourcerightSuccess response
errorsourcebottomError response

Action nodes follow this structure:

{
// Only if app requires a connection (OAuth, API Key, etc.)
connection_id?: string,
// Action-specific parameters
parameters: {
// Defined by the action's spec
}
}

When an app requires authentication, the form includes a connection selector:

{
name: 'connection_id',
type: 'select',
label: 'Connection',
placeholder: 'Select Connection',
required: true,
icon: app.icon,
options: [
{ label: 'My Shopify Store', value: 'conn_abc123' },
{ label: 'Backup Store', value: 'conn_def456' }
],
action: {
label: 'Add',
value: 'add_connection.app.shopify.create_order'
}
}

Trigger nodes start flow execution when external events occur. They act as entry points for flows.

{app_prefix}.{trigger_name}
// Examples:
app.shopify.order_created
app.stripe.payment_received
ion.webhook // Custom webhook
HandleTypePositionDescription
outputsourcerightEvent data
errorsourcebottomProcessing error

Trigger nodes require a webhook selector:

{
// Required: which webhook instance to use
webhook_id: string,
// Event-specific parameters
parameters: {
// Defined by the trigger's spec
}
}
{
name: 'webhook_id',
type: 'select',
label: 'Webhook',
placeholder: 'Select Webhook',
required: true,
icon: app.icon,
options: [
{ label: 'Production Webhook', value: 'wh_abc123' },
{ label: 'Testing Webhook', value: 'wh_def456' }
],
action: {
label: 'Add',
value: 'add_webhook.app.shopify.order_created'
}
}

This is how app nodes are constructed internally:

interface AppNode {
label: string; // "Create Order"
module: string; // "app.shopify.create_order"
group: {
icon: string; // App icon URL
name: string; // "app.shopify"
};
version: number; // 1
icon: string; // App icon URL
spec: {
type: 'collection',
spec: Field[] // Form fields
};
handle: Handle; // Input/output configuration
}

Action nodes:

{
source: [{ id: 'input', position: 'left' }],
target: [
{ id: 'output', position: 'right' },
{ id: 'error', position: 'bottom' }
]
}

Trigger nodes:

{
source: [], // No input
target: [
{ id: 'output', position: 'right' },
{ id: 'error', position: 'bottom' }
]
}

Apps come from two sources:

SourcePrefixDescription
Global Appsapp.{type}Platform-wide integrations (Shopify, FedEx)
Tenant Appstenant.app.{name}Custom integrations per tenant

App node configuration forms are built using the Spec Paradigm. Each action/trigger defines a spec that describes its parameters:

// Example: Shopify Create Order spec
{
type: 'object',
spec: [
{ name: 'customer_id', type: 'string', label: 'Customer ID', required: true },
{ name: 'email', type: 'email', label: 'Email' },
{ name: 'line_items', type: 'array', label: 'Line Items' },
{ name: 'note', type: 'textarea', label: 'Order Note' }
]
}

See Spec Paradigm for full documentation.


┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Shopify │ │ Mapper │ │ FedEx │
│ Webhook │─────▶│ Transform │─────▶│ Get Rates │
│ (trigger) │ │ │ │ (action) │
└─────────────┘ └──────────────┘ └─────────────┘
│ │
└───────────────────┬───────────────────────┘
┌─────────────┐
│ Condition │
└─────────────┘