---
title: "Install a physical eSIM on a device"
method: POST
path: "/numbers/esims/{id}/install"
tags: ["Esims"]
---

# Install a physical eSIM on a device

`POST /numbers/esims/{id}/install`

Installs the eSIM's activation code onto a device. `deviceId` is optional — omit it to use an available device from the pool. This call is asynchronous: it returns 202 with `{esim, operationId, statusUrl}` immediately, and the result is available by polling `GET /esims/{id}/install-status`. Retrying with the same request is safe if a response is lost.

Returns 409 when the eSIM is not in the `owned` state, or when no device is currently available (see `reason`). When rent-first billing is enabled, a BYO eSIM whose rent isn't active returns 402 with `{esim, rentStatus, checkoutUrl}` instead.

## Path parameters

- `id` string, uuid, required

## Request body

- InstallEsimInput
  - `deviceId` string — physedge device id to install the eSIM onto; omit for a random pool device

## Response `201`

eSIM installed (the device resolved `active`)

- object
  - `data` PublicEsim, required
    - `id` string, uuid, required
    - `status` 'in_stock' | 'owned' | 'installing' | 'installed' | 'install_failed' | 'retired', required
    - `source` 'stocked' | 'byo', required
    - `carrierName` string, nullable, required
    - `countryCode` string, nullable, required
    - `iccid` string, nullable, required
    - `subscriptionId` integer, nullable, required
    - `deviceId` string, uuid, nullable, required
    - `deviceUuid` string, nullable, required
    - `msisdn` string, nullable, required
    - `name` string, nullable, required
    - `createdBy` string, nullable, required
    - `networkStatus` 'degraded' | 'null', nullable, required
    - `rentStatus` 'not_applicable' | 'exempt' | 'inactive' | 'awaiting_payment' | 'active' | 'cancel_pending' | 'refund_pending' | 'retiring' | 'billing_error'
    - `checkoutUrl` string, nullable
    - `currentPeriodEnd` string, date-time, nullable
    - `cancellationScheduled` boolean
    - `exempt` boolean
    - `createdAt` string, date-time, nullable, required
    - `updatedAt` string, date-time, nullable, required

## Other responses

- `202` — Install accepted but not yet resolved to `active` — poll `GET /esims/{id}/install-status` after `Retry-After` seconds
- `400` — Bad Request
- `401` — Unauthorized
- `402` — BYO rent payment required before this eSIM can be installed — see `checkoutUrl` (poll `GET /esims/{id}` if `null`)
- `404` — Not Found
- `409` — Conflict — see `reason` for the stable, machine-readable cause
- `500` — Internal Server Error
- `503` — Service Unavailable — esims are disabled for this deployment (see `reason`)

---

[API](https://skmtc.dev/droidrun/apis/droidrun-cloud.md) · [All operations](https://skmtc.dev/droidrun/apis/droidrun-cloud/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/droidrun/droidrun-cloud/revisions/a1453ac769d4/schema)
