Перейти к содержимому
API-документация

Купить пакет eSIM

POST/api/partner/v1/esim/orders
Scope
esim:write
Idempotency-Key
обязателен

Резервирует цену пакета на вашем балансе и запускает выпуск.

Ответ — заказ в статусе processing, а не eSIM. Выпуск асинхронный: дождитесь события esim.issued или опрашивайте GET /esim/orders/{id}, пока status не уйдёт из processing.

До завершения заказа деньги на балансе зарезервированы, а не списаны. esim.issue_failed возвращает резерв целиком. operation.needs_review означает, что провайдер не дал однозначного ответа: eSIM может существовать, деньги остаются в резерве, мы разбираемся — не покупайте повторно.

Idempotency-Key обязателен. Повтор с тем же ключом возвращает исходный заказ — второй eSIM куплен не будет.

Тело запроса

ПолеТипОбяз.Описание
external_idstringнетВаш собственный идентификатор заказа. Необязателен; уникален в пределах аккаунта — вторая покупка с тем же external_id отклоняется с 409 idempotency_conflict. По нему заказ находится через GET /esim/orders/external/{external_id}, если наш ответ потерялся. (до 128 символов)
package_idstring (uuid)даИз GET /esim/packages

Пример запроса

BODY='{"package_id":"5b2f7c1a-3d4e-4f60-8a71-9c0d1e2f3a4b","external_id":"order-1001"}'
IDEM=$(uuidgen)
TS=$(date +%s)
SIG=$(printf '%s\n%s\n%s\n%s\n%s' "$TS" "POST" "/api/partner/v1/esim/orders" "$BODY" "$IDEM" \
  | openssl dgst -sha256 -hmac "$PP_SECRET" -hex | awk '{print $NF}')

curl -sS -X POST "https://api.plativputi.com/api/partner/v1/esim/orders" \
  -H "X-Key-Id: $PP_KEY_ID" \
  -H "X-Timestamp: $TS" \
  -H "X-Signature: $SIG" \
  -H "Idempotency-Key: $IDEM" \
  -H "Content-Type: application/json" \
  -d "$BODY"
import { randomUUID } from "node:crypto";

const res = await pp("POST", "/esim/orders", {
  "package_id": "5b2f7c1a-3d4e-4f60-8a71-9c0d1e2f3a4b",
  "external_id": "order-1001"
}, { idempotencyKey: randomUUID() });
import uuid

res = pp("POST", "/esim/orders", body={
    "package_id": "5b2f7c1a-3d4e-4f60-8a71-9c0d1e2f3a4b",
    "external_id": "order-1001",
}, idempotency_key=str(uuid.uuid4()))
$res = pp('POST', '/esim/orders', [
    'package_id' => '5b2f7c1a-3d4e-4f60-8a71-9c0d1e2f3a4b',
    'external_id' => 'order-1001',
], uuid4());

pp() — функция-обёртка с подписью из раздела Аутентификация и подпись.

Ответ

202 Accepted — EsimOrderDTO

