Troubleshooting: connectivity SIM events — usage gates, lifecycle stream, and a silent webhook
A connectivity (eSIM / IoT / M2M) SIM reports every state change and every quota gate as one of sevenconnectivity_sim.* webhook events. This page is
the runbook for that event family: what each event means, why the warning
and the hard cap behave differently, how to decode the lifecycle, and what
to check when the events you subscribed to never arrive.
The model behind the events is on the
connectivity SIM concept page, and the
full operating walk-through (order → activate → meter → suspend →
terminate) is the connectivity SIM lifecycle guide. This page is for when the
stream misbehaves. The dashboard surface for everything below is
Numbers → Connectivity.
1. Event subscription
There are sevenconnectivity_sim.* event types, split into two families:
the usage gates (usage_warning, limit_exceeded) and the lifecycle
transitions (ordered, activated, suspended, resumed,
terminated). Subscribe to the ones you need on the endpoint that receives
POST /api/v1/webhooks deliveries — registered under
Settings → Webhooks in the dashboard, or through the webhooks API. The
delivery envelope, signature headers, and retry schedule are the same as
for every other event family; see
Webhooks overview.
The payload differs by family. Usage-gate events carry the quota counters:
connectivity_sim.* deliveries are at-least-once, so a
retry or a dead-letter replay can deliver the same lifecycle event twice.
2. Usage gates — warning vs hard cap
Two events guard consumption, and they answer different questions:
The warning is advisory: it fires once per threshold crossing and changes
nothing on the SIM. The limit event is the gate closing — at the cap the
SIM suspends itself, which is the platform enforcing the budget you set
rather than a fault. That is why every
limit_exceeded handler should end
in a quota change plus a resume; without both, resuming alone puts the SIM
straight back over the same cap on the next session.
If you receive limit_exceeded but never saw a usage_warning first,
check the quota configuration: a warning point only exists where
warningThresholdPct is set, and a threshold without a cap is rejected at
write time. Clear both fields and the stream goes quiet on the usage
family entirely — lifecycle events still fire.
3. Lifecycle decoder
The SIM lifecycle has four states, and every legal move between them emits exactly one event:connectivity_sim.ordered— record created fromPOST /numbers/connectivity/sims. The SIM exists but carries no data. An eSIM line may wait on a device-side install before activation; a physical SIM waits on its activation call.connectivity_sim.activated— first transition intoactivefromPOST .../activate. Data sessions start accruing from here.connectivity_sim.suspended— paused fromPOST .../suspend(manually, or by the usage hard cap). No usage accrues while suspended.connectivity_sim.resumed— return fromsuspendedtoactiveviaPOST .../resume. This is deliberately a different type fromactivatedso your subscriber can tell a first activation apart from a post-suspend restart — bill or alert accordingly.connectivity_sim.terminated— terminal sink fromPOST .../terminate. Nothing can run against the SIM afterward;active ⇄ suspendedwas reversible, this is not.
409 on activate/suspend/resume/terminate means the SIM is not in the
state the verb expects (most often: already terminated). Read the current
state with GET /numbers/connectivity/sims/:iccid before issuing the
transition. If your integration only watches activated and treats
resumed as unknown, it sees suspended SIMs come back as noise — handle
both return-to-active types.
4. Events not firing — the silent-stream checklist
connectivity_sim.* events are emitted best-effort from the per-SIM
endpoints (POST /numbers/connectivity/sims and the
/activate|/suspend|/resume|/terminate|/usage verbs). A successful state
change returns 2xx even when the webhook delivery fails, so an empty
stream while the API works means the delivery path broke, not the SIM.
Work through these in order:
- Subscription. Confirm the endpoint under Settings → Webhooks
still lists the
connectivity_sim.*types. A recreated endpoint does not inherit the old one’s event filter. - Endpoint health. A delivery endpoint that answers
401/403/404/410is treated as proven-dead: retries are skipped, the endpoint is disabled, and the org admin is notified. Re-enable it after fixing the response — see integration receiver disabled. - Endpoint cap. Creating or re-registering endpoints can race the per-organization endpoint cap, which silently drops registrations. See webhook endpoint cap and DNS pre-create.
- Dead-letter queue. Deliveries that exhausted retries (about 4.3
hours of backoff) land in the DLQ and stay replayable for 7 days. List
them under Developer → Webhooks → Dead-letter queue or with
GET /api/v1/webhooks/dlq, and requeue withPOST /api/v1/webhooks/dlq/:deliveryId/requeue. The full recovery flow is on the Webhooks overview. - Silent by configuration. Usage events only exist while a quota is set — if only the usage family is missing while lifecycle events arrive, re-read section 2 before suspecting delivery.
ordered forever despite an install
completing, for example — that is a queue or surface problem, not an event
problem; route through
enqueued empty states.
5. Escalation checklist
Open a ticket when sections 1–4 rule out every self-serve cause. Attach the bundle so support does not have to re-derive your state:- ICCID of the SIM (the identifier in every payload and every per-SIM path).
- Plan id (
plan_idfrom the subscription or the SIM record). - Request id — the
meta.request_idfrom the state-change or usage-recording POST that should have fired the event. - The event type you expected and the delivery id (
evt_...) from the DLQ row or the inspecting-deliveries log, when one exists. - For quota disputes: the
usage_bytes,data_limit_bytes, andwarning_threshold_bytesfrom the event payload or fromGET /numbers/connectivity/sims/:iccid/usage.