POST /api/v2/flows/executions returns 400 with 'Invalid input' for simple flow

Stuck on triggering an Architect flow from our Kotlin service. The goal is to kick off a simple IVR-style flow for a specific user context without going through the web messaging SDK. Using the POST /api/v2/flows/executions endpoint as described in the docs.

Here’s the request setup:

val flowId = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
val payload = mapOf(
 "context" to mapOf(
 "contactId" to "user-123",
 "channel" to "voice",
 "language" to "en-us"
 )
)

val response = httpClient.post("https://${orgHost}.mygenesiscustomer.net/api/v2/flows/executions") {
 header("Content-Type", "application/json")
 header("Authorization", "Bearer $token")
 body = json.encodeToString(payload)
}

The response is a 400 Bad Request with this body:

{
 "code": "badRequest",
 "message": "Invalid input. Cannot create flow execution.",
 "details": [
 {
 "code": "invalid",
 "message": "The request body is not valid."
 }
 ]
}

I’ve verified the token has flow:write scope. The flow itself works fine when triggered via a standard inbound call. Is there a specific field missing in the context object? The docs for v2 are pretty sparse on what’s strictly required for programmatic launches. Tried adding "type": "external" to the root but that just breaks the JSON schema validation entirely.