Skip to main content

Provision and operate eSIM / IoT (M2M) SIMs

Programmable wireless brings cellular-data SIMs under API control alongside Orbit’s phone numbers. This guide walks the full lifecycle — order → activate → configure → meter → suspend/resume → terminate — plus fleets, quotas, and the webhook events that let your backend react to every transition. Connectivity SIMs are data-only. They carry internet traffic; outbound voice and SMS terminate on Orbit’s own network, never on a cellular bearer. A SIM can only be ordered against a data-only catalog plan — the order API rejects anything else. Reads need the numbers:read scope; provisioning and lifecycle writes need numbers:write. The dashboard surface for everything below is Numbers → Connectivity.

1. Choose the right line type

If your device needs only data, a SIM is the right object. If you need a reachable phone number for a device (for M2M SMS commands, for example), pair the SIM with a purchased DID.

2. Prerequisites

Before ordering a SIM:
  • Funded wallet. Provisioning charges hit your balance, the same as number purchases.
  • A catalog plan. Browse GET /numbers/connectivity/plans and keep the id of an approved plan — e.g. esim-global-payg for consumer eSIM lines or iot-fleet-pooled for pooled IoT fleets.
  • A webhook endpoint subscribed to connectivity_sim.ordered and connectivity_sim.activated (plus the quota events — see section 7). Register it under Settings → Webhooks; without it your backend learns about lifecycle transitions only by polling.

3. Order a SIM

The response is 201 with the SIM record:
A connectivity_sim.ordered webhook fires on success. Ordering the same ICCID twice returns 409 — fetch the existing SIM instead.

4. Activate

New SIMs wait in ordered until you activate them:
The SIM moves ordered → active, a connectivity_sim.activated webhook fires, and data sessions start accruing. For eSIM plans you can also issue an SGP.22 activation (LPA code + QR payload) for customer self-install — POST /numbers/connectivity/sims/:iccid/esim/activation with the aggregator’s SM-DP+ address, then read it back with GET .../esim/activation.

5. Configure fleet network-access rules

Fleets can carry a Network Access Profile: an allow/block policy over countries and carrier networks the fleet’s SIMs may attach to, enforced on every recorded data session — a denied attach is rejected with 403 and never accrues usage. This is your roaming bill-shock guardrail.
GET .../network-access reads the profile back (null when unset — unrestricted attaches), DELETE .../network-access clears it. Keep one profile per fleet; SIMs outside any fleet stay unrestricted.

6. Apply an OTA profile

An OTA (over-the-air) profile pushes a configuration — most often an APN change — to the SIM at runtime, without reissuing hardware. Apply it on an active SIM:
Pass "otaProfileId": null to clear the applied profile. The SIM record’s otaProfileId field shows what is currently queued or applied.

7. Meter usage and enforce limits

Record each data session against the SIM. Usage accumulates on a monotonic per-SIM counter:
The session is rejected (403) if it names a country/carrier denied by the fleet’s Network Access Profile, and rejected (422) on a malformed body. Set a hard cap and a warning point:
  • dataLimitBytes — hard cap. Crossing it suspends the SIM for quota, pending your intervention. null clears the cap.
  • warningThresholdPct — 1–99 percent of the cap where the warning fires. null clears it. A threshold without a cap is rejected.
Read the counter back with GET /numbers/connectivity/sims/:iccid/usage — it returns cumulative bytes, the active quota, and recent sessions. Wire the two quota webhook events into your handler:
The warning event fires once per threshold crossing; the limit event fires when cumulative usage meets or passes the cap and the SIM suspends. Handlers that raise the cap and POST to /resume close the loop.

8. Suspend, resume, terminate

active ⇄ suspended is reversible; terminated is the terminal sink — nothing else can be run against the SIM afterward. Each transition fires its lifecycle webhook (connectivity_sim.suspended / .resumed / .terminated) with the same payload shape: iccid, plan_id, state, fleet_id.

9. Fleet rollup

SIMs ordered with the same fleetId aggregate as a fleet. The bulk read:
returns one entry per fleet with its member count, cumulative usage, and — for fleets on a pooled plan — the shared-pool health (allowance drawn, remaining, ok/warning/exceeded status). In the dashboard, Numbers → Connectivity shows the same fleet cards plus the per-SIM table and the fleet-aggregated usage panel. Pagination: the SIM list endpoint accepts ?limit=N (max 1000) and always reports the full filtered count, so page by growing limit (the dashboard’s “Load more” pattern) instead of drifting offsets. Keep limit small for the first render and widen in chunks. Example 1 — Node.js SDK, full lifecycle:
Example 2 — Python, mirroring the curl flow:

10. Troubleshooting

Only tenant-scoped endpoints appear in this guide; internal administration surfaces stay out of scope by design. For the event payloads of every webhook shown here, see Webhook events.