Skip to main content

Workflows

Workflows are the core automation engine of SpatialFlow, enabling you to create event-driven automation sequences that respond to geospatial events in real-time. When a device enters or exits a geofence, workflows automatically trigger actions like sending webhooks, Slack notifications, emails, or SMS messages—typically within 2 seconds.

What is a Workflow?

A workflow is an automation pipeline that connects a trigger to one or more actions. Think of it as: "When [something happens], do [these things]."

Trigger → Action 1 → Action 2 → Action 3

For example:

  • When a delivery truck enters the customer's geofence
  • Do send a webhook to your backend API and send a Slack message to the operations channel

Workflow Components

Triggers

Triggers define when a workflow should execute. SpatialFlow currently supports the following trigger types:

Geofence Entry

Fires when a device enters a geofence boundary.

Configuration:

  • Geofence Selection: Choose one or more geofences to monitor
  • Debounce Settings: Minimum distance delta and time interval to prevent GPS jitter from causing duplicate triggers

Example:

{
"type": "geofence_enter",
"geofence_ids": ["a1b2c3d4-..."],
"debounce_distance_m": 50,
"debounce_time_s": 30
}

Geofence Exit

Fires when a device leaves a geofence boundary.

Configuration:

  • Geofence Selection: Choose one or more geofences to monitor
  • Debounce Settings: Similar to entry triggers

Example:

{
"type": "geofence_exit",
"geofence_ids": ["a1b2c3d4-..."],
"debounce_distance_m": 50,
"debounce_time_s": 30
}

Signal Triggers

Workflows can also trigger on spatial signals — anomaly detection events that go beyond simple boundary crossings. Signal triggers fire when SpatialFlow detects behavioral patterns like prolonged dwell time or policy violations.

Configuration:

  • Signal Types: Choose which signal types to listen for (dwell, policy_violation)
  • Signal States: Which lifecycle states trigger the workflow (default: confirmed)
  • Geofence Filter: Optionally limit to signals from specific geofences
  • Device Filter: Optionally limit to signals from specific devices

Example:

{
"type": "signal",
"signal_types": ["dwell", "policy_violation"],
"signal_states": ["confirmed"],
"geofence_ids": ["a1b2c3d4-..."]
}
note

route_deviation is a reserved signal type but is not yet active. See Signals for details.

See Signals for details on signal types and lifecycle, and the Signal Configuration Guide for setup instructions.

Actions

Actions define what happens when a workflow is triggered. You can chain multiple actions together in sequence.

Webhook (HTTP Request)

Send HTTP requests to external APIs with custom headers, authentication, and payloads.

Supported Methods: GET, POST, PUT, PATCH, DELETE

Features:

  • Custom headers and request body
  • Authentication: Basic Auth, Bearer Token, API Key
  • Variable substitution from trigger data
  • Request signing with HMAC signatures
  • Automatic retries with exponential backoff
  • Configurable timeouts (up to 30 seconds)

Example Configuration:

{
"type": "webhook",
"name": "Send arrival notification",
"config": {
"url": "https://api.example.com/webhooks/arrival",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"X-API-Key": "your-api-key"
},
"body": {
"device_id": "{{trigger.device_id}}",
"geofence_name": "{{trigger.geofence.name}}",
"timestamp": "{{trigger.timestamp}}",
"location": {
"lat": "{{trigger.location.lat}}",
"lng": "{{trigger.location.lng}}"
}
},
"timeout": 10,
"retry_count": 3
}
}

Slack Notification

Send messages to Slack channels or direct messages with rich formatting.

Features:

  • Webhook-based authentication via Integrations
  • Channel or user targeting
  • Rich message formatting with Markdown
  • Block Kit support for interactive messages
  • Thread support for organizing conversations

Example Configuration:

{
"type": "slack",
"name": "Notify operations team",
"config": {
"integration_id": "int_abc123",
"channel": "#operations",
"message": "Vehicle {{trigger.device_id}} arrived at {{trigger.geofence.name}}"
}
}

Email

Send email notifications using AWS SES or SendGrid.

Features:

  • HTML and plain text email support
  • Template variables for dynamic content
  • Multiple recipients (to, cc, bcc)
  • Attachments support
  • Custom sender names

Example Configuration:

