دخول البوابة · Portal login

توثيق الربط البرمجي (Partner API)

أصدر شرائح eSIM لروسيا آلياً من نظامك أو تطبيقك، بالدفع من رصيد مسبق.

Russia eSIM - Partner API

Issue Russia eSIMs automatically from your own system, paid from a prepaid balance.

كيف تبدأ؟ (4 خطوات)

1. ادخل البوابةمن رابط بوابة الشركاء بمعرف الشركة وكلمة المرور اللذين أرسلناهما لك، ثم غيّر كلمة المرور من أسفل لوحتك.
2. ولّد مفتاح APIمن قسم «مفاتيح الربط» اضغط «توليد مفتاح». المفتاح يظهر مرة واحدة فقط: سلّمه لمبرمجكم ليحفظه في إعدادات السيرفر.
3. اشحن رصيدكمن البوابة: «شحن الرصيد» وادفع بالبطاقة، فيُضاف المبلغ فوراً (أو حوّل لنا بنكياً). يُخصم سعر الجملة عند كل شريحة، ويعود تلقائياً إذا فشل الإصدار.
4. ابدأ الإصدارنظامكم يرسل طلباً واحداً لكل شريحة (التفاصيل التقنية في قسم English)، فيستلم كود التثبيت وصورة QR خلال ثوانٍ ويعرضها لعميلكم.

ماذا ترى في البوابة؟

كيف تعمل العملية؟

  1. عميلكم يشتري شريحة روسيا من موقعكم أو تطبيقكم.
  2. نظامكم يرسل لنا الطلب: رقم الطلب، عدد الأيام، اسم العميل وإيميله.
  3. نخصم سعر الجملة من رصيدكم ونصدر الشريحة.
  4. نظامكم يستعلم عن الطلب كل 5 ثوانٍ حتى تصبح الحالة «جاهزة»، فيعرض للعميل رمز QR داخل تطبيقكم أو يرسله بإيميلكم.

معلومات مهمة

للدعم أو شحن الرصيد: support@russianesim.com

Quick start

1. Log inOpen the partner portal with the partner ID and password we sent you, then change your password.
2. Create an API key"API Keys" → "Generate". The key is shown once. Store it in an environment variable, never in client-side code.
3. Top upIn the portal, "Top up balance" lets you pay by card and the amount is credited instantly (bank transfer also possible). Each eSIM is charged at your wholesale price and refunded automatically if issuing fails.
4. IntegrateCreate an order, then poll its status until it is ready (usually a few seconds).

Base URL & authentication

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

Keys can be created and revoked at any time from the portal; each key expires after 90 days to 1 year. Never expose a key in a browser or mobile app - call our API from your server.

POST/partner/v1/orders

Issues one eSIM. The wholesale price is deducted from your balance immediately; if issuing ultimately fails, it is refunded automatically.

FieldTypeRequiredDescription
orderIdstringyesYour 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.
daysintegeryesPlan length: 3, 7, 14 or 30.
customerNamestringnoOptional, max 100. Stored only to help you find orders. We never contact your customers.
customerEmailstringnoOptional. 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);

Response 200 OK

{
  "status": "processing",
  "orderId": "ORD-1001",
  "message": "eSIM is being issued. Poll the status endpoint.",
  "remaining_balance": 85.0
}

GET/partner/v1/orders/{orderId}

Returns the current state of an order. Poll every 5 seconds after creating it.

statusMeaning
processingBeing issued by the network. Keep polling.
readyDone. The response includes lpa_code and qr_url.
failedCould 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)

GET/partner/v1/balance

{ "balance": 85.0, "currency": "EUR" }

Tip: check your balance daily and top up before it runs low - orders are rejected with 402 when the balance is insufficient.

Errors

Errors return a JSON body such as {"detail": {"error": "INSUFFICIENT_BALANCE"}}.

HTTPerrorWhat to do
401Invalid or Expired API KeyCheck the header, or create a new key in the portal.
402INSUFFICIENT_BALANCETop up your balance. Nothing was charged.
404ORDER_NOT_FOUNDUnknown orderId for your account.
409ORDER_ID_EXISTSThis orderId was already used - fetch its status instead.
422UNSUPPORTED_DAYS / validationFix the request body (days, email format, orderId characters).
429RATE_LIMITEDWait for the Retry-After seconds, then retry.
5xx-Temporary. Retry with the same orderId - you will never be charged twice.

Limits & best practices

  • Fully white-label: we never email, message or otherwise contact your customers, and our name never appears to them. You deliver the eSIM in your own app or email.
  • Rate limit: 60 requests per minute per API key.
  • Generate a unique orderId on your side and save it before calling us - this makes retries safe.
  • Use one key per server/environment so you can revoke one without stopping the others.
  • Your wholesale prices are private to your account and shown only in your partner portal.
  • Support: support@russianesim.com