GET /v4/jobs/{jobId} for progress and GET /v4/jobs/{jobId}/items for per-recipient outcomes. Mirrors POST /contacts/bulk/async exactly./messages/{channel}/audience.type and basis sit on the envelope, as in the synchronous batch, and for the same reasons.expiresAt). Send Idempotency-Key to make retries safe: a replay returns the ORIGINAL job rather than enqueuing a second one.curl --location '/messages/sms/batch/async' \
--header 'Authorization: Bearer <token>' \
--header 'Idempotency-Key: 0f3e2b1a-7c4d-4e2a-9b11-2f6d8c1a5e30' \
--header 'Content-Type: application/json' \
--data '{
"type": "transactional",
"basis": "contract_performance",
"messages": [
{
"to": {
"contactId": "string",
"clientContactId": "string",
"phoneNumber": "string"
},
"from": "string",
"templateId": 0,
"content": "string",
"language": "string",
"variables": {},
"tags": [
"string"
],
"metadata": {},
"sendAt": "string",
"createContact": true,
"retainBody": true,
"event": "string",
"permId": "string"
}
]
}'{
"jobId": "string",
"type": "string",
"status": "string",
"progress": {
"total": 0,
"processed": 0,
"succeeded": 0,
"failed": 0
},
"createdAt": "string",
"startedAt": "string",
"finishedAt": "string",
"expiresAt": "string",
"error": "string",
"links": {
"self": "string",
"items": "string"
}
}