When to use this
Bulk provisioning is designed for:- Migrations — moving a large subscriber base from another platform to kurnl
- New building activations — activating an entire MDU building at once when all units are pre-wired
- Batch imports — provisioning a list of new subscribers from a CSV or external system
How it works
ThePOST is synchronous per item: kurnl creates the subscriber and
subscription and queues the SSH job for every item inline, then returns
200 with a per-item result list. Only the switch SSH step runs in the
background — expect a long-running request for big batches. You then poll the
batch status endpoint to track the SSH jobs.
Submit a batch
Each item wraps the full subscriber object (same shape as provider-initiated provisioning) plus aplan_version_id, a location_hash or location_identifier, and optionally a billing block
(see Billing per item).
status per item is "queued" or "error".
Poll for status
job_status is one of pending, running, completed, failed, error,
unknown. There is no batch-level status field — aggregate the item states
client-side (the batch is done when no item is pending or running).
Unknown batch_id returns 404; another provider’s batch returns 403.
Handling partial failures
Individual item failures don’t stop the rest of the batch: failed items come back with"status": "error" and an "error" message in the POST response.
Fix the cause (e.g. correct the location hash) and resubmit those items.
Resubmitting is safe: provisioning is idempotent per item — the same
subscriber email + plan version + location returns the existing subscription
instead of creating a duplicate.
Billing per item
Every item takes the same optionalbilling block as a single
provider-initiated order. Without it kurnl
provisions and you bill. With owner: "kurnl" and the customer’s id from your Stripe account, kurnl
adopts that customer and bills the subscription — a prorated first invoice at activation, then monthly on
billing_day:
"status": "error" and the reason in error, prefixed
with the code (billing_not_available, stripe_customer_not_found, stripe_customer_has_no_payment_method,
stripe_customer_in_use, stripe_unavailable), and the rest of the batch continues. Each item’s result
carries billing_owner so you can confirm what kurnl recorded.
Limits
If you need to provision more than 100 subscribers, split them into multiple
batches (mind the 10/min rate limit on the POST).
Migration checklist
Before running a bulk migration:1
Map location hashes
Every subscriber needs a valid
location_hash corresponding to a kurnl switch port. Work with your kurnl account manager to get a mapping from your building/unit records to kurnl location hashes.2
Validate plan versions
Confirm your
plan_version_id values are active. Expired plan versions will cause the entire subscriber entry to fail.3
Test with a small batch
Run a batch of 3–5 subscribers first and verify they provision correctly before running the full migration.
4
Run in off-peak hours
Large batches generate significant switch SSH traffic. Schedule migrations during low-traffic periods.
5
Handle failed entries
After the batch completes, process failed entries individually. Log the errors, fix the root cause, and resubmit.