Queue Async Processing
This guide explains how to enable and configure asynchronous processing for your Integration API endpoints.
Overview
The Queue Async Processing feature allows you to process API requests asynchronously using AWS SNS/SQS queues. When enabled, requests are published to an SNS topic, processed asynchronously via SQS, and results are sent back via a callback endpoint.
How to Enable Async Processing
The Integration API library provides pre-configured async-enabled endpoints. To use them, you need to manually configure the required properties - no code changes or annotations are needed.
What you need to do:
-
Manually add all required stream configuration properties (SNS/SQS setup)
-
Configure callback settings (optional)
-
Enable the specific endpoints you want to use asynchronously
-
Configure the Notify Async Stream (required for callback functionality)
Note: Property auto-configuration (integrationlayer.async.processing.property.autoconfigure.enabled) is always set to false and should not be changed. All properties must be configured manually.
Notify Async Stream Configuration
The Notify Async Stream is a dedicated queue that handles callback notifications after async processing completes. This stream is required when you want to receive callbacks about the processing results.
How It Works
When an async endpoint finishes processing (either successfully or with an error), it publishes a notification message to the Notify Async Stream. This stream then:
-
Receives the notification message via SNS
-
Processes it via SQS
-
Calls the configured callback endpoint with the processing result
Configuration Properties
Add the following properties to your setup.properties to enable the Notify Async Stream:
# ============================================
# Notify Async Stream Configuration
# ============================================
# Publisher configuration (SNS)
# Add snsIntegrationApiNotifyAsync to the foundation.stream.pub list
foundation.stream.pub.snsIntegrationApiNotifyAsync.spout=*.spout.AsyncProcessingNotifyMessage
foundation.stream.pub.snsIntegrationApiNotifyAsync.target=integrationApiNotifyAsyncTarget
# SNS Target
foundation.stream.target.integrationApiNotifyAsyncTarget.type=SNS
foundation.stream.target.integrationApiNotifyAsyncTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiNotifyAsyncTarget.topic=IntegrationApi-NotifyAsync
# Subscriber configuration (SQS)
# Add integrationApiNotifyAsync to the foundation.stream.sub list
foundation.stream.sub.integrationApiNotifyAsync.spin=*.spin.AsyncProcessingEventNotifyMessage
foundation.stream.sub.integrationApiNotifyAsync.source=integrationApiNotifyAsyncSub
foundation.stream.sub.integrationApiNotifyAsync.spin.agent=integrationApiNotifyAsyncAgent
foundation.stream.sub.integrationApiNotifyAsync.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiNotifyAsyncSub.type=SQS
foundation.stream.source.integrationApiNotifyAsyncSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiNotifyAsyncSub.topic=IntegrationApi-NotifyAsync
foundation.stream.source.integrationApiNotifyAsyncSub.logging=true
foundation.stream.source.integrationApiNotifyAsyncSub.emergencyTopic=IntegrationApi-NotifyAsync-DLQ
Important Notes
-
The Notify Async Stream must be included in both
foundation.stream.pubandfoundation.stream.sublists -
Example when enabling async processing with notify stream:
foundation.stream.pub=snsIntegrationApiPostAssetsR1Assets,snsIntegrationApiNotifyAsync foundation.stream.sub=integrationApiPostAssetsR1Assets,integrationApiNotifyAsync -
The Notify Async Stream is shared across all async endpoints - you only need to configure it once
-
If no callback endpoint is configured, the notify messages will still be processed but no external call will be made
AWS Resources for Notify Async Stream
Create the following AWS resources:
|
Resource Type |
Name |
|---|---|
|
SNS Topic |
|
|
SQS Queue |
|
|
DLQ |
|
Pre-configured Async Endpoints
The following endpoints are pre-configured for async processing. Copy and paste the configuration for the endpoints you want to enable:
1. POST /integration/assets/r1/accounts
Property Key: integrationApiPostAssetsR1Accounts
# Enable endpoint
integrationlayer.async.processing.integrationApiPostAssetsR1Accounts.enabled=true
# Publisher configuration (SNS)
foundation.stream.pub=snsIntegrationApiPostAssetsR1Accounts
foundation.stream.pub.snsIntegrationApiPostAssetsR1Accounts.spout=*.spout.PostIntegrationAssetsR1AccountsAsyncProcessingRequestMessage
foundation.stream.pub.snsIntegrationApiPostAssetsR1Accounts.target=integrationApiPostAssetsR1AccountsTarget
# SNS Target
foundation.stream.target.integrationApiPostAssetsR1AccountsTarget.type=SNS
foundation.stream.target.integrationApiPostAssetsR1AccountsTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiPostAssetsR1AccountsTarget.topic=IntegrationApi-IntegrationApiPostAssetsR1Accounts
# Subscriber configuration (SQS)
foundation.stream.sub=integrationApiPostAssetsR1Accounts
foundation.stream.sub.integrationApiPostAssetsR1Accounts.spin=*.spin.PostIntegrationAssetsR1AccountsAsyncProcessingEventRequestMessage
foundation.stream.sub.integrationApiPostAssetsR1Accounts.source=integrationApiPostAssetsR1AccountsSub
foundation.stream.sub.integrationApiPostAssetsR1Accounts.spin.agent=integrationApiPostAssetsR1AccountsAgent
foundation.stream.sub.integrationApiPostAssetsR1Accounts.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiPostAssetsR1AccountsSub.type=SQS
foundation.stream.source.integrationApiPostAssetsR1AccountsSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiPostAssetsR1AccountsSub.topic=IntegrationApi-IntegrationApiPostAssetsR1Accounts
foundation.stream.source.integrationApiPostAssetsR1AccountsSub.logging=true
foundation.stream.source.integrationApiPostAssetsR1AccountsSub.emergencyTopic=IntegrationApi-IntegrationApiPostAssetsR1Accounts-DLQ
2. POST /integration/assets/r1/assets
Property Key: integrationApiPostAssetsR1Assets
# Enable endpoint
integrationlayer.async.processing.integrationApiPostAssetsR1Assets.enabled=true
# Publisher configuration (SNS)
foundation.stream.pub=snsIntegrationApiPostAssetsR1Assets
foundation.stream.pub.snsIntegrationApiPostAssetsR1Assets.spout=*.spout.PostIntegrationAssetsR1AssetsAsyncProcessingRequestMessage
foundation.stream.pub.snsIntegrationApiPostAssetsR1Assets.target=integrationApiPostAssetsR1AssetsTarget
# SNS Target
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.type=SNS
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.topic=IntegrationApi-IntegrationApiPostAssetsR1Assets
# Subscriber configuration (SQS)
foundation.stream.sub=integrationApiPostAssetsR1Assets
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin=*.spin.PostIntegrationAssetsR1AssetsAsyncProcessingEventRequestMessage
foundation.stream.sub.integrationApiPostAssetsR1Assets.source=integrationApiPostAssetsR1AssetsSub
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin.agent=integrationApiPostAssetsR1AssetsAgent
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.type=SQS
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.topic=IntegrationApi-IntegrationApiPostAssetsR1Assets
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.logging=true
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.emergencyTopic=IntegrationApi-IntegrationApiPostAssetsR1Assets-DLQ
3. POST /integration/work-orders/r1/work-orders
Property Key: integrationApiPostWorkOrdersR1WorkOrders
# Enable endpoint
integrationlayer.async.processing.integrationApiPostWorkOrdersR1WorkOrders.enabled=true
# Publisher configuration (SNS)
foundation.stream.pub=snsIntegrationApiPostWorkOrdersR1WorkOrders
foundation.stream.pub.snsIntegrationApiPostWorkOrdersR1WorkOrders.spout=*.spout.PostIntegrationWorkOrdersR1WorkOrdersAsyncProcessingRequestMessage
foundation.stream.pub.snsIntegrationApiPostWorkOrdersR1WorkOrders.target=integrationApiPostWorkOrdersR1WorkOrdersTarget
# SNS Target
foundation.stream.target.integrationApiPostWorkOrdersR1WorkOrdersTarget.type=SNS
foundation.stream.target.integrationApiPostWorkOrdersR1WorkOrdersTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiPostWorkOrdersR1WorkOrdersTarget.topic=IntegrationApi-IntegrationApiPostWorkOrdersR1WorkOrders
# Subscriber configuration (SQS)
foundation.stream.sub=integrationApiPostWorkOrdersR1WorkOrders
foundation.stream.sub.integrationApiPostWorkOrdersR1WorkOrders.spin=*.spin.PostIntegrationWorkOrdersR1WorkOrdersAsyncProcessingEventRequestMessage
foundation.stream.sub.integrationApiPostWorkOrdersR1WorkOrders.source=integrationApiPostWorkOrdersR1WorkOrdersSub
foundation.stream.sub.integrationApiPostWorkOrdersR1WorkOrders.spin.agent=integrationApiPostWorkOrdersR1WorkOrdersAgent
foundation.stream.sub.integrationApiPostWorkOrdersR1WorkOrders.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.type=SQS
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.topic=IntegrationApi-IntegrationApiPostWorkOrdersR1WorkOrders
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.logging=true
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.emergencyTopic=IntegrationApi-IntegrationApiPostWorkOrdersR1WorkOrders-DLQ
4. PATCH /integration/work-orders/r1/work-orders
Property Key: integrationApiPatchWorkOrdersR1WorkOrders
# Enable endpoint
integrationlayer.async.processing.integrationApiPatchWorkOrdersR1WorkOrders.enabled=true
# Publisher configuration (SNS)
foundation.stream.pub=snsIntegrationApiPatchWorkOrdersR1WorkOrders
foundation.stream.pub.snsIntegrationApiPatchWorkOrdersR1WorkOrders.spout=*.spout.PatchIntegrationWorkOrdersR1WorkOrdersAsyncProcessingRequestMessage
foundation.stream.pub.snsIntegrationApiPatchWorkOrdersR1WorkOrders.target=integrationApiPatchWorkOrdersR1WorkOrdersTarget
# SNS Target
foundation.stream.target.integrationApiPatchWorkOrdersR1WorkOrdersTarget.type=SNS
foundation.stream.target.integrationApiPatchWorkOrdersR1WorkOrdersTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiPatchWorkOrdersR1WorkOrdersTarget.topic=IntegrationApi-IntegrationApiPatchWorkOrdersR1WorkOrders
# Subscriber configuration (SQS)
foundation.stream.sub=integrationApiPatchWorkOrdersR1WorkOrders
foundation.stream.sub.integrationApiPatchWorkOrdersR1WorkOrders.spin=*.spin.PatchIntegrationWorkOrdersR1WorkOrdersAsyncProcessingEventRequestMessage
foundation.stream.sub.integrationApiPatchWorkOrdersR1WorkOrders.source=integrationApiPatchWorkOrdersR1WorkOrdersSub
foundation.stream.sub.integrationApiPatchWorkOrdersR1WorkOrders.spin.agent=integrationApiPatchWorkOrdersR1WorkOrdersAgent
foundation.stream.sub.integrationApiPatchWorkOrdersR1WorkOrders.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiPatchWorkOrdersR1WorkOrdersSub.type=SQS
foundation.stream.source.integrationApiPatchWorkOrdersR1WorkOrdersSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiPatchWorkOrdersR1WorkOrdersSub.topic=IntegrationApi-IntegrationApiPatchWorkOrdersR1WorkOrders
foundation.stream.source.integrationApiPatchWorkOrdersR1WorkOrdersSub.logging=true
foundation.stream.source.integrationApiPatchWorkOrdersR1WorkOrdersSub.emergencyTopic=IntegrationApi-IntegrationApiPatchWorkOrdersR1WorkOrders-DLQ
5. POST /integration/workforce/r1/work-shift-exceptions
Property Key: integrationApiPostWorkforceR1WorkShiftExceptions
# Enable endpoint
integrationlayer.async.processing.integrationApiPostWorkforceR1WorkShiftExceptions.enabled=true
# Publisher configuration (SNS)
foundation.stream.pub=snsIntegrationApiPostWorkforceR1WorkShiftExceptions
foundation.stream.pub.snsIntegrationApiPostWorkforceR1WorkShiftExceptions.spout=*.spout.PostIntegrationWorkforceR1WorkShiftExceptionsAsyncProcessingRequestMessage
foundation.stream.pub.snsIntegrationApiPostWorkforceR1WorkShiftExceptions.target=integrationApiPostWorkforceR1WorkShiftExceptionsTarget
# SNS Target
foundation.stream.target.integrationApiPostWorkforceR1WorkShiftExceptionsTarget.type=SNS
foundation.stream.target.integrationApiPostWorkforceR1WorkShiftExceptionsTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiPostWorkforceR1WorkShiftExceptionsTarget.topic=IntegrationApi-IntegrationApiPostWorkforceR1WorkShiftExceptions
# Subscriber configuration (SQS)
foundation.stream.sub=integrationApiPostWorkforceR1WorkShiftExceptions
foundation.stream.sub.integrationApiPostWorkforceR1WorkShiftExceptions.spin=*.spin.PostIntegrationWorkforceR1WorkShiftExceptionsAsyncProcessingEventRequestMessage
foundation.stream.sub.integrationApiPostWorkforceR1WorkShiftExceptions.source=integrationApiPostWorkforceR1WorkShiftExceptionsSub
foundation.stream.sub.integrationApiPostWorkforceR1WorkShiftExceptions.spin.agent=integrationApiPostWorkforceR1WorkShiftExceptionsAgent
foundation.stream.sub.integrationApiPostWorkforceR1WorkShiftExceptions.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiPostWorkforceR1WorkShiftExceptionsSub.type=SQS
foundation.stream.source.integrationApiPostWorkforceR1WorkShiftExceptionsSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiPostWorkforceR1WorkShiftExceptionsSub.topic=IntegrationApi-IntegrationApiPostWorkforceR1WorkShiftExceptions
foundation.stream.source.integrationApiPostWorkforceR1WorkShiftExceptionsSub.logging=true
foundation.stream.source.integrationApiPostWorkforceR1WorkShiftExceptionsSub.emergencyTopic=IntegrationApi-IntegrationApiPostWorkforceR1WorkShiftExceptions-DLQ
Important Notes:
-
If you enable multiple endpoints, combine the
foundation.stream.pubandfoundation.stream.subproperties with comma-separated values -
Always include the Notify Async Stream when using callbacks
-
Example for enabling 2 endpoints with notify stream:
foundation.stream.pub=snsIntegrationApiPostAssetsR1Assets,snsIntegrationApiPostWorkOrdersR1WorkOrders,snsIntegrationApiNotifyAsync foundation.stream.sub=integrationApiPostAssetsR1Assets,integrationApiPostWorkOrdersR1WorkOrders,integrationApiNotifyAsync
Configuration
Prerequisites
-
AWS SNS and SQS configuration (via Foundation stream properties)
-
Notify Async Stream configuration (required for callbacks)
-
Callback endpoint URL (optional - callback is only enabled if the URL is configured)
-
Authentication credentials for the callback endpoint (optional, depends on auth type)
Step 1: Configure Foundation Stream Properties
For each endpoint you want to enable asynchronously, you must manually configure the Foundation stream properties for SNS publishing and SQS consumption.
Example: Async Processing for POST /integration/assets/r1/assets
The property key follows the pattern: integrationApi{HttpMethod}{CamelCasePath}
For this endpoint, the key is: integrationApiPostAssetsR1Assets
Add the following properties to your setup.properties:
# Enable endpoint
integrationlayer.async.processing.integrationApiPostAssetsR1Assets.enabled=true
# Publisher configuration (SNS)
foundation.stream.pub=snsIntegrationApiPostAssetsR1Assets
foundation.stream.pub.snsIntegrationApiPostAssetsR1Assets.spout=*.spout.PostIntegrationAssetsR1AssetsAsyncProcessingRequestMessage
foundation.stream.pub.snsIntegrationApiPostAssetsR1Assets.target=integrationApiPostAssetsR1AssetsTarget
# SNS Target
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.type=SNS
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.topic=IntegrationApi-IntegrationApiPostAssetsR1Assets
# Subscriber configuration (SQS)
foundation.stream.sub=integrationApiPostAssetsR1Assets
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin=*.spin.PostIntegrationAssetsR1AssetsAsyncProcessingEventRequestMessage
foundation.stream.sub.integrationApiPostAssetsR1Assets.source=integrationApiPostAssetsR1AssetsSub
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin.agent=integrationApiPostAssetsR1AssetsAgent
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.type=SQS
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.topic=IntegrationApi-IntegrationApiPostAssetsR1Assets
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.logging=true
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.emergencyTopic=IntegrationApi-IntegrationApiPostAssetsR1Assets-DLQ
Step 2: Configure Notify Async Stream
If you want to receive callbacks when async processing completes, you must configure the Notify Async Stream. See the Notify Async Stream Configuration section above.
Step 3: Configure Callback (Optional)
If you want to receive callbacks when async processing completes, configure the callback settings:
# Global callback endpoint (optional)
integrationlayer.async.processing.global.callback.endpoint=${env:ASYNC_PROCESSING_CALLBACK_ENDPOINT}
# Global authentication configuration (optional)
# Supported auth types: "none", "basic", "bearer"
# Default: "none" (if not specified)
integrationlayer.async.processing.global.auth.type=${env:ASYNC_PROCESSING_CALLBACK_AUTH_TYPE}
# Required only for "basic" and "bearer" auth types
integrationlayer.async.processing.global.auth.user=${env:ASYNC_PROCESSING_CALLBACK_AUTH_USER}
integrationlayer.async.processing.global.auth.password=${env:ASYNC_PROCESSING_CALLBACK_AUTH_PASSWORD}
# Required only for "bearer" auth type (OAuth2 token endpoint)
integrationlayer.async.processing.global.auth.url=${env:ASYNC_PROCESSING_CALLBACK_AUTH_URL}
You can also override callback settings per endpoint:
# Override callback endpoint for specific endpoint
integrationlayer.async.processing.integrationApiPostAssetsR1Assets.callback.endpoint=${env:CUSTOM_CALLBACK_ENDPOINT}
integrationlayer.async.processing.integrationApiPostAssetsR1Assets.auth.type=basic
integrationlayer.async.processing.integrationApiPostAssetsR1Assets.auth.user=custom_user
integrationlayer.async.processing.integrationApiPostAssetsR1Assets.auth.password=custom_password
Authentication Types
The callback mechanism supports three authentication types:
|
Auth Type |
Description |
Required Properties |
|---|---|---|
|
|
No authentication (default if not specified) |
None |
|
|
HTTP Basic Authentication |
|
|
|
OAuth2 Bearer Token Authentication |
|
Important Notes:
-
If
auth.typeis not specified, it defaults tonone -
The callback is only executed if
callback.endpointis configured -
For
bearerauth, the system will automatically retrieve an OAuth2 token fromauth.urlusing the provided credentials
Step 4: Set Environment Variables
Configure the following environment variables:
# AWS Endpoints (REQUIRED)
SNS_ENDPOINT=arn:aws:sns:eu-west-1:0000012344556
SQS_ENDPOINT=https://sqs.eu-west-1.amazonaws.com
# Callback Configuration (optional - only if you want callbacks)
ASYNC_PROCESSING_CALLBACK_ENDPOINT=https://your-app.com/callback
# Authentication Configuration (optional - depends on auth type)
ASYNC_PROCESSING_CALLBACK_AUTH_TYPE=basic # Options: none, basic, bearer
ASYNC_PROCESSING_CALLBACK_AUTH_USER=username
ASYNC_PROCESSING_CALLBACK_AUTH_PASSWORD=password
# Only for bearer auth type
ASYNC_PROCESSING_CALLBACK_AUTH_URL=https://auth-server.com/oauth/token
Property Key Naming Convention
The property key is generated based on:
-
HTTP method (Post, Get, Put, Patch, Delete)
-
Controller path
-
Method path
Pattern: integrationApi + {HttpMethod} + {CamelCasePath}
Examples:
-
POST /integration/assets/r1/assets→integrationApiPostAssetsR1Assets -
POST /integration/work-orders/r1/work-orders→integrationApiPostWorkOrdersR1WorkOrders -
PATCH /integration/work-orders/r1/work-orders→integrationApiPatchWorkOrdersR1WorkOrders -
POST /integration/assets/r1/accounts→integrationApiPostAssetsR1Accounts -
POST /integration/workforce/r1/work-shift-exceptions→integrationApiPostWorkforceR1WorkShiftExceptions
Complete Configuration Example
Here's a complete example for enabling async processing on two endpoints with callback support:
setup.properties:
# ============================================
# Notify Async Stream (REQUIRED for callbacks)
# ============================================
# Publisher configuration (SNS)
foundation.stream.pub.snsIntegrationApiNotifyAsync.spout=*.spout.AsyncProcessingNotifyMessage
foundation.stream.pub.snsIntegrationApiNotifyAsync.target=integrationApiNotifyAsyncTarget
# SNS Target
foundation.stream.target.integrationApiNotifyAsyncTarget.type=SNS
foundation.stream.target.integrationApiNotifyAsyncTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiNotifyAsyncTarget.topic=IntegrationApi-NotifyAsync
# Subscriber configuration (SQS)
foundation.stream.sub.integrationApiNotifyAsync.spin=*.spin.AsyncProcessingEventNotifyMessage
foundation.stream.sub.integrationApiNotifyAsync.source=integrationApiNotifyAsyncSub
foundation.stream.sub.integrationApiNotifyAsync.spin.agent=integrationApiNotifyAsyncAgent
foundation.stream.sub.integrationApiNotifyAsync.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiNotifyAsyncSub.type=SQS
foundation.stream.source.integrationApiNotifyAsyncSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiNotifyAsyncSub.topic=IntegrationApi-NotifyAsync
foundation.stream.source.integrationApiNotifyAsyncSub.logging=true
foundation.stream.source.integrationApiNotifyAsyncSub.emergencyTopic=IntegrationApi-NotifyAsync-DLQ
# ============================================
# Async Processing for POST /integration/assets/r1/assets
# ============================================
# Enable endpoint
integrationlayer.async.processing.integrationApiPostAssetsR1Assets.enabled=true
# Publisher configuration (SNS)
foundation.stream.pub=snsIntegrationApiPostAssetsR1Assets,snsIntegrationApiPostWorkOrdersR1WorkOrders,snsIntegrationApiNotifyAsync
foundation.stream.pub.snsIntegrationApiPostAssetsR1Assets.spout=*.spout.PostIntegrationAssetsR1AssetsAsyncProcessingRequestMessage
foundation.stream.pub.snsIntegrationApiPostAssetsR1Assets.target=integrationApiPostAssetsR1AssetsTarget
# SNS Target
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.type=SNS
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiPostAssetsR1AssetsTarget.topic=IntegrationApi-IntegrationApiPostAssetsR1Assets
# Subscriber configuration (SQS)
foundation.stream.sub=integrationApiPostAssetsR1Assets,integrationApiPostWorkOrdersR1WorkOrders,integrationApiNotifyAsync
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin=*.spin.PostIntegrationAssetsR1AssetsAsyncProcessingEventRequestMessage
foundation.stream.sub.integrationApiPostAssetsR1Assets.source=integrationApiPostAssetsR1AssetsSub
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin.agent=integrationApiPostAssetsR1AssetsAgent
foundation.stream.sub.integrationApiPostAssetsR1Assets.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.type=SQS
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.topic=IntegrationApi-IntegrationApiPostAssetsR1Assets
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.logging=true
foundation.stream.source.integrationApiPostAssetsR1AssetsSub.emergencyTopic=IntegrationApi-IntegrationApiPostAssetsR1Assets-DLQ
# ============================================
# Async Processing for POST /integration/work-orders/r1/work-orders
# ============================================
# Enable endpoint
integrationlayer.async.processing.integrationApiPostWorkOrdersR1WorkOrders.enabled=true
# Publisher configuration (SNS)
foundation.stream.pub.snsIntegrationApiPostWorkOrdersR1WorkOrders.spout=*.spout.PostIntegrationWorkOrdersR1WorkOrdersAsyncProcessingRequestMessage
foundation.stream.pub.snsIntegrationApiPostWorkOrdersR1WorkOrders.target=integrationApiPostWorkOrdersR1WorkOrdersTarget
# SNS Target
foundation.stream.target.integrationApiPostWorkOrdersR1WorkOrdersTarget.type=SNS
foundation.stream.target.integrationApiPostWorkOrdersR1WorkOrdersTarget.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.integrationApiPostWorkOrdersR1WorkOrdersTarget.topic=IntegrationApi-IntegrationApiPostWorkOrdersR1WorkOrders
# Subscriber configuration (SQS)
foundation.stream.sub.integrationApiPostWorkOrdersR1WorkOrders.spin=*.spin.PostIntegrationWorkOrdersR1WorkOrdersAsyncProcessingEventRequestMessage
foundation.stream.sub.integrationApiPostWorkOrdersR1WorkOrders.source=integrationApiPostWorkOrdersR1WorkOrdersSub
foundation.stream.sub.integrationApiPostWorkOrdersR1WorkOrders.spin.agent=integrationApiPostWorkOrdersR1WorkOrdersAgent
foundation.stream.sub.integrationApiPostWorkOrdersR1WorkOrders.spin.tenant=admin
# SQS Source
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.type=SQS
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.topic=IntegrationApi-IntegrationApiPostWorkOrdersR1WorkOrders
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.logging=true
foundation.stream.source.integrationApiPostWorkOrdersR1WorkOrdersSub.emergencyTopic=IntegrationApi-IntegrationApiPostWorkOrdersR1WorkOrders-DLQ
# ============================================
# Global Callback Configuration (Optional)
# ============================================
integrationlayer.async.processing.global.callback.endpoint=${env:ASYNC_PROCESSING_CALLBACK_ENDPOINT}
integrationlayer.async.processing.global.auth.type=basic
integrationlayer.async.processing.global.auth.user=${env:ASYNC_PROCESSING_CALLBACK_AUTH_USER}
integrationlayer.async.processing.global.auth.password=${env:ASYNC_PROCESSING_CALLBACK_AUTH_PASSWORD}
Note: When enabling multiple endpoints, the foundation.stream.pub and foundation.stream.sub properties should list all enabled endpoints separated by commas, including the Notify Async Stream.
How It Works
-
Request Reception: When a request arrives at an async-enabled endpoint, it's immediately queued
-
SNS Publishing: The request is published to an SNS topic (configured via
foundation.stream.pub.*) -
SQS Processing: The message is consumed from an SQS queue (configured via
foundation.stream.sub.*) -
Async Execution: The service method is executed asynchronously
-
Notify Message: A notification message is published to the Notify Async Stream
-
Callback (if configured): The Notify Async Stream processor calls the configured callback endpoint with the processing result
Callback Behavior
-
Callback is only executed if
callback.endpointis configured -
Notify Async Stream must be configured for callbacks to work
-
If no callback endpoint is set, async processing still works but no notification is sent
-
The callback includes the processing result and the original request trace information
-
Authentication is applied based on the
auth.typesetting
AWS Resources Naming Convention
The SNS topics, SQS queues, and DLQs follow this naming pattern:
-
SNS Topic:
IntegrationApi-{CapitalizedApiName} -
SQS Queue:
IntegrationApi-{CapitalizedApiName} -
DLQ:
IntegrationApi-{CapitalizedApiName}-DLQ
Example: For integrationApiPostAssetsR1Assets:
-
SNS Topic:
IntegrationApi-IntegrationApiPostAssetsR1Assets -
SQS Queue:
IntegrationApi-IntegrationApiPostAssetsR1Assets -
DLQ:
IntegrationApi-IntegrationApiPostAssetsR1Assets-DLQ
For Notify Async Stream:
-
SNS Topic:
IntegrationApi-NotifyAsync -
SQS Queue:
IntegrationApi-NotifyAsync -
DLQ:
IntegrationApi-NotifyAsync-DLQ
Troubleshooting
Async Processing Not Working
-
Check all Foundation stream properties are configured:
-
Verify
foundation.stream.pubincludes your endpoint (e.g.,foundation.stream.pub=snsIntegrationApiPostAssetsR1Assets) -
Verify
foundation.stream.pub.*properties for SNS publishing -
Verify
foundation.stream.target.*properties for SNS target -
Verify
foundation.stream.subincludes your endpoint (e.g.,foundation.stream.sub=integrationApiPostAssetsR1Assets) -
Verify
foundation.stream.sub.*properties for SQS subscription -
Verify
foundation.stream.source.*properties for SQS source
-
-
Check endpoint enable flag: Verify the specific endpoint is enabled with the correct property key
integrationlayer.async.processing.integrationApiPostAssetsR1Assets.enabled=true -
Check AWS endpoints: Ensure SNS and SQS endpoints are configured and accessible
BashSNS_ENDPOINT=arn:aws:sns:eu-west-1:0000012344556 SQS_ENDPOINT=https://sqs.eu-west-1.amazonaws.com -
Check AWS resources exist: Verify that the SNS topics and SQS queues exist in AWS with the correct names
-
Check logs: Look for errors related to SNS/SQS connectivity or message processing
Callback Not Working
-
Check Notify Async Stream is configured:
-
Verify
foundation.stream.pubincludessnsIntegrationApiNotifyAsync -
Verify
foundation.stream.subincludesintegrationApiNotifyAsync -
Verify all Notify Async Stream properties are configured (see Notify Async Stream Configuration)
-
-
Check callback endpoint is configured:
integrationlayer.async.processing.global.callback.endpoint=${env:ASYNC_PROCESSING_CALLBACK_ENDPOINT}Callback is only executed if this property is set
-
Check authentication configuration:
-
For
auth.type=basic: Ensureauth.userandauth.passwordare set -
For
auth.type=bearer: Ensureauth.user,auth.password, andauth.urlare set -
If
auth.typeis not set, it defaults tonone(no authentication)
-
-
Verify callback endpoint is accessible: Test the callback URL manually to ensure it's reachable
-
Check logs for callback errors: Look for "Error during callback to external system" messages
-
Check Notify Async Stream AWS resources exist: Verify that
IntegrationApi-NotifyAsyncSNS topic and SQS queue exist
Finding the Correct Property Key
The property key follows the pattern: integrationApi{HttpMethod}{CamelCasePath}
Steps to determine the key:
-
Identify the HTTP method (POST, GET, PUT, PATCH, DELETE)
-
Identify the full path (e.g.,
/integration/assets/r1/assets) -
Convert to camelCase, capitalizing the first letter of each segment except "integration"
-
Prepend with
integrationApi
Examples:
-
POST /integration/assets/r1/assets→integrationApiPostAssetsR1Assets -
POST /integration/work-orders/r1/work-orders→integrationApiPostWorkOrdersR1WorkOrders -
PATCH /integration/work-orders/r1/work-orders→integrationApiPatchWorkOrdersR1WorkOrders -
POST /integration/workforce/r1/work-shift-exceptions→integrationApiPostWorkforceR1WorkShiftExceptions
Common Mistakes
-
Missing Notify Async Stream configuration: Callbacks won't work without the Notify Async Stream
-
Missing
foundation.stream.puborfoundation.stream.subproperties: These must list all enabled endpoints includingsnsIntegrationApiNotifyAsyncandintegrationApiNotifyAsync -
Missing Foundation stream properties: All
foundation.stream.*properties must be configured manually -
Expecting callback without configuring endpoint: Callback is only sent if
callback.endpointis configured -
Wrong authentication configuration: Make sure to provide all required properties for your chosen auth type
-
Forgetting to enable specific endpoints: Even with all stream configuration, each endpoint must be individually enabled with
.enabled=true -
Wrong property key format: Ensure you follow the exact naming convention (case-sensitive)
-
Incorrect AWS resource names: SNS topics and SQS queues must match the naming convention exactly
Configuration Template
Use this template to configure async processing for any endpoint:
# ============================================
# Async Processing for {HTTP_METHOD} {ENDPOINT_PATH}
# Property Key: {PROPERTY_KEY}
# ============================================
# Enable endpoint
integrationlayer.async.processing.{PROPERTY_KEY}.enabled=true
# Publisher configuration (SNS)
# Add {PROPERTY_KEY_SNS} to the comma-separated list
foundation.stream.pub=sns{PROPERTY_KEY}
foundation.stream.pub.sns{PROPERTY_KEY}.spout=*.spout.{MessageClassName}
foundation.stream.pub.sns{PROPERTY_KEY}.target={PROPERTY_KEY}Target
# SNS Target
foundation.stream.target.{PROPERTY_KEY}Target.type=SNS
foundation.stream.target.{PROPERTY_KEY}Target.endpoint=${env:SNS_ENDPOINT}
foundation.stream.target.{PROPERTY_KEY}Target.topic=IntegrationApi-{CAPITALIZED_PROPERTY_KEY}
# Subscriber configuration (SQS)
# Add {PROPERTY_KEY} to the comma-separated list
foundation.stream.sub={PROPERTY_KEY}
foundation.stream.sub.{PROPERTY_KEY}.spin=*.spin.{MessageClassName}
foundation.stream.sub.{PROPERTY_KEY}.source={PROPERTY_KEY}Sub
foundation.stream.sub.{PROPERTY_KEY}.spin.agent={PROPERTY_KEY}Agent
foundation.stream.sub.{PROPERTY_KEY}.spin.tenant=admin
# SQS Source
foundation.stream.source.{PROPERTY_KEY}Sub.type=SQS
foundation.stream.source.{PROPERTY_KEY}Sub.endpoint=${env:SQS_ENDPOINT}
foundation.stream.source.{PROPERTY_KEY}Sub.topic=IntegrationApi-{CAPITALIZED_PROPERTY_KEY}
foundation.stream.source.{PROPERTY_KEY}Sub.logging=true
foundation.stream.source.{PROPERTY_KEY}Sub.emergencyTopic=IntegrationApi-{CAPITALIZED_PROPERTY_KEY}-DLQ
Replace:
-
{HTTP_METHOD}- HTTP method (POST, GET, PUT, etc.) -
{ENDPOINT_PATH}- Full endpoint path -
{PROPERTY_KEY}- Property key in camelCase (e.g.,integrationApiPostAssetsR1Assets) -
{CAPITALIZED_PROPERTY_KEY}- Property key with capital first letter (e.g.,IntegrationApiPostAssetsR1Assets) -
{MessageClassName}- Message class name (e.g.,PostIntegrationAssetsR1AssetsAsyncProcessingRequestMessage)
Quick Reference Checklist
- Determine the property key for your endpoint using the naming convention
- Add the endpoint to
foundation.stream.pub(withsnsprefix) - Add the endpoint to
foundation.stream.sub - Configure all Foundation stream properties (
foundation.stream.pub.*,foundation.stream.target.*,foundation.stream.sub.*,foundation.stream.source.*) - Enable the endpoint with
.enabled=true - Configure Notify Async Stream (required for callbacks)
- Add
snsIntegrationApiNotifyAsynctofoundation.stream.pub - Add
integrationApiNotifyAsynctofoundation.stream.sub - Configure callback endpoint (optional)
- Configure authentication (optional)
- Set environment variables (SNS_ENDPOINT, SQS_ENDPOINT, callback settings)
- Create AWS resources (SNS topics, SQS queues, DLQs) with correct names
- Create Notify Async Stream AWS resources (
IntegrationApi-NotifyAsynctopic, queue, and DLQ) - Deploy and test
Required vs Optional Configuration
|
Configuration |
Required? |
Notes |
|---|---|---|
|
|
Required |
Comma-separated list of all enabled publishers (with |
|
|
Required |
Comma-separated list of all enabled subscribers |
|
Foundation stream properties |
Required |
All |
|
|
Required |
Each endpoint must be explicitly enabled |
|
SNS/SQS endpoints |
Required |
Must be set via environment variables |
|
AWS resources (topics/queues) |
Required |
Must exist in AWS with correct names |
|
Notify Async Stream |
Required for callbacks |
Must be configured if you want callback notifications |
|
|
Optional |
Callback only works if this is set |
|
|
Optional |
Defaults to |
|
|
Conditional |
Required for |
|
|
Conditional |
Required for |
|
|
Conditional |
Required only for |
For more information, contact the Integration API team.