Workflow Integration Patterns
Learn common integration patterns for connecting workflows with external systems, APIs, and services in Axon OS.
Overview
Workflow integration enables seamless connectivity between Axon OS workflows and external systems, allowing you to automate complex business processes that span multiple platforms and services.
Key Integration Types
- API Integration: Connect to REST, GraphQL, and SOAP APIs
- Database Integration: Direct database connections and operations
- File System Integration: File processing and storage operations
- Message Queue Integration: Asynchronous messaging patterns
- Cloud Service Integration: Integration with AWS, Azure, GCP services
- Third-party Platform Integration: CRM, ERP, and business applications
API Integration Patterns
REST API Integration
interface RestApiConfig {
baseUrl: string;
authentication: {
type: 'bearer' | 'api-key' | 'oauth' | 'basic';
credentials: AuthCredentials;
};
headers: Record<string, string>;
timeout: number;
retryPolicy: RetryPolicy;
}
interface ApiRequest {
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
endpoint: string;
payload?: any;
queryParams?: Record<string, string>;
headers?: Record<string, string>;
}
// Example workflow node for API calls
const apiNode = {
id: 'api-call-001',
type: 'http-request',
config: {
method: 'POST',
url: 'https://api.example.com/users',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${auth.token}'
},
body: {
name: '${input.userName}',
email: '${input.userEmail}',
department: '${input.department}'
},
timeout: 30000,
retries: 3
},
errorHandling: {
onError: 'retry',
maxRetries: 3,
retryDelay: 1000
}
};
GraphQL Integration
interface GraphQLConfig {
endpoint: string;
authentication: AuthConfig;
introspection: boolean;
subscriptions: boolean;
}
// GraphQL query node example
const graphqlNode = {
id: 'graphql-query-001',
type: 'graphql-request',
config: {
endpoint: 'https://api.example.com/graphql',
query: `
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
profile {
avatar
department
}
}
}
`,
variables: {
id: '${input.userId}'
},
headers: {
'Authorization': 'Bearer ${auth.token}'
}
}
};
Webhook Integration
interface WebhookConfig {
url: string;
method: 'POST' | 'PUT';
headers: Record<string, string>;
authentication: AuthConfig;
payload: any;
retryPolicy: RetryPolicy;
}
// Webhook trigger node
const webhookTrigger = {
id: 'webhook-trigger-001',
type: 'webhook-trigger',
config: {
path: '/webhooks/order-created',
method: 'POST',
authentication: {
type: 'signature',
secret: '${env.WEBHOOK_SECRET}'
},
validation: {
schema: {
type: 'object',
properties: {
orderId: { type: 'string' },
customerId: { type: 'string' },
amount: { type: 'number' }
},
required: ['orderId', 'customerId', 'amount']
}
}
}
};
Database Integration
SQL Database Connection
interface DatabaseConfig {
type: 'postgresql' | 'mysql' | 'sqlite' | 'mssql';
connection: {
host: string;
port: number;
database: string;
username: string;
password: string;
ssl?: boolean;
};
pool: {
min: number;
max: number;
idle: number;
};
}
// Database query node
const sqlQueryNode = {
id: 'sql-query-001',
type: 'sql-query',
config: {
connection: 'primary-db',
query: `
SELECT u.id, u.name, u.email, p.department
FROM users u
JOIN profiles p ON u.id = p.user_id
WHERE u.created_at >= $1
ORDER BY u.created_at DESC
`,
parameters: ['${input.startDate}'],
timeout: 30000
},
output: {
format: 'array',
transform: {
camelCase: true,
excludeFields: ['password', 'internal_id']
}
}
};
NoSQL Database Integration
// MongoDB integration example
const mongoQueryNode = {
id: 'mongo-query-001',
type: 'mongodb-query',
config: {
connection: 'mongodb-primary',
collection: 'orders',
operation: 'find',
query: {
status: 'pending',
created_at: {
$gte: '${input.startDate}',
$lte: '${input.endDate}'
}
},
projection: {
_id: 1,
order_id: 1,
customer_id: 1,
amount: 1,
items: 1
},
sort: { created_at: -1 },
limit: 100
}
};
Message Queue Integration
RabbitMQ Integration
interface RabbitMQConfig {
connection: {
hostname: string;
port: number;
username: string;
password: string;
vhost: string;
};
exchange: {
name: string;
type: 'direct' | 'topic' | 'fanout' | 'headers';
durable: boolean;
};
queue: {
name: string;
durable: boolean;
exclusive: boolean;
autoDelete: boolean;
};
}
// Message publisher node
const messagePublisher = {
id: 'rabbitmq-publish-001',
type: 'rabbitmq-publish',
config: {
connection: 'rabbitmq-primary',
exchange: 'order.events',
routingKey: 'order.created',
message: {
orderId: '${input.orderId}',
customerId: '${input.customerId}',
amount: '${input.amount}',
timestamp: '${workflow.timestamp}'
},
options: {
persistent: true,
mandatory: true,
immediate: false
}
}
};
// Message consumer trigger
const messageConsumer = {
id: 'rabbitmq-consume-001',
type: 'rabbitmq-consume',
config: {
connection: 'rabbitmq-primary',
queue: 'order.processing',
options: {
noAck: false,
exclusive: false,
priority: 0,
consumerTag: 'workflow-consumer'
},
prefetch: 10
}
};
Apache Kafka Integration
// Kafka producer node
const kafkaProducer = {
id: 'kafka-produce-001',
type: 'kafka-produce',
config: {
brokers: ['kafka1:9092', 'kafka2:9092'],
topic: 'user-events',
partition: null, // Auto-select partition
message: {
key: '${input.userId}',
value: {
event: 'user_created',
userId: '${input.userId}',
timestamp: '${workflow.timestamp}',
data: '${input.userData}'
},
headers: {
'source': 'axon-workflow',
'version': '1.0'
}
},
options: {
acks: 'all',
retries: 3,
batchSize: 16384
}
}
};
Cloud Service Integration
AWS Integration
// S3 file upload node
const s3UploadNode = {
id: 's3-upload-001',
type: 'aws-s3-upload',
config: {
credentials: {
accessKeyId: '${env.AWS_ACCESS_KEY}',
secretAccessKey: '${env.AWS_SECRET_KEY}',
region: 'us-east-1'
},
bucket: 'my-workflow-files',
key: 'uploads/${workflow.executionId}/${input.fileName}',
body: '${input.fileContent}',
metadata: {
'uploaded-by': 'axon-workflow',
'execution-id': '${workflow.executionId}'
},
serverSideEncryption: 'AES256'
}
};
// Lambda function invocation
const lambdaInvokeNode = {
id: 'lambda-invoke-001',
type: 'aws-lambda-invoke',
config: {
credentials: {
accessKeyId: '${env.AWS_ACCESS_KEY}',
secretAccessKey: '${env.AWS_SECRET_KEY}',
region: 'us-east-1'
},
functionName: 'process-user-data',
invocationType: 'RequestResponse',
payload: {
userId: '${input.userId}',
action: 'process',
metadata: {
executionId: '${workflow.executionId}',
timestamp: '${workflow.timestamp}'
}
}
}
};
Azure Integration
// Azure Blob Storage node
const azureBlobNode = {
id: 'azure-blob-001',
type: 'azure-blob-upload',
config: {
connectionString: '${env.AZURE_STORAGE_CONNECTION}',
containerName: 'workflow-files',
blobName: '${workflow.executionId}/${input.fileName}',
content: '${input.fileContent}',
options: {
blobHTTPHeaders: {
contentType: '${input.contentType}'
},
metadata: {
'uploaded-by': 'axon-workflow',
'execution-id': '${workflow.executionId}'
}
}
}
};
File System Integration
File Processing Patterns
// File reader node
const fileReaderNode = {
id: 'file-reader-001',
type: 'file-reader',
config: {
path: '${input.filePath}',
encoding: 'utf8',
format: 'csv', // csv, json, xml, xlsx
options: {
delimiter: ',',
hasHeader: true,
skipEmptyLines: true
},
chunked: {
enabled: true,
chunkSize: 1000 // Process 1000 rows at a time
}
}
};
// File writer node
const fileWriterNode = {
id: 'file-writer-001',
type: 'file-writer',
config: {
path: '/output/${workflow.executionId}/processed_data.json',
content: '${processing.result}',
format: 'json',
options: {
createDirectories: true,
overwrite: false,
backup: true
}
}
};
// Directory watcher trigger
const directoryWatcher = {
id: 'directory-watch-001',
type: 'directory-watcher',
config: {
path: '/input/files',
pattern: '*.csv',
events: ['created', 'modified'],
recursive: true,
debounce: 1000 // Wait 1 second for file changes to settle
}
};
Third-Party Platform Integration
CRM Integration (Salesforce)
const salesforceNode = {
id: 'salesforce-create-001',
type: 'salesforce-create',
config: {
authentication: {
type: 'oauth',
clientId: '${env.SALESFORCE_CLIENT_ID}',
clientSecret: '${env.SALESFORCE_CLIENT_SECRET}',
username: '${env.SALESFORCE_USERNAME}',
password: '${env.SALESFORCE_PASSWORD}',
securityToken: '${env.SALESFORCE_SECURITY_TOKEN}',
sandbox: false
},
sobject: 'Contact',
fields: {
FirstName: '${input.firstName}',
LastName: '${input.lastName}',
Email: '${input.email}',
Phone: '${input.phone}',
LeadSource: 'Web Form'
}
}
};
ERP Integration (SAP)
const sapRfcNode = {
id: 'sap-rfc-001',
type: 'sap-rfc-call',
config: {
connection: {
host: '${env.SAP_HOST}',
client: '${env.SAP_CLIENT}',
user: '${env.SAP_USER}',
password: '${env.SAP_PASSWORD}',
language: 'EN'
},
functionModule: 'RFC_READ_TABLE',
parameters: {
QUERY_TABLE: 'MARA',
DELIMITER: '|',
FIELDS: [
{ FIELDNAME: 'MATNR' },
{ FIELDNAME: 'MAKTX' },
{ FIELDNAME: 'MTART' }
],
OPTIONS: [
{ TEXT: "MATNR LIKE '${input.materialPattern}'" }
]
}
}
};
Authentication Patterns
OAuth 2.0 Flow
interface OAuth2Config {
authUrl: string;
tokenUrl: string;
clientId: string;
clientSecret: string;
scope: string[];
redirectUri: string;
grantType: 'authorization_code' | 'client_credentials' | 'refresh_token';
}
const oauthNode = {
id: 'oauth-auth-001',
type: 'oauth2-authenticate',
config: {
provider: 'google',
clientId: '${env.GOOGLE_CLIENT_ID}',
clientSecret: '${env.GOOGLE_CLIENT_SECRET}',
scope: ['https://www.googleapis.com/auth/drive.readonly'],
redirectUri: 'https://app.axonos.com/oauth/callback',
refreshToken: '${credentials.google.refreshToken}'
},
output: {
accessToken: 'auth.accessToken',
expiresIn: 'auth.expiresIn',
refreshToken: 'auth.refreshToken'
}
};
API Key Management
const apiKeyAuth = {
id: 'api-key-auth-001',
type: 'api-key-auth',
config: {
keyLocation: 'header', // header, query, body
keyName: 'X-API-Key',
keyValue: '${env.EXTERNAL_API_KEY}',
encoding: 'base64' // optional
}
};
Error Handling in Integration
Retry Strategies
interface RetryConfig {
maxAttempts: number;
backoffStrategy: 'fixed' | 'exponential' | 'linear';
baseDelay: number;
maxDelay: number;
jitter: boolean;
retryableStatusCodes: number[];
retryableErrors: string[];
}
const integrationWithRetry = {
id: 'api-call-with-retry',
type: 'http-request',
config: {
url: 'https://api.unreliable-service.com/data',
method: 'GET'
},
errorHandling: {
retry: {
maxAttempts: 5,
backoffStrategy: 'exponential',
baseDelay: 1000,
maxDelay: 30000,
jitter: true,
retryableStatusCodes: [500, 502, 503, 504],
retryableErrors: ['ECONNRESET', 'ETIMEDOUT']
},
fallback: {
type: 'alternative_service',
config: {
url: 'https://backup-api.service.com/data'
}
}
}
};
Circuit Breaker Pattern
const circuitBreakerConfig = {
id: 'circuit-breaker-001',
type: 'circuit-breaker',
config: {
failureThreshold: 5,
resetTimeout: 60000,
monitoringPeriod: 30000,
halfOpenMaxCalls: 3
},
wrappedNode: {
type: 'http-request',
config: {
url: 'https://api.external-service.com/endpoint'
}
}
};
Performance Optimization
Connection Pooling
interface ConnectionPoolConfig {
min: number;
max: number;
acquireTimeoutMillis: number;
idleTimeoutMillis: number;
reapIntervalMillis: number;
createRetryIntervalMillis: number;
}
const databasePool = {
type: 'connection-pool',
config: {
database: 'postgresql',
min: 2,
max: 20,
acquireTimeoutMillis: 30000,
idleTimeoutMillis: 600000,
reapIntervalMillis: 1000,
createRetryIntervalMillis: 200
}
};
Caching Strategies
const cachedApiCall = {
id: 'cached-api-call-001',
type: 'http-request',
config: {
url: 'https://api.example.com/slow-endpoint',
method: 'GET'
},
caching: {
enabled: true,
ttl: 300000, // 5 minutes
keyTemplate: 'api:${input.userId}:${input.category}',
strategy: 'cache-first',
conditions: {
cacheOn: ['2xx'],
skipCacheOn: ['4xx', '5xx']
}
}
};
Monitoring and Observability
Integration Metrics
interface IntegrationMetrics {
requestCount: number;
successCount: number;
errorCount: number;
averageResponseTime: number;
p95ResponseTime: number;
retryCount: number;
circuitBreakerStatus: 'closed' | 'open' | 'half-open';
}
const monitoringConfig = {
metrics: {
enabled: true,
interval: 30000,
tags: {
service: 'external-api',
environment: 'production'
}
},
alerting: {
errorRate: {
threshold: 0.05, // 5%
window: '5m'
},
responseTime: {
threshold: 5000, // 5 seconds
window: '1m'
}
}
};
Security Best Practices
Credential Management
- Store sensitive credentials in environment variables or secure vaults
- Use short-lived tokens when possible
- Implement credential rotation policies
- Never log or expose credentials in workflow outputs
Network Security
- Use HTTPS/TLS for all external communications
- Implement proper certificate validation
- Use VPN or private networks for sensitive integrations
- Apply network firewall rules and IP whitelisting
Data Protection
- Encrypt sensitive data in transit and at rest
- Implement data masking for logs and monitoring
- Apply data retention policies
- Use secure data transformation techniques
Common Integration Patterns
Fan-Out Pattern
const fanOutPattern = {
trigger: 'order-created',
parallel: [
{ node: 'update-inventory' },
{ node: 'send-confirmation-email' },
{ node: 'update-analytics' },
{ node: 'notify-shipping' }
],
joinStrategy: 'wait-all'
};
Scatter-Gather Pattern
const scatterGatherPattern = {
scatter: {
type: 'parallel-requests',
nodes: [
{ id: 'price-service-a', url: 'https://price-a.com/quote' },
{ id: 'price-service-b', url: 'https://price-b.com/quote' },
{ id: 'price-service-c', url: 'https://price-c.com/quote' }
]
},
gather: {
type: 'aggregate-results',
strategy: 'best-price',
timeout: 10000
}
};
Saga Pattern
const sagaPattern = {
steps: [
{
action: 'reserve-inventory',
compensation: 'release-inventory'
},
{
action: 'charge-payment',
compensation: 'refund-payment'
},
{
action: 'ship-order',
compensation: 'cancel-shipment'
}
],
onFailure: 'compensate-all'
};
Testing Integration Workflows
Mock Services
const mockServiceConfig = {
id: 'mock-payment-service',
type: 'mock-http-service',
config: {
port: 3001,
routes: [
{
path: '/charge',
method: 'POST',
response: {
status: 200,
body: {
transactionId: 'mock-${random.uuid}',
status: 'success',
amount: '${request.body.amount}'
}
},
delay: 1000 // Simulate network delay
}
]
}
};
Integration Testing
const integrationTest = {
name: 'Order Processing Integration Test',
setup: {
mockServices: ['payment-service', 'inventory-service'],
testData: './test-data/orders.json'
},
workflow: 'order-processing-workflow',
assertions: [
{
type: 'api-call-made',
service: 'payment-service',
endpoint: '/charge'
},
{
type: 'output-contains',
field: 'orderId',
pattern: /^ORD-\d+$/
},
{
type: 'execution-time',
maxDuration: 30000
}
]
};