{
"type": "email",
"name": "Send arrival email",
"config": {
"integration_id": "int_xyz789",
"to": ["manager@example.com"],
"subject": "Arrival at {{trigger.geofence.name}}",
"body_html": "<p>Device {{trigger.device_id}} has arrived at {{trigger.geofence.name}} at {{trigger.timestamp}}.</p>",
"body_text": "Device {{trigger.device_id}} arrived at {{trigger.geofence.name}}"
}
}

SMS (Twilio)

Send SMS notifications via Twilio integration.

Features:

  • International phone number support
  • Template variables for dynamic content
  • Delivery tracking and status updates
  • Support for multiple recipients

Example Configuration:

{
"type": "twilio_sms",
"name": "Send arrival SMS",
"config": {
"integration_id": "int_twilio123",
"to": "+14155551234",
"message": "Your delivery has arrived at {{trigger.geofence.name}}"
}
}

AWS Lambda

Invoke AWS Lambda functions with custom payloads.

Features:

  • Synchronous and asynchronous invocation
  • IAM role support for secure authentication
  • Custom payload with trigger context
  • Response data capture for downstream actions

Example Configuration:

{
"type": "aws_lambda",
"name": "Process arrival event",
"config": {
"integration_id": "int_lambda456",
"function_name": "process-geofence-event",
"payload": {
"event_type": "arrival",
"device_id": "{{trigger.device_id}}",
"geofence_id": "{{trigger.geofence.id}}"
}
}
}

AWS SNS

Publish messages to AWS SNS topics for fan-out messaging patterns.

Features:

  • Topic publishing with message attributes
  • Support for different message formats (JSON, String)
  • IAM role support
  • Message deduplication for FIFO topics

Example Configuration:

{
"type": "aws_sns",
"name": "Publish to SNS topic",
"config": {
"integration_id": "int_sns789",
"topic_arn": "arn:aws:sns:us-east-1:123456789012:geofence-events",
"message": "{{trigger | json}}",
"message_attributes": {
"event_type": "geofence_entry",
"device_id": "{{trigger.device_id}}"
}
}
}

Microsoft Teams

Send messages to Microsoft Teams channels via webhook connectors.

Features:

  • Adaptive Cards support for rich formatting
  • Channel webhook integration
  • Action buttons and interactive elements

Discord

Send messages to Discord channels via webhooks.

Features:

  • Rich embeds with colors and formatting
  • Webhook-based messaging
  • Support for avatars and custom usernames

Database Operations

Execute database queries for custom data persistence.

Features:

  • PostgreSQL query execution
  • Read and write operations
  • Parameterized queries for security
  • Result capture for downstream actions

Creating Workflows

Via Visual Builder

The SpatialFlow web application includes a no-code workflow builder with a drag-and-drop canvas interface powered by React Flow.

Steps:

  1. Navigate to Workflows in the dashboard
  2. Click New Workflow
  3. Drag a Trigger node onto the canvas
  4. Configure the trigger (select geofences, set debounce settings)
  5. Drag Action nodes and connect them to the trigger
  6. Configure each action with the required settings
  7. Test your workflow with the built-in testing tool
  8. Save and activate your workflow

Features:

  • Visual workflow canvas with zoom and pan
  • Collapsible component palette
  • Real-time configuration inspector
  • Auto-save and draft recovery
  • Workflow templates for common patterns
  • Test mode with live execution monitoring

Via API

Create workflows programmatically using the REST API.

API Format

The actual API uses a nodes and edges format (a visual graph representation) rather than the simplified trigger_config/steps structure shown below. See Create Your First Workflow for the exact API schema with the nodes/edges format.

Endpoint: POST /api/v1/workflows

Request (simplified representation):

curl -X POST https://api.spatialflow.io/api/v1/workflows \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Warehouse Arrival Alert",
"description": "Send notifications when trucks arrive at warehouse",
"trigger_config": {
"type": "geofence_enter",
"geofence_ids": ["a1b2c3d4-5678-90ab-cdef-1234567890ab"]
},
"steps": [
{
"type": "webhook",
"name": "Send to backend",
"config": {
"url": "https://api.example.com/arrivals",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"device_id": "{{trigger.device_id}}",
"timestamp": "{{trigger.timestamp}}"
}
}
},
{
"type": "slack",
"name": "Notify team",
"config": {
"integration_id": "int_slack123",
"channel": "#warehouse",
"message": "Truck {{trigger.device_id}} arrived"
}
}
],
"is_active": false,
"is_test_mode": true,
"tags": ["warehouse", "arrivals"],
"category": "geofence"
}'

Response:

