I received an interesting request today – could we start receiving payload to existing Logic App as batch – meaning a JSON array of same objects as we already receive. This would in some use cases be much more efficient for the sender, but mostly we’d still get separate event messages.
There were a few gotchas:
- The id we receive in each object is essential to tracking the end-to-end workflow (split in multiple Logic Apps & Function processing).
- During transition, could we be able to process both methods – so there could come a single object OR an array.
Logic App has “SplitOn” feature in trigger configuration, which makes it easy to split an array input into multiple runs. It also supports separate client tracking id for each instance created from the array. I’m not digging into that part here, as there are already good blog posts on this subject (for example by Kent Weare and Srinivasa Mahendrakar).
NOTE! SplitOn works (logically) only with asynchronous calls that accept 202 response (request-only workflow) – you cannot use it for request-response scenarios as explained in the official documentation.
But the second part was something I wasn’t sure of – so time for some trial and error… first playing with Compose action and workflow language functions, and then trying them with SplitOn-expression.
So we have two separate test cases to test – array & single object – samples below:


Try 1 – Just split it

Testing with array case works nicely and both cases get their own correlation id, but with the single object we get a 400 / Bad Request error:{ "error": { "code": "InvalidTemplate", "message": "The template language expression evaluation failed: 'The execution of template trigger 'manual' failed: the result of the evaluation of 'splitOn' expression '@triggerBody()' is of type 'Object'. The result must be a valid array.'." } }
Try 2 – Convert to array
Next, let’s try to convert input to an array – my assumption was that this solves single item case but breaks the array case, because when I tried array() function in a Compose action, it inserted the original array inside the new one: [ [ {…}, {…} ] ]

Single object works as expected with a correct correlation id. BUT – for my surprise, the array case worked like a charm too!
I was expecting this to fail based on my trials inside the workflow and was preparing to test something like below as splitOn-expression:@if(startsWith(trim(string(triggerBody())), '['), triggerBody(), array(triggerBody()))
That actually works too, but naturally keeping it simple is always a good choice…
So it seems that with that one small expression we can actually support both requirements. Nice surprise!
