End
Workflow execution exit point that defines output parameters and HTTP responses.
The End node terminates workflow execution and defines the response structure returned to the calling system. It handles output formatting, HTTP response configuration, and error handling for completed workflows.
┌─────────────────────────────────────────────────────────┐
│ WORKFLOW COMPLETION │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ PROCESS │────▶│ LOGIC │────▶│ END │ │
│ │ NODES │ │ NODES │ │ NODE │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │ │ │ │
│ Data Processing Business Logic Response │
│ │ │ │ │
│ └───── Workflow Execution ──────┘ │
│ │ │
│ ┌─────▼─────┐ │
│ │ CALLER │ │
│ │ RESPONSE │ │
│ └───────────┘ │
│ │
└─────────────────────────────────────────────────────────┘Configuration (Readonly)
| Property | Value |
|---|---|
| Code | end |
| Node Type | END |
| Workflow Types | Workflow only (not Agentflow) |
Connections
| Direction | Description |
|---|---|
| Incoming | Receives flow from workflow execution |
| Outgoing | None (terminates workflow) |
Output Configuration
The End node defines the data contract for your workflow's response. Unlike standard processing nodes that have predefined outputs (data, success, error), End nodes use completely custom, user-defined output structures tailored to your specific workflow requirements.
End Node vs Component Outputs
| Type | Output Structure | Purpose | Example |
|---|---|---|---|
| Standard Components | Fixed: data, success, error | Internal processing | Script, Logger, API calls |
| End Node | Custom: User-defined fields | External response | result, status, metadata |
Output Field Configuration
Each End node output field supports the same configuration options as Start node inputs:
| Option | Purpose | Example | Applies To |
|---|---|---|---|
| Code | Unique field identifier | "customerData" | All types |
| Name | Display name | "Customer Information" | All types |
| Type | Data type | text, integer, object | All types |
| Required | Field must be present | ✓ Response status | All types |
| Array | Multiple values | ✓ List of results | All types |
| Description | Documentation | "Processed customer data" | All types |
| Source Value | Context expression (see below) | See Context Expressions section | All types |
Output Field Types
| Type | Description | Example Source Value |
|---|---|---|
| Text | String values | {{ctx.nodes.formatter.outputs.message}} |
| Integer | Whole numbers | {{ctx.nodes.counter.outputs.total}} |
| Fractional | Decimal numbers | {{ctx.nodes.calculator.outputs.average}} |
| Boolean | True/false values | {{ctx.nodes.validator.outputs.isValid}} |
| Object | JSON objects | {{ctx.nodes.aggregator.outputs.summary}} |
| Array | Lists of values | {{ctx.nodes.collector.outputs.items}} |
| File | File references | {{ctx.nodes.generator.outputs.reportFile}} |
Context Expressions for Output Values
End nodes use context expressions to populate output values by accessing data from the workflow execution context. These expressions work in both Parameters mode (individual fields) and Inline mode (entire response body).
For comprehensive context documentation including expression syntax, built-in functions, and advanced patterns, see the Workflow Context guide.
Quick Context Reference
Basic Node Output Access:
{{ctx.nodes.nodeCode.outputs.outputField}}Common Expression Patterns:
| Data Source | Expression | Example Value |
|---|---|---|
| Start node inputs | {{ctx.nodes.start.inputs.fieldName}} | User-provided data |
| Node output data | {{ctx.nodes.processor.outputs.data}} | Processed results |
| Node success status | {{ctx.nodes.validator.outputs.success}} | true/false |
| Workflow variables | {{ctx.vars.variableName}} | Workflow-scoped variables |
| User information | {{ctx.user.id}} / {{ctx.user.login}} | Current user details |
Parameters Mode Examples
Simple Status Response:
{
"status": {
"code": "status",
"type": "text",
"required": true,
"sourceValue": "success",
"description": "Operation completion status"
}
}Complex Data Response:
{
"customerInfo": {
"code": "customerInfo",
"type": "object",
"required": true,
"sourceValue": "{{ctx.nodes.customerProcessor.outputs.data}}",
"description": "Processed customer information"
},
"orderCount": {
"code": "orderCount",
"type": "integer",
"required": false,
"sourceValue": "{{ctx.nodes.orderCounter.outputs.total}}",
"description": "Total number of orders processed"
},
"warnings": {
"code": "warnings",
"type": "text",
"required": false,
"isArray": true,
"sourceValue": "{{ctx.nodes.validator.outputs.warnings}}",
"description": "Processing warnings"
}
}Aggregated Results:
{
"summary": {
"code": "summary",
"type": "object",
"required": true,
"sourceValue": "{
\"processedCount\": {{ctx.nodes.processor.outputs.data.count}},
\"startTime\": \"{{ctx.nodes.start.inputs.timestamp}}\",
\"endTime\": \"{{ctx.current_timestamp}}\",
\"results\": {{ctx.nodes.aggregator.outputs.data}}
}",
"description": "Workflow execution summary"
}
}Inline Mode
Return raw response body using the bodySourceValue field:
{
"bodySourceValue": "{{ctx.nodes.fileProcessor.outputs.content}}"
}Use Cases:
- File content delivery (text files, JSON, CSV)
- Simple string responses
- Binary data streaming
- Custom formatted responses
Output Mode Toggle
The End node UI provides a mode toggle that switches between:
| Mode | Description | UI Behavior | Configuration |
|---|---|---|---|
| Parameters Mode | Custom output fields | Shows "Outputs" section with add/remove fields | Uses individual output field configurations |
| Inline Mode | Raw body content | Shows "Outputs" text area | Uses bodySourceValue for entire response body |
Switching Modes:
- Toggle "As inline" switch in the End node panel
- Parameters mode: Define structured output fields
- Inline mode: Write expression for entire response body
Mode Selection Guidelines:
- Use Parameters Mode for: APIs with structured responses, multi-field outputs, validation requirements
- Use Inline Mode for: File delivery, simple text responses, pass-through scenarios
HTTP Endpoint Configuration
Configure HTTP response behavior when workflow is triggered via HTTP endpoints. The End node provides separate configuration fields for HTTP responses that are independent of the output data structure.
| Setting | Field | Description | Example |
|---|---|---|---|
| Method | method | HTTP method | GET, POST, PUT, PATCH, DELETE |
| Path | path | URL endpoint path | /api/v1/process-order |
| Status Code | statusSourceValue | HTTP response status (static or dynamic) | "200", "{{ctx.nodes.validator.outputs.statusCode}}" |
| Headers | headersSourceValue | Custom response headers (JSON expression) | "{{\"Content-Type\": \"application/json\"}}" |
| Body | bodySourceValue | Response body content (uses End node outputs) | "{{ctx.nodes.end.outputs}}" |
Status Source Value
The statusSourceValue field is separate from output configuration and specifically controls the HTTP status code returned to the caller. This field supports both static values and dynamic expressions.
Static Status Codes:
{
"statusSourceValue": "200" // Always return 200 OK
}Dynamic Status Codes:
{
"statusSourceValue": "{{ctx.nodes.validator.outputs.success ? 200 : 400}}"
}Conditional Status Based on Results:
{
"statusSourceValue": "{
const errors = {{ctx.nodes.processor.outputs.error}};
const success = {{ctx.nodes.processor.outputs.success}};
if (!success && errors.includes('VALIDATION_ERROR')) return 400;
if (!success && errors.includes('NOT_FOUND')) return 404;
if (!success) return 500;
return 200;
}"
}Status from Processing Results:
{
"statusSourceValue": "{{ctx.nodes.apiCall.outputs.data.responseCode || 200}}"
}
### HTTP Status Codes
Configure appropriate status codes using the `statusSourceValue` field:
| Status | When to Use | Example statusSourceValue | Use Case |
|--------|-------------|---------------------------|----------|
| **200 OK** | Successful operation | `"200"` | Data retrieved/updated successfully |
| **201 Created** | Resource created | `"{{ctx.nodes.dbInsert.outputs.success ? 201 : 400}}"` | New record created |
| **204 No Content** | Successful DELETE | `"204"` | Resource deleted, no response body |
| **400 Bad Request** | Validation failed | `"{{ctx.nodes.validator.outputs.valid ? 200 : 400}}"` | Invalid input data |
| **404 Not Found** | Resource missing | `"{{ctx.nodes.lookup.outputs.found ? 200 : 404}}"` | Record doesn't exist |
| **500 Internal Server Error** | Processing error | `"{{ctx.nodes.processor.outputs.success ? 200 : 500}}"` | Workflow execution failed |
### Complete HTTP Configuration Example
```json
{
"method": "POST",
"path": "/api/v1/users",
"statusSourceValue": "{{ctx.nodes.userCreator.outputs.success ? (ctx.nodes.userCreator.outputs.data.isNew ? 201 : 200) : 400}}",
"headersSourceValue": "{
\"Content-Type\": \"application/json\",
\"X-Request-ID\": \"{{ctx.execution_id}}\",
\"Cache-Control\": \"no-cache\"
}",
"bodySourceValue": "{{ctx.nodes.end.outputs}}"
}
## Response Patterns
### API Success Response
```json
{
"success": true,
"data": {
"id": "{{createdId}}",
"name": "{{processedName}}",
"status": "active"
},
"meta": {
"timestamp": "{{ctx.current_timestamp}}",
"version": "v1"
}
}API Error Response
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "{{errorMessage}}",
"details": "{{validationErrors}}"
},
"meta": {
"timestamp": "{{ctx.current_timestamp}}",
"requestId": "{{ctx.execution_id}}"
}
}Data Transformation Response
{
"originalCount": "{{inputData.length}}",
"processedCount": "{{outputData.length}}",
"transformedData": "{{outputData}}",
"processingTime": "{{executionTime}}ms"
}File Processing Response
{
"fileName": "{{originalFileName}}",
"fileSize": "{{outputFileSize}}",
"downloadUrl": "{{generatedUrl}}",
"expiresAt": "{{urlExpiration}}"
}Advanced Output Patterns
Multi-Node Data Aggregation:
{
"customerProfile": {
"code": "customerProfile",
"type": "object",
"sourceValue": "{{ctx.nodes.customerLookup.outputs.data}}",
"description": "Customer information from database"
},
"orderHistory": {
"code": "orderHistory",
"type": "object",
"sourceValue": "{{ctx.nodes.orderProcessor.outputs.data}}",
"description": "Processed order history"
},
"recommendations": {
"code": "recommendations",
"type": "object",
"sourceValue": "{{ctx.nodes.aiRecommendations.outputs.data}}",
"description": "AI-generated product recommendations"
},
"processingMetadata": {
"code": "processingMetadata",
"type": "object",
"sourceValue": "{
\"startTime\": \"{{ctx.nodes.start.inputs.requestTimestamp}}\",
\"endTime\": \"{{ctx.current_timestamp}}\",
\"nodesExecuted\": [\"customerLookup\", \"orderProcessor\", \"aiRecommendations\"],
\"executionId\": \"{{ctx.execution_id}}\"
}",
"description": "Workflow execution metadata"
}
}Conditional Output Based on Results:
{
"result": {
"code": "result",
"type": "object",
"sourceValue": "{
\"status\": {{ctx.nodes.validator.outputs.success}} ? \"success\" : \"failure\",
\"data\": {{ctx.nodes.processor.outputs.data}},
\"errors\": {{ctx.nodes.validator.outputs.success}} ? [] : {{ctx.nodes.validator.outputs.error}},
\"retryable\": {{ctx.nodes.errorHandler.outputs.data.canRetry}}
}",
"description": "Conditional response based on validation results"
}
}Array Aggregation from Multiple Nodes:
{
"allResults": {
"code": "allResults",
"type": "object",
"sourceValue": "{
\"processed\": [{{ctx.nodes.step1.outputs.data}}, {{ctx.nodes.step2.outputs.data}}, {{ctx.nodes.step3.outputs.data}}],
\"summary\": {
\"totalItems\": {{ctx.nodes.step1.outputs.data.count}} + {{ctx.nodes.step2.outputs.data.count}} + {{ctx.nodes.step3.outputs.data.count}},
\"successfulSteps\": [{{ctx.nodes.step1.outputs.success}}, {{ctx.nodes.step2.outputs.success}}, {{ctx.nodes.step3.outputs.success}}].filter(x => x).length
}
}",
"description": "Aggregated results from parallel processing steps"
}
}Input Pass-Through with Processing Results:
{
"originalRequest": {
"code": "originalRequest",
"type": "object",
"sourceValue": "{{ctx.nodes.start.inputs}}",
"description": "Original input parameters"
},
"processedResponse": {
"code": "processedResponse",
"type": "object",
"sourceValue": "{{ctx.nodes.finalProcessor.outputs.data}}",
"description": "Processed workflow results"
},
"correlationId": {
"code": "correlationId",
"type": "text",
"sourceValue": "{{ctx.nodes.start.inputs.requestId}}",
"description": "Request correlation identifier"
}
}Content Types
Configure appropriate content types for different response formats:
| Content Type | Use Case | Example |
|---|---|---|
application/json | Structured data | API responses |
text/plain | Plain text | Log files, simple text |
text/csv | Tabular data | Data exports |
application/xml | XML data | SOAP responses |
application/pdf | Generated documents | Reports, invoices |
image/png | Generated images | Charts, graphics |
Error Handling
Error Response Structure
{
"error": {
"type": "{{errorType}}",
"message": "{{errorMessage}}",
"code": "{{errorCode}}",
"timestamp": "{{ctx.current_timestamp}}"
},
"context": {
"workflowId": "{{ctx.workflow_id}}",
"executionId": "{{ctx.execution_id}}",
"failedNode": "{{errorSource}}"
}
}Status Code Mapping
Map workflow errors to appropriate HTTP status codes:
{
"validationError": 400,
"authenticationError": 401,
"authorizationError": 403,
"notFoundError": 404,
"rateLimit": 429,
"processingError": 500,
"serviceUnavailable": 503
}Security and Headers
Security Headers
{
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000"
}CORS Headers
{
"Access-Control-Allow-Origin": "{{allowedOrigin}}",
"Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Max-Age": "86400"
}Cache Control
{
"Cache-Control": "no-cache, no-store, must-revalidate",
"Pragma": "no-cache",
"Expires": "0"
}Integration Patterns
REST API Pattern
{
"method": "POST",
"path": "/api/v1/users",
"statusCode": 201,
"headers": {
"Content-Type": "application/json",
"Location": "/api/v1/users/{{createdUserId}}"
},
"response": {
"id": "{{createdUserId}}",
"name": "{{userName}}",
"email": "{{userEmail}}",
"createdAt": "{{ctx.current_timestamp}}"
}
}Webhook Response Pattern
{
"method": "POST",
"path": "/webhooks/{{eventType}}",
"statusCode": 200,
"response": {
"received": true,
"eventId": "{{ctx.execution_id}}",
"processedAt": "{{ctx.current_timestamp}}"
}
}File Download Pattern
{
"method": "GET",
"path": "/files/{{fileId}}/download",
"statusCode": 200,
"headers": {
"Content-Type": "{{fileContentType}}",
"Content-Disposition": "attachment; filename=\"{{fileName}}\"",
"Content-Length": "{{fileSize}}"
},
"response": "{{fileContent}}"
}Working with End Nodes in Studio
Configuring Outputs
Adding Output Fields (Parameters Mode):
- Open the End node by clicking on it
- In the "Outputs" section, click "+ Add Parameter"
- Select the field type (Text, Integer, Object, etc.)
- Configure field properties:
- Code: Unique identifier for the field
- Name: Display name for the field
- Type: Data type (affects validation)
- Required: Whether field must be present
- Array: Enable for multiple values
- Source Value: Expression to populate the field
Configuring HTTP Endpoint:
- In the End node panel, find the HTTP configuration section
- Configure:
- Status Code: Static value (
"200") or dynamic expression - Headers: JSON object with response headers
- Status Code: Static value (
- The system automatically uses the node outputs for the response body
Mode Switching:
- Toggle between Parameters and Inline mode using the "As inline" switch
- Parameters mode: Structured field-by-field configuration
- Inline mode: Single expression for entire response body
UI Features
| Feature | Location | Purpose | Example |
|---|---|---|---|
| Output Fields | Outputs section | Define response structure | customerData, status, timestamp |
| Mode Toggle | Top right of outputs | Switch between parameter/inline mode | "As inline" checkbox |
| Status Code Field | HTTP configuration | Control HTTP response status | "{{success ? 200 : 400}}" |
| Headers Field | HTTP configuration | Set response headers | {"Content-Type": "application/json"} |
| Add Parameter | Outputs section | Create new output field | Click to add Text, Object, etc. |
Studio Workflow Tips
Development Process:
- Plan Output Structure: Decide what data the workflow should return
- Start with Parameters Mode: Define structured outputs first
- Add Fields Incrementally: Create one output field at a time
- Test Expressions: Validate source value expressions work correctly
- Configure HTTP Settings: Set appropriate status codes and headers
- Switch to Inline Mode: If simple string response is preferred
Field Configuration Best Practices:
- Use descriptive codes: Choose meaningful identifiers like
customerProfileinstead ofdata1 - Set appropriate types: Match field types to actual data being returned
- Mark required fields: Identify which outputs are mandatory
- Add descriptions: Document what each field contains for team members
- Order fields logically: Use the UI ordering to organize outputs sensibly
Best Practices
Response Design
- Consistent structure: Use standardized response format
- Include metadata: Add timestamps, versions, request IDs
- Clear error messages: Provide actionable error information
- Appropriate status codes: Use correct HTTP status codes
Performance Optimization
- Minimize response size: Only include necessary data
- Use appropriate caching: Set cache headers for static responses
- Stream large responses: Consider streaming for large payloads
- Compress responses: Enable gzip compression
Security Considerations
- Sanitize outputs: Clean response data to prevent XSS
- Rate limiting: Include rate limit headers
- Audit logging: Log response data for security audits
- Data privacy: Exclude sensitive information from responses
Troubleshooting
Common Issues
| Problem | Cause | Solution |
|---|---|---|
| Empty response | Output mapping error | Check field mappings |
| Wrong status code | Incorrect HTTP configuration | Review status code settings |
| Header issues | Invalid header values | Validate header format |
| JSON parsing errors | Invalid JSON structure | Validate response structure |
Debugging Tips
- Test responses: Use test values to verify output
- Check logs: Review execution logs for output generation
- Validate JSON: Ensure JSON responses are valid
- Monitor performance: Track response times and sizes
Response Validation
// Example response validation
const responseSchema = {
type: "object",
properties: {
success: { type: "boolean" },
data: { type: "object" },
timestamp: { type: "string" }
},
required: ["success", "data"]
};