{
"id": "wf_abc123def456",
"name": "Warehouse Arrival Alert",
"description": "Send notifications when trucks arrive at warehouse",
"status": "draft",
"version": 1,
"created_at": "2025-11-10T12:00:00Z",
"updated_at": "2025-11-10T12:00:00Z"
}

Workflow Execution

When a trigger condition is met, SpatialFlow executes the workflow automatically:

  1. Event Detection: The platform monitors location updates and detects geofence transitions
  2. Workflow Matching: All active workflows matching the trigger are identified
  3. Execution Queue: A workflow execution job is queued to Celery for async processing
  4. Step Execution: Each action in the workflow executes in sequence
  5. Status Updates: Real-time status updates are sent via WebSocket
  6. Result Capture: Execution results, timing, and any errors are stored

Target Latency: < 2 seconds from trigger to action completion (p95)

Execution Context

Each workflow execution has access to a context object containing:

  • trigger: The triggering event data (device_id, location, geofence details, timestamp)
  • workflow: Workflow metadata (id, name, version)
  • execution: Current execution context (id, started_at)
  • Step outputs: Accessible via step_0, step_1, etc., for subsequent steps

Example Template Variable Usage:

Device {{trigger.device_id}} entered {{trigger.geofence.name}} at {{trigger.timestamp}}
Location: {{trigger.location.lat}}, {{trigger.location.lng}}

Workflow Status & Monitoring

Status States

Workflows can be in one of three states:

  • Draft: Inactive workflow in test mode (not triggered by real events)
  • Active: Deployed workflow actively monitoring for trigger conditions
  • Paused: Inactive workflow that can be quickly reactivated

Execution History

Every workflow execution is tracked with detailed information:

  • Execution ID: Unique identifier for each run
  • Status: pending, running, completed, failed, cancelled
  • Trigger Source: geofence, manual_test, schedule, webhook
  • Step Details: Individual step execution with timing and status
  • Duration: Total execution time in milliseconds
  • Error Messages: Detailed error information for failed executions

API Endpoint: GET /api/v1/workflows/{workflow_id}/executions

Real-time Monitoring

The workflow builder includes a real-time debugger that shows:

  • Live execution progress
  • Step-by-step status updates via WebSocket
  • Input and output data for each step
  • Execution duration and performance metrics
  • Error messages and retry attempts

Best Practices

Naming Conventions

  • Use descriptive names that explain the purpose: "Warehouse Entry Alerts" instead of "Workflow 1"
  • Include the trigger type and primary action: "Geofence Exit → Webhook"
  • Add environment prefix for multi-environment setups: "PROD: Customer Arrivals"

Testing Workflows

  1. Start workflows in test mode (is_test_mode: true)
  2. Use the built-in workflow tester with mock trigger data
  3. Verify all actions execute successfully
  4. Check execution logs for timing and error details
  5. Test edge cases (missing data, API failures)
  6. Activate only after thorough testing

Error Handling

  • Configure appropriate retry counts for webhook actions (default: 3)
  • Set realistic timeouts based on downstream API performance
  • Monitor execution history for patterns of failures
  • Use exponential backoff for retry policies
  • Configure dead-letter queues for terminal failures

Performance Considerations

  • Keep action chains short (recommended: 3-5 actions maximum)
  • Use async actions when order doesn't matter
  • Minimize large payload sizes in webhook bodies
  • Cache frequently accessed data in action handlers
  • Monitor execution latency and optimize slow actions

Security

  • Use integrations for storing credentials instead of hardcoding secrets
  • Enable webhook signature verification (HMAC)
  • Validate input data before using in templates
  • Follow least-privilege principle for IAM roles (AWS actions)
  • Regularly rotate API keys and tokens

Common Patterns

Pattern 1: Delivery Arrival Notification

Use Case: Notify customers when their delivery vehicle arrives

{
"name": "Customer Arrival Notification",
"trigger_config": {
"type": "geofence_enter",
"geofence_ids": ["customer_delivery_zone"]
},
"steps": [
{
"type": "webhook",
"name": "Update backend",
"config": {
"url": "https://api.example.com/deliveries/arrival",
"method": "POST",
"body": {
"delivery_id": "{{trigger.device_id}}",
"customer_id": "{{trigger.geofence.metadata.customer_id}}",
"arrival_time": "{{trigger.timestamp}}"
}
}
},
{
"type": "twilio_sms",
"name": "SMS customer",
"config": {
"to": "{{trigger.geofence.metadata.customer_phone}}",
"message": "Your delivery is arriving now!"
}
}
]
}