ПолеТипОбяз.Описание
created_atstringда—
error_codestringнетprovider_rejected | refunded | needs_review | order_expired | unknown_order_status
external_idstringнет—
idstringдаНаш идентификатор заказа eSIM
operation_idstringдаОперация, держащая ваши деньги, — тот же id, что приходит в событиях
operation_statusstringдаprocessing | succeeded | failed | needs_review — судьба вашего резерва
packageEsimPackageDTOнетПакет в его текущем виде; price_usd выше — то, что вы заплатили
package.countriesarray<string>даISO alpha-2 коды стран, которые покрывает пакет. Пусто, если провайдер не опубликовал список.
package.currencystringнет—
package.data_gbstringдаОбъём трафика в ГБ, десятичная строка. Не имеет смысла, если unlimited = true.
package.has_5gbooleanдаtrue, если в опубликованной сети упомянут 5G. false означает и «не указано».
package.idstringдаИдентификатор пакета — передайте его как package_id в POST /esim/orders
package.networkstringнетПоколение сети / операторы, как их опубликовал провайдер, если известны
package.price_usdstringнетСколько покупка этого пакета спишет с вашего баланса, USD
package.region_codestringдаISO 3166-1 alpha-2 для пакета одной страны, иначе код региона (EUROPE, ASIA, GLOBAL, …)
package.region_namestringда—
package.smsintegerнетВключённые SMS, если они есть в пакете
package.titlestringда—
package.unlimitedbooleanда—
package.validity_daysintegerда—
package.voice_minutesintegerнетВключённые минуты звонков, если они есть в пакете
price_usdstringдаСколько эта покупка резервирует / списала с вашего баланса, USD
profileEsimProfileDTOнетПоявляется, когда eSIM выпущена И покупка списана (operation_status succeeded)
profile.activation_codestringдаПолная строка LPA (LPA:1$<SM-DP+>$<matching id>). Секрет: кто им владеет, тот может установить eSIM. Не пишите его в логи и не храните открытым текстом.
profile.apnstringнет—
profile.iccidstringда—
profile.matching_idstringнет—
profile.qr_payloadstringдаСтрока для QR-кода установки (совпадает с activation_code). Картинку рисуете вы.
profile.smdp_addressstringнет—
refreshedbooleanнетТолько у usage-refresh. false: отдано сохранённое значение (обновляли меньше минуты назад или спрашивать провайдера пока не о чем)
settled_atstringнет—
statusstringдаprocessing | active | exhausted | expired | needs_review | failed | refunded
usageEsimUsageDTOнет—
usage.activated_atstringнет—
usage.data_remaining_gbstringнетПоследнее показание. Обновить — POST /esim/orders/{id}/usage-refresh.
usage.data_total_gbstringнет—
usage.expires_atstringнет—
usage.unlimitedbooleanда—

Примеры ответа

{
  "id": "7e6d5c4b-3a29-4180-9f7e-6d5c4b3a2918",
  "operation_id": "c1d2e3f4-a5b6-4c7d-8e9f-0a1b2c3d4e5f",
  "external_id": "order-1001",
  "status": "processing",
  "operation_status": "processing",
  "price_usd": "5.26",
  "package": {
    "id": "5b2f7c1a-3d4e-4f60-8a71-9c0d1e2f3a4b",
    "title": "Turkey · 5GB 30 days",
    "region_code": "TR",
    "region_name": "Turkey",
    "countries": [
      "TR"
    ],
    "data_gb": "5",
    "unlimited": false,
    "validity_days": 30,
    "network": "4G/5G",
    "has_5g": true
  },
  "usage": {
    "data_total_gb": "5",
    "unlimited": false
  },
  "created_at": "2026-10-07T09:13:02Z"
}
{
  "title": "Payment Required",
  "status": 402,
  "detail": "partner_balance_exhausted",
  "errors": [
    {
      "message": "balance_exhausted",
      "location": "error.code",
      "value": "balance_exhausted"
    }
  ]
}

Ошибки

HTTPКодКогда
402balance_exhaustedДоступного баланса (available) не хватает на операцию. Пополните счёт.
404esim_package_not_availableПакет eSIM неизвестен, снят с продажи или сейчас недоступен. Возьмите актуальный из GET /esim/packages. Деньги не двигались.
404esim_price_below_costЦена пакета по вашему eSIM-тарифу не выше нашей себестоимости — покупка отклонена до резерва, деньги не двигались. Повтор не поможет; напишите нам, мы поправим тариф.
404tariff_not_availableeSIM для вашего аккаунта не включён.
409idempotency_conflictЭтот Idempotency-Key уже использован для другой покупки (другой пакет или другой external_id), либо external_id уже занят другой операцией.
422amount_above_limitЦена пакета выше лимита на одну операцию для вашего аккаунта.
422—Нет заголовка Idempotency-Key или обязательного поля.
429daily_issue_limitДостигнут лимит покупок eSIM за последние 24 часа: по числу покупок или по сумме в USD, если для аккаунта задан суточный потолок.
503maintenanceТехнические работы на этом направлении. Деньги не двигались — повторите позже с тем же Idempotency-Key.

Плюс общие ошибки подписи и лимитов — см. Ошибки.