PATCH /api/v2/conversations/{id}/participants not updating attributes via .NET SDK

Trying to update participant attributes mid-conversation using the .NET SDK. The docs say you can send a PATCH to /api/v2/conversations/{id}/participants.

Here’s the code I’m using:

var patch = new PatchDocument();
patch.Add(new PatchOperation 
{ 
 Op = "replace", 
 Path = "/attributes/custom", 
 Value = new Dictionary<string, object> { { "orderId", "12345" } } 
});

await _conversationsApi.PatchConversationParticipantAsync(conversationId, participantId, patch);

It doesn’t throw an exception. Returns 200 OK. But the attributes don’t show up in the conversation log or via the GET endpoint.

Checked the raw HTTP request with a proxy. The payload looks like this:

[
 {
 "op": "replace",
 "path": "/attributes/custom",
 "value": {
 "orderId": "12345"
 }
 }
]

If I use Postman with the same token and payload, it works fine. The SDK seems to be serializing something wrong or hitting a different endpoint version. Running SDK v8.14. Any ideas?

Might be worth checking how you’re serializing that value object. The .NET SDK is pretty strict about the Value property expecting a concrete type or a proper JSON string depending on the version, and passing a raw dictionary can sometimes trip up the serializer if it doesn’t know how to handle the generic object.

Try wrapping it in a JObject from Newtonsoft.Json or explicitly casting it. Here is a safer pattern:

var attributes = new Dictionary<string, object> { { "orderId", "12345" } };
var patch = new PatchDocument();
patch.Add(new PatchOperation 
{ 
 Op = "replace", 
 Path = "/attributes/custom", 
 Value = JObject.FromObject(attributes) // Ensures proper JSON serialization
});

await _conversationsApi.PatchConversationParticipantsAsync(
 conversationId, 
 new[] { participantId }, 
 patch
);

Also, double-check that you’re actually passing the participantId array correctly. The endpoint requires specific participants to target, not just the conversation ID. If that array is null or empty, the request might silently fail or return a generic 400. I’ve seen this bite me when migrating from curl tests to SDK code.

Spot on. The serializer is definitely the culprit here. In the JS SDK, we usually just pass a plain object, but .NET gets pedantic about generic object types inside PatchOperation. If you don’t hint the type, it might serialize as null or drop the key entirely.

Using JObject is the safe bet, but you can also just pass a JSON string if you’re feeling lazy. Here is the pattern I use in my Node services, adapted for .NET:

var value = new Dictionary<string, object> 
{ 
 ["orderId"] = "12345" 
};

// Force serialization to ensure the structure is preserved
var jsonValue = JsonConvert.SerializeObject(value);

patch.Add(new PatchOperation 
{ 
 Op = "replace", 
 Path = "/attributes/custom", 
 Value = jsonValue // or use JObject.Parse(jsonValue) if the SDK demands an object
});

await _conversationsApi.PatchConversationParticipantAsync(conversationId, patch);

Just make sure you have the right scopes. conversation:write is mandatory here. If the API returns 204 but the data isn’t there, check the response headers for retry-after or rate limiting. Genesys Cloud throttles participant updates pretty hard if you fire them in a tight loop.