Overview
When Azure API Management (APIM) acts as the gateway for your integration flows, you can use APIM policies to forward tracking events to Business Activity Monitoring (BAM) without modifying the underlying APIs. The send-request policy in APIM sends an HTTP POST to the BAM endpoint at each stage, recording transaction progress directly from the gateway layer.
You configure APIM with the Turbo360 OpenAPI spec or a custom API definition, then implement a policy that injects the BAM API key and tracking headers into requests before forwarding them to BAM.
Business value
Instrumenting BAM through APIM policies applies tracking at the gateway layer, independent of the individual services behind it. This reduces the need to modify each back-end service and provides a single point where tracking headers and business context are injected. It is particularly useful for organisations that already route all Azure integrations through APIM.
Prerequisites
- A BAM environment deployed in your Azure subscription.
- A business process and transaction configured in the Turbo360 portal.
- Your BAM Host Endpoint URL, available from Configuration > Connection details in the Turbo360 portal.
- An Azure API Management instance with permission to edit policies.
Required permissions
| Permission | Role |
|---|---|
| Read BAM configuration | BAM Reader or higher |
| Edit APIM policies | APIM Contributor on the APIM instance |
How it works
APIM policies are XML documents attached to an API operation. They run inside the APIM gateway and can modify both inbound requests and outbound responses. The send-request policy makes an independent HTTP call from the gateway — in this case, to the BAM tracking endpoint — without disrupting the main request flow.
You configure the policy with the BAM endpoint URL and pass tracking headers (BAM-BusinessProcess, BAM-Transaction, BAM-Stage, BAM-StageStatus, and others) to record each stage. The ignoreerror="true" attribute ensures that a BAM tracking failure does not interrupt the primary integration flow.
To learn more about policies in API Management, see the Azure API Management policies documentation.
:::
Steps
The following steps show how to add a BAM tracking policy to an APIM operation. Open the APIM policy editor in the Azure portal before starting.
Add a send-request policy to track a stage
Adding this policy records a BAM stage checkpoint every time the APIM operation is called.
- In the Azure portal, navigate to your APIM instance.
- Select the API and operation you want to instrument.
- Open the Policy editor for the operation (inbound or outbound, depending on where you want to record the stage).
- Insert the following XML policy, replacing placeholder values with your BAM host endpoint, business process name, transaction name, stage name, and status:
<send-request mode="new" response-variable-name="reponse" timeout="60" ignoreerror="true">
<set-url> BAM Host Endpoint </set-url>
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-header name="BAM-BusinessProcess" exists-action="append">
<value> Business Process Name </value>
</set-header>
<set-header name="BAM-Transaction" exists-action="append">
<value> Transaction Name </value>
</set-header>
<set-header name="BAM-Stage" exists-action="append">
<value> Stage Name </value>
</set-header>
<set-header name="BAM-StageStatus" exists-action="append">
<value> Success/Failure/InProgress </value>
</set-header>
<set-header name="BAM-ArchiveMessage" exists-action="append">
<value> true/false </value>
</set-header>
<set-header name="BAM-IsTransactionComplete" exists-action="append"> <value> true/false </value>
</set-header>
<set-body>@{
return new JObject( new JProperty("MessageBody",context.Variables["YOUR_Data"]),
new JProperty("MessageHeader", new JObject( new JProperty("Content-Type", "application/json") ).ToString()) ).ToString();
}</set-body>
</send-request>
- Save the policy and test the operation to verify that BAM records the stage.
Example scenario
A payment processing flow uses APIM as the front-end gateway. Three operations — ValidatePayment, ProcessPayment, and ConfirmPayment — each have a send-request policy that records their corresponding BAM stage. The policy on ConfirmPayment sets BAM-IsTransactionComplete to true to close the transaction instance.
Limitations
- The
send-requestpolicy runs asynchronously whenignoreerror="true"is set. BAM tracking events may appear slightly delayed relative to the main transaction flow. - The request body syntax in the
<set-body>block must match the BAM API request body schema. See the 101 - Sending data to the BAM API article for the correct body structure.
Troubleshooting
-
BAM stage is not recorded even though the APIM operation succeeds
Cause:ignoreerror="true"masks the error and thesend-requestcall to BAM is failing silently.
Fix: Temporarily setignoreerror="false"and inspect the policy output. Check that the BAM host endpoint URL is correct and the API key header is present. -
BAM policy causes the APIM operation to time out
Cause: Thetimeoutvalue onsend-requestis too low for the BAM endpoint response time.
Fix: Increase thetimeoutattribute value (for example, from60to120seconds) and confirm there are no network restrictions between APIM and the BAM Function App. -
Business process or transaction not found error from BAM
Cause: TheBAM-BusinessProcessorBAM-Transactionheader values do not match the names configured in the Turbo360 portal.
Fix: Verify the exact names in the Turbo360 portal under business process configuration and update the policy values to match. -
Transaction instance remains open after the final stage
Cause:BAM-IsTransactionCompleteis not set totrueon the final operation's policy.
Fix: AddBAM-IsTransactionComplete: trueto thesend-requestpolicy on the operation that completes the transaction. -
JObject set-body expression fails with a runtime error
Cause: Thecontext.Variables["YOUR_Data"]reference does not resolve because the variable has not been set in a prior policy step.
Fix: Ensure the variable is populated by a precedingset-variablepolicy or replace it with the actual context expression that holds the message body data.