Skip to main content
flag
Mon - Fri   10:00 – 18:00

Voice Broadcast

API Documentation / Voice Broadcast / Voice Broadcast

Base URL for your account: https://cpaas.studio/api/v1

GET POST /api/v1/voice/broadcast

Sends a broadcast to a list of numbers from one of your account's DIDs. Requires a key scoped to voice.obd or all. This endpoint accepts a request; it does not bill or deliver synchronously.

Parameters

Param Type Required Notes
did string yes The phone number of one of your account's active DIDs enabled for Voice Broadcast (not a row id). Matched on the national number so a country code or leading zero on either side never causes a mismatch.
numbers array or string yes The recipient list — JSON array, repeated form/query key, or comma-separated string. Maximum 1,000 numbers per request.
audio_uid string one of audio_uid/audio_reference An approved, operator-delivered, enabled asset from your Audio Library. Takes precedence if both are supplied.
audio_reference string one of audio_uid/audio_reference Resolves to your most recently uploaded asset with this reference. The response always echoes the resolved audio_uid.
schedule_at string (date) no Omit to send immediately. ISO-8601 with a UTC offset is honoured exactly; a bare datetime is read in your account's configured timezone.
ring_time integer no One of 10,15,20,25,30,45,60. Defaults to your account's standard default (30).
retry_count integer no One of 0,1,2,3. Defaults to 0.
retry_interval integer no One of 15,30,60,120,180,300. Defaults to 60.
reference string, max 64 no Your own label for this broadcast, echoed back on the response. Not unique — does not prevent duplicate sends. Use the Idempotency-Key header for replay protection.
name string, max 255 no A label for the broadcast. Defaults to reference if supplied, otherwise a generated label.
caller_id do not supply Derived from did server-side. Supplying this field is rejected, not silently ignored.

Request example

curl -X POST "https://cpaas.studio/api/v1/voice/broadcast" \
  -H "X-API-KEY: cpk_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: 3f29b1c2-6e2a-4c1a-9e3b-7a2f0d5c9e11" \
  -d "did=9876500000" \
  -d "audio_uid=AUD7K2M9QX4WQ" \
  -d "numbers=9876543210,9876543211" \
  -d "reference=order-4471"
<?php
$ch = curl_init('https://cpaas.studio/api/v1/voice/broadcast');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'X-API-KEY: cpk_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
        'Idempotency-Key: 3f29b1c2-6e2a-4c1a-9e3b-7a2f0d5c9e11',
        'Content-Type: application/json',
    ],
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode([
        'did' => '9876500000',
        'audio_uid' => 'AUD7K2M9QX4WQ',
        'numbers' => ['9876543210', '9876543211'],
        'reference' => 'order-4471',
    ]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);

Success response (data)

{
    "id": "BCQVCUU6YTAA",
    "reference": "order-4471",
    "status": "queued",
    "total_numbers": 3,
    "summary": {
        "accepted": 2,
        "duplicate": 0,
        "invalid": 1
    },
    "credits_estimated": 2,
    "audio_uid": "AUD7K2M9QX4WQ",
    "scheduled_at": null,
    "numbers": [
        {
            "id": "BCQVCUU6YTAA-1",
            "mobile": "9876543210",
            "status": "pending",
            "attempts": 0,
            "duration_seconds": null,
            "billsec": null,
            "answered_at": null,
            "updated_at": "2026-08-15T12:00:00+00:00"
        },
        {
            "id": "BCQVCUU6YTAA-2",
            "mobile": "9876543211",
            "status": "pending",
            "attempts": 0,
            "duration_seconds": null,
            "billsec": null,
            "answered_at": null,
            "updated_at": "2026-08-15T12:00:00+00:00"
        },
        {
            "id": "BCQVCUU6YTAA-3",
            "mobile": "12345",
            "status": "invalid",
            "attempts": 0,
            "duration_seconds": null,
            "billsec": null,
            "answered_at": null,
            "updated_at": "2026-08-15T12:00:00+00:00"
        }
    ],
    "created_at": "2026-08-15T12:00:00+00:00"
}

Errors

Code Status When
AUDIO_NOT_FOUND 404 audio_uid/audio_reference doesn't match any of your broadcast-type assets.
AUDIO_NOT_APPROVED 422 The asset is not approved, or has not been delivered to the operator yet.
AUDIO_DISABLED 422 The asset has been turned off via Audio Enable/Disable.
BCAST_DID_INVALID 422 did doesn't match any of your account's active, voice.obd-enabled DIDs.
BCAST_NO_VALID_NUMBERS 422 Every submitted number was invalid or a duplicate.
BCAST_ALL_NUMBERS_INVALID 422 Every submitted number specifically failed format normalization.
BILLING_INSUFFICIENT_CREDITS 402 Your voice.obd wallet balance doesn't cover the estimated cost.
REQ_IDEMPOTENCY_KEY_CONFLICT 409 The Idempotency-Key header matches a prior request, but this request's body is different.
REQ_SCHEDULE_IN_PAST 422 schedule_at resolved to a time that had already passed by the time the request was processed.
REQ_SCHEDULE_INVALID_FORMAT 422 schedule_at isn't a value the date parser accepts — a more specific promotion of REQ_VALIDATION_FAILED for that one field.
REQ_NUMBERS_LIMIT_EXCEEDED 422 numbers exceeds the per-request cap (1,000 by default) — a more specific promotion of REQ_VALIDATION_FAILED for this one case.
REQ_AUDIO_SELECTION_INVALID 422 Neither or both of audio_uid/audio_reference were supplied where exactly one is required.
REQ_VALIDATION_FAILED 422 Missing/invalid did, caller_id supplied, or any other field-level rule failure not covered by a more specific code above.

Notes

  • accepted != billed. A 200/202 response means your broadcast was accepted, not billed and not delivered — actual credit debit happens per-chunk, asynchronously, after this request has already returned.
  • credits_estimated is exactly that — an estimate from the pre-flight balance check, never a charged amount.
  • numbers[] contains every number you submitted, exactly once each — accepted, duplicate, and invalid alike. There is no separate rejected_numbers/accepted_numbers array any more.
  • Array order is NOT guaranteed to match your original submission order across the accepted/duplicate/invalid boundary — match entries back to your input by mobile, not by array position.
  • An optional Idempotency-Key request header is the real replay-safety mechanism for this endpoint — reference alone does not prevent a duplicate send. Keys expire after 24 hours.
  • There is no contact-groups selection parameter on this endpoint — resolve any saved group's numbers on your own side before calling it.

Need more context? See Getting started for authentication, the response envelope, and the full error-code reference.