Predictive Campaign halting with WEM constraint error during peak hours

Running the Q4_EU_Push campaign here in Berlin :germany: and it stops dead around 14:00 CET every Tuesday. Campaign status flips to PAUSED instantly. Console is empty. API monitor catches POST /api/v2/outbound/campaigns returning 400. Error body says WEM_AGENT_AVAILABILITY_THRESHOLD_NOT_MET. :thinking: Very interesting puzzle! Great learning opportunity!

Pro tip! WEM skills must match campaign skill exactly :rocket: Verified this three times. Skill Outbound_Sales_EU is attached to campaign and WEM schedule. :camera_with_flash: screenshot attached!

Checked Architect flow. Flow Outbound_Engagement_v2 is active. No errors there. WEM schedule has 20 agents available. Threshold is set to 5. Should be fine. Logs are quiet. Campaign just sleeps. Behavior is confusing. :man_shrugging: Is the threshold calculation maybe using a different timezone offset? :globe_showing_europe_africa:

Tried disabling WEM constraint in campaign settings. Campaign runs wild immediately. Constraint is definitely the blocker. WEM constraint type is MINIMUM_AVAILABLE_AGENTS. Don’t see why calculation fails. :face_with_monocle: I check latest release notes and everything looks standard. Maybe I missing something small? I will bring this to our local GC user group! :raising_hands: Also, the official WEM constraint docs here might help us debug together. What do you think?

Using Python SDK v2.1.4 to poll status. It’s throwing same 400. :snake:

Region is EU_GEN. Version is latest release. :package:

CampaignId: 8f3a2b1c-9d4e-4f5a-b6c7-d8e9f0a1b2c3

The dialer is throttling because the WEM forecast dips below the configured wemAvailabilityThreshold during peak Tuesday volume. Resolve this by validating the baseline metrics first, then adjusting the threshold directly.

Step 1: Query the actual availability metrics via OData. Pull the agentAvailability dataset to confirm real-time capacity before modifying campaign settings. This ensures you are patching against verified data rather than a skewed forecast.

Step 2: Apply the threshold adjustment via the Campaigns API. Use a PATCH request to update the wemConfiguration object. This prevents the predictive engine from triggering a hard cap when the forecast naturally contracts.

curl -X PATCH "https://api.mypurecloud.com/api/v2/outbound/campaigns/{campaignId}" \
 -H "Authorization: Bearer $ACCESS_TOKEN" \
 -H "Content-Type: application/json" \
 -d '{"wemConfiguration": {"enabled": true, "availabilityThreshold": 0.75, "skillId": "your-skill-id"}}'

Step 3: Validate the change. Query the Reporting API v2 immediately after the patch completes. Cross-reference the forecastTimestamp fields to confirm the new availabilityThreshold is being applied to subsequent intervals.

Problem

The WEM forecast is dipping below the campaign limit during that Tuesday peak. Patching the threshold is the right call, but you should fetch the current config first to avoid wrecking a deliberate setting. You don’t want to overwrite a value that was tuned for a different constraint.

Code

Run this GET to see what wemAvailabilityThreshold is currently set to. Look for the wemConstraints object in the response. The wemConstraints payload usually hides inside the main campaign JSON. You might need to expand the view in Postman.

curl -X GET "https://api.mypurecloud.com/api/v2/outbound/campaigns/{campaignId}" \
 -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
 -H "Accept: application/json"

Error

Lowering that threshold blindly risks sending calls to agents who aren’t ready. You’ll see AHT spike because the dialer is forcing connections.

If you are triggering this adjustment from a Data Action flow, be careful. That 400 error on the campaign status change will break your span propagation. You’ll lose the distributed trace link between the availability drop and the pause event. Make sure your error handler captures the context before it dies. The trace ID needs to survive the 400 response so you can correlate the WEM forecast data with the campaign halt in Jaeger. When the campaign pauses, the Data Action might retry if you haven’t set the error handling correctly. This creates duplicate spans in your backend. Just remember to inject the baggage before the call fails.

Question

What’s your current approach for preserving OTel context across Data Action retries? I’m trying to standardize how we inject baggage and capture the trace ID on 400 responses to prevent duplicate spans in Jaeger while keeping the distributed trace intact.