See Bulk Provisioning for the full guide.

Endpoints

Both endpoints require X-API-Key.

Submit batch body

Each item wraps the full subscriber object (same shape as provider-initiated provisioning) plus a plan_version_id, a location_hash or location_identifier (at least one; hash preferred), and optionally a discount_code (as on provider-initiated provisioning) and the same billing block as the single endpoint (owner, stripe_customer_id, billing_day — see provider-initiated provisioning). 1–100 items per batch.

Response — 200 OK (synchronous)

The POST processes every item inline (subscriber + subscription created, SSH job queued) and returns per-item results — not a 202:
status per item is "queued" or "error". A failed item may also carry error_code, a machine-readable code (for example install_required, speed_tier, port_in_use); it is absent or null otherwise. Failed items don’t stop the rest of the batch. billing_owner is "kurnl" or "partner" on a queued item and null on a failed one. An item that asked for kurnl billing and failed the billing pre-flight reports 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).

Poll response

GET /partner/provisioning/bulk/{batch_id}:
A failed item (job_status: "error") carries the same error and error_code as in the POST response. job_status is one of pending, running, completed, failed, error, unknown. There is no batch-level aggregate status — the batch is done when no item is pending or running.

Errors & limits

Bulk provisioning is a first-line tool. An item whose port is not in a first-line building — a second- or third-line building, an unclassified building, or a switch with no building — comes back with status: "error" and error_code: "install_required"; nothing is created for that item and the rest of the batch runs. Order that suite with provider-initiated provisioning (CKO-04) and its unit_id instead. An item whose plan is for existing customers only comes back with status: "error" and the plan_audience refusal of provider-initiated provisioning as its error; nothing is created for that item. An item whose discount_code does not resolve comes back with status: "error" and Invalid or expired discount code as its error; nothing is created for that item and the rest of the batch runs. An item whose subscriber.password the sign-in service refuses for a new account comes back with status: "error" and the service’s reason as its error (e.g. Password should be at least 6 characters.); nothing is created for that item and the rest of the batch runs. Resubmit it with another password. Batch results are retained for 30 days. Retrying failed items is safe: provisioning is idempotent per item — the same subscriber email + plan version + location returns the existing subscription instead of creating a duplicate. An item whose port already carries another live order (another subscriber’s, or another plan version) fails with error_code: "port_in_use"; resubmitting it does not help until that line is cancelled.