> ## Documentation Index
> Fetch the complete documentation index at: https://docs.esimstory.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Get eSIM status

> Live installation and usage state for one eSIM

The order response and the webhook both describe a moment: an eSIM was issued,
here is its activation data. Neither tells you what happened next.

This endpoint does. Use it to answer whether a traveller installed the profile,
how much data they have left, and when it expires.

<Note>
  This is **not** a substitute for your webhook. The webhook is the only channel
  that delivers the activation data itself — the ICCID, the activation code, the
  QR. This endpoint reports on an eSIM you have already been told about.
</Note>

## Path parameter

<ParamField path="topup_id" type="string" required>
  The unit's `topup_id`, exactly as returned in the order response and repeated
  in its webhook. Unique across all orders.
</ParamField>

## Signing a GET

The signed string is the same five lines as any other request, with the body
hash taken over the empty string. See
[Authentication](/authentication/overview) — the constant is listed there.

The path you sign includes the `/api` prefix and the `topup_id`:

```
/api/v1/api_partner/esims/20250129123456123456789012/status
```

## Response

`200` with the fields below, and only those. The set is fixed: anything the
upstream provider sends that is not listed here is dropped before the response
leaves us, so you can rely on the shape.

All timestamps are **UTC**, ISO 8601 with a `Z` suffix. `activation_expiration_at`
is a plain date with no zone attached — read it as UTC, or a partner in UTC+9
will be a day out at the boundary.

<ResponseField name="status" type="string">
  Where the profile is in its lifecycle. One of:

  | Value                | Meaning                                                              |
  | -------------------- | -------------------------------------------------------------------- |
  | `not_installed`      | Issued; the traveller has not installed it yet                       |
  | `installed`          | On a device, never connected — the plan has not started              |
  | `activated`          | Connected to a network at the destination; the plan clock is running |
  | `expired`            | The plan period ended                                                |
  | `activation_expired` | Never activated within the 180-day activation window                 |
  | `refunded`           | The unit was refunded                                                |
</ResponseField>

<ResponseField name="created_at" type="string">
  When the profile was issued. UTC.
</ResponseField>

<ResponseField name="installed_at" type="string">
  When the traveller installed it, or `null` if they have not. UTC.
</ResponseField>

<ResponseField name="activated_at" type="string">
  When the profile first connected, or `null`. UTC.
</ResponseField>

<ResponseField name="expires_at" type="string">
  When the plan stops working. UTC.
</ResponseField>

<ResponseField name="data_total_mb" type="number">
  Allowance in megabytes.
</ResponseField>

<ResponseField name="data_used_mb" type="number">
  Consumed so far.
</ResponseField>

<ResponseField name="data_remaining_mb" type="number">
  Left to use.
</ResponseField>

<ResponseField name="device_name" type="string">
  The handset the profile was installed on, or `null`.
</ResponseField>

<ResponseField name="install_count" type="integer">
  How many times the profile has been installed.
</ResponseField>

<ResponseField name="eid" type="string">
  The eUICC identifier of the device holding the profile, or `null`.
</ResponseField>

<ResponseField name="activation_expiration_at" type="string">
  The last date the profile can still be activated, `YYYY-MM-DD` in UTC. After
  it passes without activation, `status` becomes `activation_expired`.
</ResponseField>

<Note>
  Refund eligibility is not reported here. It is set by your agreement with us —
  a full refund before activation, and settlement as a credit on your next
  invoice — not by anything in this response. Contact support to raise one.
</Note>

## Installed is not activated

The two are separate events, and most of this endpoint only makes sense once
that is clear.

**Installed** means the profile is on the device. A traveller does this at home,
on Wi-Fi, before leaving — it is what we recommend, and it changes nothing
commercially. `installed_at` is set; `activated_at` is still `null`.

**Activated** means the profile attached to a network for the first time, inside
the coverage the plan was bought for. It happens by itself once the traveller
arrives, turns on data roaming for the eSIM line, and the handset finds a local
carrier. Nobody presses an "activate" button.

So a profile installed at home stays `installed` until the trip — usually for as
long as the traveller has until departure. The exception is a regional plan
whose coverage already includes where they are: that can attach before they
leave, and the clock starts then.

Three things hang off that moment rather than off the order or the install:

* **The plan clock starts.** `expires_at` is counted from activation, and a
  daily allowance refills every 24 hours from the same point. A traveller who
  buys a 7-day plan in March and lands in June still gets seven days.
* **The 180-day window closes.** Until activation, the unit has until
  `activation_expiration_at` to be used at all. Past that date it becomes
  `activation_expired` and is spent.
* **Refund eligibility ends.** Before activation the unit is fully refundable —
  installing it does not change that. Once it connects, or once any data is
  used, it is not.

<Warning>
  Do not treat delivery or installation as the start of anything. A support reply
  telling a traveller their plan is running while `activated_at` is still `null`
  is wrong, and refusing a refund on an installed-but-never-activated unit is
  refusing one your agreement with us grants.
</Warning>

<ResponseExample>
  ```json Response theme={null}
  {
    "status": "activated",
    "created_at": "2026-08-18T02:14:07Z",
    "installed_at": "2026-08-19T09:31:44Z",
    "activated_at": "2026-08-20T01:02:58Z",
    "expires_at": "2026-09-17T01:02:58Z",
    "device_name": "iPhone 15 Pro",
    "install_count": 1,
    "eid": "89049032000000000000000000000000",
    "data_total_mb": 1024.0,
    "data_used_mb": 348.0,
    "data_remaining_mb": 676.0,
    "activation_expiration_at": "2027-02-14"
  }
  ```
</ResponseExample>

## In sandbox

Sandbox returns a fixed, representative object rather than live data — sandbox
`topup_id`s are issued by us and no real profile exists behind them. The shape
matches production, so you can build and test your parser against it, but the
values do not change and do not reflect anything you did.

## Errors

### 404 Not Found

```json theme={null}
{
  "error": {
    "code": "not_found",
    "message": "No eSIM found for that topup_id."
  }
}
```

You get the same response whether the `topup_id` was never issued or belongs to
another partner. Check the value against the order response that produced it.

### 422 Unprocessable Entity

The provider could not be reached or returned an error. Same shape as everywhere
else in this API:

```json theme={null}
{
  "errors": ["eSIM Status failed - Status: 500, Message: Unknown error"]
}
```

Safe to retry — this endpoint reads, it does not change anything.

### 429 Too Many Requests

**60 requests per minute**, counted against your access key rather than your IP.
Each call reaches the upstream provider, so this limit is tighter than the
general one described under [Rate limits](/endpoints/orders#rate-limits).

Poll sparingly. Status changes when a traveller acts — installing, connecting,
using data — not on a schedule worth watching closely.
