POST /iot/bulk_jobs
One change for up to 5,000 of the account's IoT SIMs, run in the background.
Name the SIMs by sim_ids (from GET /iot/sims) and/or iccids, 1 to 5,000 in all. Every SIM is checked to be on this account before anything runs: one that is not, a repeat, or more than 5,000 is 400 invalid_parameter and nothing is changed. The answer is 202 with the job; follow it with GET /iot/bulk_jobs/{id}. Each SIM is changed at most once, also if the job is interrupted and resumed; a SIM whose change was interrupted before it was confirmed is reported failed, never sent again. Up to 5,000 SIMs take about 2 minutes. Needs an Idempotency-Key: a retry with the same key and body returns the same job (200); the same key with another body is 409 idempotency_key_reused. A locked account gets 423 account_locked. The iot.bulk_job_done webhook fires when the job finishes.
Fields
| Name | In | Type | |
|---|---|---|---|
| Idempotency-Key * | header | string | Required on every POST. 8-128 characters: letters, digits, dot, colon, hyphen or underscore. The first response is stored for 24 hours and replayed for any retry with the same key and the same body. Two rules, set per operation by x-charged. Charged or partner-side operations (x-charged true: dips, dip batches, orders, SMS, porting) never re-run while a first attempt is unfinished: a retry answers 409 idempotency_key_in_use (outcome pending) until the first outcome is stored, and the key is also given to the partner as its own reference, so one key never causes more than one order, charge or message, even across failures. A charged operation that fails part-way stores that failure as the key's answer; only a refusal before anything ran (400, 401, 402, 403, 404, 429) frees the key for a retry. Operations with no outside effect (x-charged false) hold their key for at most 2 minutes; after that a retry runs fresh. Missing: 400 missing_parameter (param Idempotency-Key). Malformed: 400 invalid_parameter. Same key, different body: 409 idempotency_key_reused. First request still running: 409 idempotency_key_in_use. |
| sim_ids | body | array of string | |
| iccids | body | array of string | |
| change * | body | object |
* required
Example
curl -X POST "https://api.voicepro.plus/v3/iot/bulk_jobs" \
-H "Authorization: Bearer vpkey_YOUR_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"sim_ids":["sim_7k2mqqxw4hd3nvbc5rtfz6ya","sim_b4nq7zx2kw5rm3dh6ctvfypa"],"change":{"data_limit":{"total_bytes":1073741824,"period":"monthly","alert_bytes":858993459}}}'{
"object": "iot_bulk_job",
"id": "bulk_3f9a1c7e5b2d4a6c8e0f1a2b",
"status": "done",
"change": {
"data_limit": {
"total_bytes": 1073741824,
"period": "monthly",
"alert_bytes": 858993459
}
},
"total": 2,
"processed": 2,
"succeeded": 2,
"failed": 0,
"created_at": "2026-10-28T09:10:00Z",
"finished_at": "2026-10-28T09:10:04Z"
}Errors
Every error has the same shape: { "error": { "type", "code", "message", "param", "request_id" } }.
Webhook events
This call can cause iot.bulk_job_done. See webhooks.