Skip to main content

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 seven connectivity_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 seven connectivity_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:
Lifecycle events carry the inventory fields instead:
Full payload shapes for all seven types are in the webhook events reference. Deduplicate on the envelope event id — 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 from POST /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 into active from POST .../activate. Data sessions start accruing from here.
  • connectivity_sim.suspended — paused from POST .../suspend (manually, or by the usage hard cap). No usage accrues while suspended.
  • connectivity_sim.resumed — return from suspended to active via POST .../resume. This is deliberately a different type from activated so your subscriber can tell a first activation apart from a post-suspend restart — bill or alert accordingly.
  • connectivity_sim.terminated — terminal sink from POST .../terminate. Nothing can run against the SIM afterward; active ⇄ suspended was reversible, this is not.
A 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:
  1. 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.
  2. Endpoint health. A delivery endpoint that answers 401/403/404/410 is 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.
  3. 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.
  4. 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 with POST /api/v1/webhooks/dlq/:deliveryId/requeue. The full recovery flow is on the Webhooks overview.
  5. 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.
If the SIM record itself is stuck — 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_id from the subscription or the SIM record).
  • Request id — the meta.request_id from 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, and warning_threshold_bytes from the event payload or from GET /numbers/connectivity/sims/:iccid/usage.
With those, support can replay the DLQ entry, trace the emitter, and confirm the state the record settled into without a round trip.