Integration Guide
SoftyFlow provides comprehensive integration capabilities that allow you to connect with external systems and services. This guide covers the three main integration methods available in SoftyFlow.
1. EDS API Integration (Outgoing Integrations)
Overview
External Data Sources (EDS) API integration allows SoftyFlow to consume external REST APIs as data sources. This enables seamless integration with third-party services and systems.
API EDS Configuration
Configure API EDS to connect with external REST APIs:
{
baseURL: "https://api.example.com", // Base API URL (optional)
timeout: 30000, // Request timeout in milliseconds
connectionUrl: "/health", // Test connection endpoint
headers: { // Global headers
"Content-Type": "application/json",
"Accept": "application/json"
},
runScript: ` // Pre-execution script
// Fetch authentication token
const response = await SF.utils.axios.get('/auth/token', {
headers: { 'X-API-Key': 'your-api-key' }
});
return {
authToken: response.data.token
};
`,
endpoints: [ // API endpoint definitions
{
type: "retrieve", // Operation type
method: "GET", // HTTP method
value: "/{{SF_table}}/{{SF_source._id}}", // URL pattern
headers: { // Endpoint-specific headers
"Authorization": "Bearer {{authToken}}"
},
params: { // Query parameters
"include": ["relations"],
"fields": "{{SF_source.fields}}"
},
response: ` // Response transformation
return SF_result.data;
`
}
]
}
Available API Endpoint Types
- retrieve: Get single record by ID
- list: Get multiple records with pagination
- count: Count records matching criteria
- insert: Create new record
- insertMany: Create multiple records
- update: Update existing record
- delete: Delete record
- execute: Custom operations
Context Variables Available
SF_source
: Data source and query parametersSF_table
: Table/resource nameSF_postData
: Data for POST/PUT operationsSF_limit
: Maximum records to retrieveSF_sortby
: Sort field nameSF_page
: Current page numberSF_direction
: Sort direction (1 or -1)
Complete API EDS Example
{
baseURL: "https://jsonplaceholder.typicode.com",
timeout: 30000,
connectionUrl: "/posts/1",
headers: {
"Content-Type": "application/json"
},
runScript: `return { timestamp: Date.now() }`,
endpoints: [
{
type: "retrieve",
method: "GET",
value: "/{{SF_table}}/{{SF_source._id}}",
headers: "{}",
params: "{}",
response: "return SF_result"
},
{
type: "list",
method: "GET",
value: "/{{SF_table}}",
headers: "{}",
params: `{
_page: SF_page,
_limit: SF_limit,
_sort: SF_sortby,
_order: SF_direction === 1 ? 'asc' : 'desc'
}`,
response: "return SF_result"
},
{
type: "insert",
method: "POST",
value: "/{{SF_table}}",
headers: "{}",
params: "SF_postData",
response: "return SF_result"
}
]
}
Using API EDS in Actions
{
action: "findMany (EDS)",
parameters: {
dumpVar: "apiData",
clientDatabase: { _id: "my_api_eds", name: "External API" },
table: "users",
find: {
status: "active",
department: "{{selectedDepartment}}"
}
}
}
Using API EDS in Widgets
{
name: "External Data Table",
model: "externalData",
options: {
remote: "EDS",
clientDatabase: {
_id: "api_eds",
name: "External API"
},
edsSource: "users",
query: {
status: "active",
department: "{{selectedDepartment}}"
},
sortBy: "created_at",
direction: -1,
limit: 25
}
}
2. Scripts via Axios (Process Modeler SDK)
Overview
The Process Modeler SDK provides access to axios for making HTTP requests within process scripts, allowing for flexible API integrations during workflow execution.
Basic Axios Usage
// GET request
let response = await SF.utils.axios.get('/data/json/123')
.then(function (response) {
// handle success
console.log(response);
return response.data;
}).catch(function (error) {
// handle error
console.log(error);
});
POST Requests
// POST request with data
let body = {
"email": "client1@gmail.com",
"name": "John Doe"
}
let result = await SF.utils.axios.post('https://api.example.com/users', body, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}
});
PUT Requests
// PUT request for updates
let updateData = {
"status": "active",
"lastLogin": new Date()
}
let updateResult = await SF.utils.axios.put('https://api.example.com/users/123', updateData);
DELETE Requests
// DELETE request
let deleteResult = await SF.utils.axios.delete('https://api.example.com/users/123');
Authentication Examples
Bearer Token Authentication
let config = {
headers: {
'Authorization': 'Bearer ' + authToken,
'Content-Type': 'application/json'
}
};
let result = await SF.utils.axios.get('https://api.example.com/protected', config);
API Key Authentication
let apiConfig = {
headers: {
'X-API-Key': 'your-api-key',
'Content-Type': 'application/json'
}
};
let apiResult = await SF.utils.axios.post('https://api.example.com/data', data, apiConfig);
Complex Integration Example
// Multi-step API integration
try {
// Step 1: Authenticate
let authResponse = await SF.utils.axios.post('https://api.example.com/auth', {
username: 'user',
password: 'pass'
});
let token = authResponse.data.token;
// Step 2: Fetch data with authentication
let dataResponse = await SF.utils.axios.get('https://api.example.com/data', {
headers: {
'Authorization': 'Bearer ' + token
}
});
// Step 3: Process and store data
let processedData = dataResponse.data.map(item => ({
id: item.id,
name: item.name,
processed_at: new Date()
}));
// Step 4: Save to SoftyFlow collection
await SF.collection.insertMany("external_data", processedData);
return { success: true, count: processedData.length };
} catch (error) {
console.error('Integration failed:', error);
return { success: false, error: error.message };
}
3. Incoming APIs (SoftyFlow APIs)
Overview
SoftyFlow allows you to create APIs that external systems can call, enabling inbound integrations and webhooks.
API Configuration Variables
When creating SoftyFlow APIs, these variables are available:
- SF_body: Contains API body data
- SF_headers: Contains API header data
- SF_query: Contains API query data
- SF_mode: The execution mode of the API (test, uat, prod)
- SF_initiator: Contains the user who launched the API
Example API Implementation
// Process incoming data
let requestData = SF_body;
let headers = SF_headers;
let queryParams = SF_query;
// Validate incoming data
if (!requestData.email) {
return {
error: "Email is required",
status: 400
};
}
// Process the request
let result = await SF.collection.insertOne("customers", {
email: requestData.email,
name: requestData.name,
created_at: new Date(),
created_by: SF_initiator._id
});
// Return response
return {
success: true,
customer_id: result.insertedId,
message: "Customer created successfully"
};
Advanced API Example
// Advanced customer management API
let { action, customerId, customerData } = SF_body;
let authHeader = SF_headers.authorization;
// Authentication check
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return {
error: "Unauthorized",
status: 401
};
}
try {
switch (action) {
case 'create':
// Validate required fields
if (!customerData.email || !customerData.name) {
return {
error: "Email and name are required",
status: 400
};
}
// Check if customer exists
let existingCustomer = await SF.collection.findOne("customers", {
email: customerData.email
});
if (existingCustomer) {
return {
error: "Customer already exists",
status: 409
};
}
// Create customer
let newCustomer = await SF.collection.insertOne("customers", {
...customerData,
created_at: new Date(),
created_by: SF_initiator._id
});
return {
success: true,
customer: newCustomer,
message: "Customer created successfully"
};
case 'update':
if (!customerId) {
return {
error: "Customer ID is required",
status: 400
};
}
let updatedCustomer = await SF.collection.updateOne("customers",
{ _id: customerId },
{
...customerData,
updated_at: new Date(),
updated_by: SF_initiator._id
}
);
return {
success: true,
customer: updatedCustomer,
message: "Customer updated successfully"
};
case 'delete':
if (!customerId) {
return {
error: "Customer ID is required",
status: 400
};
}
await SF.collection.deleteOne("customers", { _id: customerId });
return {
success: true,
message: "Customer deleted successfully"
};
case 'get':
if (customerId) {
let customer = await SF.collection.findOne("customers", { _id: customerId });
return {
success: true,
customer: customer
};
} else {
let customers = await SF.collection.find("customers", {});
return {
success: true,
customers: customers
};
}
default:
return {
error: "Invalid action",
status: 400
};
}
} catch (error) {
return {
error: "Internal server error",
message: error.message,
status: 500
};
}
Calling SoftyFlow APIs
1. Using InvokeApi Action
{
action: "InvokeApi",
parameters: {
api: { _id: "api_id", name: "Customer API" },
dumpVar: "apiResponse",
body: {
action: "create",
customerData: {
email: "customer@example.com",
name: "John Smith"
}
}
}
}
2. Using External HTTP Calls
let body = {
"action": "create",
"customerData": {
"email": "client1@gmail.com",
"name": "John Doe"
}
}
let apiUrl = "https://softydev.softyflow.io/api/v1/api/6491696d1ef51ed2f7044b79?SF_mode=prod";
// SF_mode values: test, uat, prod
let result = await axios.post(apiUrl, body, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your-token'
}
});
API Access Control
- Configure access rights by selecting user groups
- Set APIs as public for external access
- Monitor API usage through logs
- Track API calls with user information and timestamps
API Testing
SoftyFlow provides built-in API testing capabilities:
- Define test variables in JSON format
- Use the eye button to test during development
- View results in the lower section
- Monitor logs for debugging
Best Practices
Security
- Always validate input data
- Implement proper authentication
- Use HTTPS for all API communications
- Sanitize data before processing
Error Handling
- Implement comprehensive error handling
- Return meaningful error messages
- Log errors for debugging
- Use appropriate HTTP status codes
Performance
- Implement request timeouts
- Use connection pooling where applicable
- Cache responses when appropriate
- Monitor API performance
Documentation
- Document all API endpoints
- Provide clear examples
- Maintain version compatibility
- Update documentation with changes
This comprehensive integration guide enables you to leverage SoftyFlow's full integration capabilities, whether you're consuming external APIs through EDS, making HTTP requests via axios scripts, or exposing SoftyFlow functionality through incoming APIs.