أصدر شرائح eSIM لروسيا آلياً من نظامك أو تطبيقك، بالدفع من رصيد مسبق.
Issue Russia eSIMs automatically from your own system, paid from a prepaid balance.
https://partners.russianesim.com/partner/docs/enready (usually a few seconds).https://partners.russianesim.com
Every request must include your key in the x-api-key header. JSON over HTTPS only.
x-api-key: sk_live_...
Content-Type: application/json
Issues one eSIM. The wholesale price is deducted from your balance immediately; if issuing ultimately fails, it is refunded automatically.
| Field | Type | Required | Description |
|---|---|---|---|
orderId | string | yes | Your own unique reference: 1-64 chars, letters, digits and - _ .. Re-sending the same orderId returns 409 and never charges twice, so retrying after a timeout is safe. |
days | integer | yes | Plan length: 3, 7, 14 or 30. |
customerName | string | no | Optional, max 100. Stored only to help you find orders. We never contact your customers. |
customerEmail | string | no | Optional. Stored only for your reference. We never email your customers. |
curl -X POST https://partners.russianesim.com/partner/v1/orders \
-H "x-api-key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"orderId":"ORD-1001","days":7,"customerName":"Ahmed Ali","customerEmail":"ahmed@example.com"}'const res = await fetch("https://partners.russianesim.com/partner/v1/orders", {
method: "POST",
headers: { "x-api-key": process.env.RUSSIA_ESIM_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ orderId: "ORD-1001", days: 7, customerName: "Ahmed Ali", customerEmail: "ahmed@example.com" })
});
const data = await res.json(); // { status: "processing", orderId, remaining_balance }import os, requests
r = requests.post("https://partners.russianesim.com/partner/v1/orders",
headers={"x-api-key": os.environ["RUSSIA_ESIM_KEY"]},
json={"orderId": "ORD-1001", "days": 7, "customerName": "Ahmed Ali", "customerEmail": "ahmed@example.com"},
timeout=30)
print(r.status_code, r.json())$ch = curl_init("https://partners.russianesim.com/partner/v1/orders");
curl_setopt_array($ch, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["x-api-key: " . getenv("RUSSIA_ESIM_KEY"), "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["orderId" => "ORD-1001", "days" => 7,
"customerName" => "Ahmed Ali", "customerEmail" => "ahmed@example.com"]),
]);
$data = json_decode(curl_exec($ch), true);200 OK{
"status": "processing",
"orderId": "ORD-1001",
"message": "eSIM is being issued. Poll the status endpoint.",
"remaining_balance": 85.0
}
Returns the current state of an order. Poll every 5 seconds after creating it.
| status | Meaning |
|---|---|
processing | Being issued by the network. Keep polling. |
ready | Done. The response includes lpa_code and qr_url. |
failed | Could not be issued. refunded: true means the price is back in your balance. |
{
"orderId": "ORD-1001",
"status": "ready",
"lpa_code": "LPA:1$smdp.example.com$XXXX-XXXX-XXXX",
"qr_png_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
"qr_url": "https://partners.russianesim.com/qr/....png?t=..."
}
lpa_code is the activation code - you can also generate your own QR from it. qr_png_base64 is a ready QR image (PNG, base64) to show directly in your app, e.g. <img src="data:image/png;base64,...">. Prefer it over qr_url so your customers never see a third-party link.
curl https://partners.russianesim.com/partner/v1/orders/ORD-1001 \
-H "x-api-key: sk_live_YOUR_KEY"async function waitForEsim(orderId) {
for (let i = 0; i < 60; i++) { // up to ~5 minutes
const r = await fetch(`https://partners.russianesim.com/partner/v1/orders/${orderId}`,
{ headers: { "x-api-key": process.env.RUSSIA_ESIM_KEY } });
const d = await r.json();
if (d.status === "ready") return d; // d.lpa_code, d.qr_url
if (d.status === "failed") throw new Error("failed - refunded: " + d.refunded);
await new Promise(s => setTimeout(s, 5000)); // poll every 5 seconds
}
}import time, requests
def wait_for_esim(order_id, key):
for _ in range(60):
d = requests.get(f"https://partners.russianesim.com/partner/v1/orders/{order_id}",
headers={"x-api-key": key}, timeout=30).json()
if d["status"] == "ready": return d # d["lpa_code"], d["qr_url"]
if d["status"] == "failed": raise RuntimeError(d)
time.sleep(5){ "balance": 85.0, "currency": "EUR" }
Errors return a JSON body such as {"detail": {"error": "INSUFFICIENT_BALANCE"}}.
| HTTP | error | What to do |
|---|---|---|
| 401 | Invalid or Expired API Key | Check the header, or create a new key in the portal. |
| 402 | INSUFFICIENT_BALANCE | Top up your balance. Nothing was charged. |
| 404 | ORDER_NOT_FOUND | Unknown orderId for your account. |
| 409 | ORDER_ID_EXISTS | This orderId was already used - fetch its status instead. |
| 422 | UNSUPPORTED_DAYS / validation | Fix the request body (days, email format, orderId characters). |
| 429 | RATE_LIMITED | Wait for the Retry-After seconds, then retry. |
| 5xx | - | Temporary. Retry with the same orderId - you will never be charged twice. |
orderId on your side and save it before calling us - this makes retries safe.