Context: I am auto-generating a client that needs to set wrap-up codes after interaction closure. Using the JS SDK, I call interactionsApi.putInteractionWrapUp(id, payload) with codeId and durationMs. The spec implies this is valid, but I get a 400 Bad Request. codeId is valid in the division.
Question: Does anyone know if the interaction must be in a specific state before this endpoint accepts the payload? My logs show state: 'closed'.
The root of the issue is likely a state mismatch or payload structure rigidity in the JS SDK wrapper, which often hides the actual HTTP method requirements or expects nested objects where flat keys are needed. The endpoint PUT /api/v2/interactions/{id}/wrap-up is strict. You cannot set a wrap-up on an interaction that is still active or queued. It must be closed or completed.
First, verify the interaction state via GET /api/v2/interactions/{id}. If it is not closed, the 400 is expected. Second, the JS SDK’s putInteractionWrapUp might be serializing the codeId incorrectly if you are passing a string instead of an object reference, or vice versa, depending on the SDK version. I recommend bypassing the SDK wrapper temporarily to inspect the raw request.
Use this curl pattern to isolate the variable. Note the Content-Type and the exact JSON structure. The codeId must match the UUID of a Wrap Up Code in your specific division.
If this returns a 204 No Content, your SDK payload construction is flawed. Check if the JS SDK requires the codeId to be passed as part of a wrapUpCode object rather than a top-level key. In my migration tests, I found that putInteractionWrapUp sometimes fails if the durationMs is missing or zero, even if optional in the OpenAPI spec. Explicitly set it. Also, ensure your OAuth token includes the interaction:view and interaction:write scopes. If the curl works, refactor your JS code to mirror the raw JSON structure exactly, removing any SDK-specific transformation layers that might be adding null fields or incorrect nesting.
The Java SDK documentation states “wrap-up codes must be applied to closed interactions only,” which aligns with the state validation logic, but the error often stems from how the WrapUp object is instantiated rather than the interaction state itself. The JS SDK might be masking the strict JSON structure requirements that the REST API enforces. In my Spring Boot services, I bypass the high-level SDK wrappers for this specific endpoint to ensure the payload matches the exact schema expected by the Genesys Cloud platform.
Here is the approach I use in Java to avoid the 400 error:
Verify Interaction State First: Do not assume the interaction is closed. Fetch the interaction details via GET /api/v2/interactions/{id} and check the state field. It must be closed. If it is active, the API will reject the wrap-up request immediately.
Construct the Payload Manually: The SDK’s WrapUp builder sometimes includes null fields that trigger strict validation errors. Build the JSON payload directly to ensure only codeId and durationMs are present if required.
Use Raw HTTP Client for Precision: Instead of interactionsApi.putInteractionWrapUp, use the ApiClient directly to control the request headers and body precisely. This helps in debugging if the issue is related to content-type or scope permissions.
// Example using Spring's RestTemplate or similar HTTP client
String url = "https://api.mypurecloud.com/api/v2/interactions/" + interactionId + "/wrap-up";
Map<String, Object> payload = new HashMap<>();
payload.put("codeId", validWrapUpCodeId); // Ensure this ID exists in the division
payload.put("durationMs", 120000); // Duration in milliseconds
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + accessToken);
HttpEntity<Map<String, Object>> request = new HttpEntity<>(payload, headers);
ResponseEntity<Void> response = restTemplate.exchange(url, HttpMethod.PUT, request, Void.class);
This method ensures that the payload is strictly compliant with the API spec, avoiding any SDK-induced serialization issues. Check your token scopes as well; interaction:write is required.
The documentation actually says wrap-ups require a specific state transition before the API accepts the payload. My Django analytics pipeline uses Celery to poll for closed status before hitting /api/v2/interactions/{id}/wrap-up. Ensure your codeId matches the division context. Sending requests while the interaction is still active triggers the 400. Wait for the state change.
If I remember correctly… the 400 error usually stems from timestamp precision mismatches when the JS SDK serializes the durationMs field, or attempting to wrap up an interaction that hasn’t fully settled into closed state. I verify these payloads in my Jupyter notebooks using PureCloudPlatformClientV2 and pandas to ensure schema compliance before hitting the API.
Cause: The JS SDK wrapper often omits required fields like wrapUpCode object nesting or sends millisecond timestamps that exceed API limits. Additionally, race conditions occur if the interaction state is technically closed but not yet finalized in the backend.
Solution: Construct the payload manually using requests or the Python SDK to enforce strict JSON structure. Validate the interaction state via GET /api/v2/interactions/{id} first.