Events
An event records that something happened: an order completed, an eSIM was activated, your balance ran low. Each event is sent to your webhook endpoints. The same events are kept for 30 days and can be read here.
Order, top-up and balance events are always recorded. Live eSIM events (esim.*) are recorded only while your account has at least one enabled live webhook endpoint, and only for changes seen in the last 72 hours. If you do not use webhooks, read eSIM state with GET /v1/esims instead. See eSIM events in live.
Use these endpoints to reconcile: if your server was down, or you are not sure you handled every webhook, list the events and process the ones you have not seen.
| Method | Path | What it does |
|---|---|---|
GET |
/v1/events |
List the events of the last 30 days. |
GET |
/v1/events/{id} |
Get one event. |
Event types
Section titled “Event types”| Type | data holds |
|---|---|
order.completed |
The Order. Sent for completed and for partially_completed orders: read data.status. |
order.failed |
The Order. |
esim.activated |
An eSIM summary. |
esim.usage_80 |
An eSIM summary. |
esim.usage_100 |
An eSIM summary. |
esim.expired |
An eSIM summary. |
topup.completed |
The Topup. |
balance.low |
balance and threshold, both Money. |
Webhooks explains when each one is sent. The ping test event is never stored, so it is not in this list.
Every event has a sequence number that grows with each event on your account. Use it, not created, to put events in order.
List events
Section titled “List events”GET /v1/events
Returns the events for the mode of your key, newest first. A test key sees test events and a live key sees live events.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
type |
query | string | No | One event type from the table above, such as order.completed. |
limit |
query | integer | No | 1 to 100. Default 25. |
cursor |
query | string | No | The next_cursor of the previous page. |
curl "$ESIMIFY_API_URL/v1/events?type=order.completed&limit=50" \ -H "Authorization: Bearer $ESIMIFY_API_KEY"const res = await fetch(`${process.env.ESIMIFY_API_URL}/v1/events?type=order.completed&limit=50`, { headers: { Authorization: `Bearer ${process.env.ESIMIFY_API_KEY}` },});const events = await res.json();<?php$ch = curl_init(getenv('ESIMIFY_API_URL') . '/v1/events?type=order.completed&limit=50');curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('ESIMIFY_API_KEY'), ],]);$events = json_decode(curl_exec($ch), true);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);import osimport requests
res = requests.get( os.environ["ESIMIFY_API_URL"] + "/v1/events", headers={"Authorization": "Bearer " + os.environ["ESIMIFY_API_KEY"]}, params={"type": "order.completed", "limit": "50"}, timeout=30,)events = res.json()Response
Section titled “Response”200 OK with a list of Event objects.
{ "data": [ { "id": "evt_5b81c0d2e4f6a7b8c9d0e1f2", "type": "order.completed", "mode": "test", "created": "2026-10-02T09:14:08Z", "sequence": 41, "data": { "id": "ord_test_3f9a1c2b7d4e", "status": "completed", "mode": "test", "package_id": "pkg_10482", "quantity": 1, "items": [ { "package_id": "pkg_10482", "quantity": 1 } ], "customer_ref": "booking-84512", "total": { "amount": "249.00", "currency": "INR" }, "refunded": { "amount": "0.00", "currency": "INR" }, "balance_after": { "amount": "999751.00", "currency": "INR" }, "created": "2026-10-02T09:14:07Z", "esims": [ { "iccid": "8999999000000012345", "status": "ready" } ] } } ], "has_more": false, "next_cursor": null}Errors
Section titled “Errors”| Status | Code | When |
|---|---|---|
400 |
invalid_request |
A query parameter is not valid, for example a type that is not in the table above. param names it. |
Any endpoint can also return the common errors.
Get an event
Section titled “Get an event”GET /v1/events/{id}
Returns one event. The id is the same one you receive in the webhook body and in the X-Esimify-Event-Id header.
Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | string | Yes | The event id, such as evt_5b81c0d2e4f6a7b8c9d0e1f2. |
curl "$ESIMIFY_API_URL/v1/events/evt_5b81c0d2e4f6a7b8c9d0e1f2" \ -H "Authorization: Bearer $ESIMIFY_API_KEY"const res = await fetch(`${process.env.ESIMIFY_API_URL}/v1/events/evt_5b81c0d2e4f6a7b8c9d0e1f2`, { headers: { Authorization: `Bearer ${process.env.ESIMIFY_API_KEY}` },});const event = await res.json();<?php$ch = curl_init(getenv('ESIMIFY_API_URL') . '/v1/events/evt_5b81c0d2e4f6a7b8c9d0e1f2');curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 30, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('ESIMIFY_API_KEY'), ],]);$event = json_decode(curl_exec($ch), true);$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);import osimport requests
res = requests.get( os.environ["ESIMIFY_API_URL"] + "/v1/events/evt_5b81c0d2e4f6a7b8c9d0e1f2", headers={"Authorization": "Bearer " + os.environ["ESIMIFY_API_KEY"]}, timeout=30,)event = res.json()Response
Section titled “Response”200 OK with an Event.
{ "id": "evt_9a3f7c21b0d4e5f6a7b8c9d0", "type": "esim.activated", "mode": "test", "created": "2026-10-02T11:02:41Z", "sequence": 41, "data": { "iccid": "8999999000000012345", "status": "active", "order_id": "ord_test_3f9a1c2b7d4e", "customer_ref": "booking-84512", "data": { "unlimited": false, "total_mb": 1024, "used_mb": 0, "remaining_mb": 1024 }, "expires_at": "2026-10-09T11:02:40Z" }}Errors
Section titled “Errors”| Status | Code | When |
|---|---|---|
404 |
not_found |
No event has this id for your account in this mode, or it is older than 30 days. |
Any endpoint can also return the common errors.

