For integrations where you own all billing (e.g. a store that runs WooCommerce Subscriptions, or a billing platform like Stripe Billing): when your billing system puts a subscription on hold, tell kurnl to suspend the port; when it becomes active again, tell kurnl to restore it. No kurnl invoices or fees are created either way — kurnl only performs the network action.

Endpoint

Authentication

X-Webhook-Secret header — same secret as the other external-checkout endpoints.

Request body

Identify the subscription in one of three ways:
  • A — session_id: the original checkout session.
  • B — subscription_id + service_provider_document_id: kurnl’s own identifier, as returned by the completion call.
  • C — external_subscription_id + service_provider_document_id: your own per-subscription identifier, the same value you sent as external_subscription_id when you completed the checkout.
Option C is the one to build against. It means you never have to store a kurnl identifier: the key you already own addresses the subscription for the whole of its life. An external_subscription_id kurnl has no subscription for returns 404.

Response — 200 OK

  • suspend resets the switch port to the captive portal, marks the subscription SUSPENDED, and sets is_active: false. That applies to an ACTIVE subscription.
  • Before the install, suspend holds the technician visit instead and answers 200 with subscription_status: "PENDING_INSTALL". A home-drop order is PENDING_INSTALL until the technician has been, so this is the ordinary case, not an error: kurnl cancels any booked visit, releases the slot and stops the booking link. The subscription is not marked SUSPENDED — it was never installed. restore lifts the hold and sends a fresh booking link, again answering 200 with PENDING_INSTALL.
  • A CANCELLED or TERMINATED subscription cannot be suspended — see the 409 below.
  • Read subscription_status from the response rather than assuming the action implies a status; before the install both directions report PENDING_INSTALL.
  • restore only reverses a suspend: it queues port re-provisioning, marks the subscription ACTIVE, and clears kurnl’s dunning/deprovision markers (disconnection notice, exception flag, deprovisioned-at). A subscription in any status other than SUSPENDED cannot be restored — see the 409 below.
  • restore is all-or-nothing. If kurnl cannot re-open the port — missing switch port, VLAN or plan bandwidth — it returns 409 naming what is missing and changes nothing: the subscription stays SUSPENDED. It will never report ACTIVE over a port the suspend left on the captive portal. Retry once the underlying data is fixed (ask kurnl operations).
  • Repeating a call for a subscription already in the target state (suspend an already-SUSPENDED, restore an already-ACTIVE) is an idempotent 200 with port_changed: false and an “Already …” message.

Reading port_changed and port_error

Error codes