Node.js state machine for Cognigy webhook slot filling keeps dropping context on validation failures

@cognigy/sdk is what I’m leaning on here as I try to wire up a webhook endpoint that handles complex slot filling for a Cognigy flow. The whole idea is to track multi-turn extraction, validate each slot against an external pricing API, and push the updated context back to the dialog manager. I’ve got a basic Node.js Express server running the state machine, but the error recovery logic acts up when the external call returns a mismatch. It’s giving me major state drift vibes, like my CX-as-Code pipeline is losing track of the backup state.

async function processSlotUpdate(req, res) {
 const { currentSlots, lastInput, sessionId } = req.body;
 const missing = getMissingSlots(currentSlots);
 if (!missing) return res.json({ complete: true });

 const targetSlot = missing[0];
 const validation = await fetch(`https://api.internal/pricing?slot=${targetSlot}&val=${lastInput}`);
 
 if (!validation.ok) {
 const updatedContext = {
 ...currentSlots,
 validationError: `${targetSlot} is invalid`,
 promptOverride: 'Sorry, try again.'
 };
 
 await fetch(`https://api.cognigy.com/v1/dialog/context/${sessionId}`, {
 method: 'PUT',
 headers: { 'Authorization': `Bearer ${process.env.COGNIGY_TOKEN}`, 'Content-Type': 'application/json' },
 body: JSON.stringify(updatedContext)
 });
 
 return res.json({ complete: false, error: true });
 }
}

terraform-provider-cxascode usually handles merges gracefully, but the Cognigy REST API docs claim the context update should merge, and I’m hitting a wall. A 200 comes back while the dialog manager in Cognigy shows the validationError key missing after the next turn. I tried adding merge: true to the payload and switching to PATCH, yet the state machine still loses track of which slot it’s waiting for. The external API returns { valid: false, reason: 'out_of_stock' } which parses fine, so the issue probably sits in how the context payload gets serialized or how Cognigy handles the PUT request timing. It’s like the state backup isn’t syncing properly with the live dialog engine.

node-fetch is what I’m using under the hood, and walking through the logic step by step helps isolate where things break. First, the state machine extracts the input and maps it to the target slot. Second, the validation call runs and rejects the value. Third, the error handler constructs the new context object. Fourth, the PUT request fires to the Cognigy endpoint. The response comes back clean, but the next webhook trigger shows a wiped context. I’m logging the exact JSON sent to /v1/dialog/context/... and it looks fine on our end. Maybe the webhook response timing is out of sync with the dialog engine. Or perhaps a specific header is missing for partial context updates. The state machine transitions to WAITING_FOR_SLOT again, but the bot just repeats the initial greeting instead of the error prompt. It’s super frustrating when the CX-as-Code state drifts like this.

@cognigy/sdk is my go-to for reference, so any ideas on how to force the context merge without blowing away the slot history? Attached the raw response payload below if that helps.

{
 "slots": { "product_id": "SKU-8842", "quantity": "3" },
 "validationError": "quantity exceeds max order limit",
 "next_prompt": "Please enter a smaller number."
}

The webhook times out after 12 seconds if retry logic gets added, so the whole thing is stuck between dropping the error state and letting the bot hallucinate a valid response. I’m trying to keep the state backup consistent, but the timing is throwing everything off.