Pattern 2: Restricted Zone Alert

Use Case: Alert security team when a vehicle enters a restricted area

{
"name": "Restricted Zone Entry Alert",
"trigger_config": {
"type": "geofence_enter",
"geofence_ids": ["restricted_zone_1", "restricted_zone_2"]
},
"steps": [
{
"type": "slack",
"name": "Alert security",
"config": {
"channel": "#security-alerts",
"message": "⚠️ ALERT: Vehicle {{trigger.device_id}} entered restricted zone {{trigger.geofence.name}} at {{trigger.timestamp}}"
}
},
{
"type": "email",
"name": "Email security manager",
"config": {
"to": ["security@example.com"],
"subject": "Restricted Zone Entry Alert",
"body_html": "<p>Vehicle {{trigger.device_id}} entered {{trigger.geofence.name}}</p>"
}
}
]
}

Pattern 3: Multi-Action Webhook Fan-out

Use Case: Trigger multiple downstream systems when a depot entry occurs

{
"name": "Depot Entry Multi-System Update",
"trigger_config": {
"type": "geofence_enter",
"geofence_ids": ["main_depot"]
},
"steps": [
{
"type": "webhook",
"name": "Update ERP system",
"config": {
"url": "https://erp.example.com/api/vehicle-arrival",
"method": "POST"
}
},
{
"type": "webhook",
"name": "Update fleet management",
"config": {
"url": "https://fleet.example.com/api/events",
"method": "POST"
}
},
{
"type": "aws_sns",
"name": "Publish to event bus",
"config": {
"topic_arn": "arn:aws:sns:us-east-1:123456789012:depot-events",
"message": "{{trigger | json}}"
}
}
]
}

Pattern 4: Time-Windowed Notification

Use Case: Only send alerts during business hours

{
"name": "Business Hours Arrival Alert",
"trigger_config": {
"type": "geofence_enter",
"geofence_ids": ["office_location"],
"time_window": {
"start": "08:00",
"end": "18:00",
"timezone": "America/New_York",
"days": ["monday", "tuesday", "wednesday", "thursday", "friday"]
}
},
"steps": [
{
"type": "slack",
"name": "Notify reception",
"config": {
"channel": "#reception",
"message": "Visitor arrived at front entrance"
}
}
]
}

Troubleshooting

Workflow Not Triggering

Symptoms: Workflow is active but not executing when expected

Solutions:

  1. Verify the workflow status is "active" (not "draft" or "paused")
  2. Check that is_test_mode is set to false for production
  3. Confirm geofences are correctly selected in trigger configuration
  4. Review location data accuracy—low accuracy points may be filtered
  5. Check debounce settings aren't preventing triggers
  6. Verify the device is sending location updates to SpatialFlow

Action Failing Repeatedly

Symptoms: Workflow executes but specific action always fails

Solutions:

  1. Review execution logs for detailed error messages
  2. Test the action endpoint independently (e.g., curl for webhooks)
  3. Verify integration credentials are valid and not expired
  4. Check webhook URL is accessible from SpatialFlow servers
  5. Ensure request payload is valid for the destination API
  6. Review timeout settings—increase if downstream API is slow
  7. Check rate limits on destination service

Slow Workflow Execution

Symptoms: Workflow takes longer than 2 seconds to complete

Solutions:

  1. Review execution timing for each step to identify bottleneck
  2. Increase timeout for slow webhook endpoints
  3. Optimize downstream API performance
  4. Consider parallelizing independent actions (future feature)
  5. Reduce payload size by removing unnecessary data
  6. Check for network latency between SpatialFlow and action endpoints

Template Variables Not Rendering

Symptoms: Action receives literal {{variable}} instead of actual value

Solutions:

  1. Verify the variable path is correct (e.g., trigger.device_id)
  2. Check that the trigger data contains the expected fields
  3. Use the workflow tester to inspect trigger data structure
  4. Ensure JSON is properly formatted in webhook body
  5. Review template syntax documentation for correct format

Integration Not Found

Symptoms: Action fails with "Integration not found" error

Solutions:

  1. Verify the integration_id exists and is active
  2. Check that the integration belongs to your workspace
  3. Ensure the integration type matches the action type
  4. Verify the integration credentials are valid
  5. Verify the user has permission to use the integration

Next Steps