API reference
Bulk API
Buy up to 50 eSIMs of one plan on behalf of a business. The call takes payment, returns 202, and provisions in the background. Read the result from the status URL. Keys are issued after a conversation — there is no self-serve signup.
Authentication
Send Authorization: Bearer <api key>. The key must be active, belong to vigxo, and have the bulk scope. A missing key is 401. A revoked or unknown key is 401. Any other key is 403.
Limits
- At most 50 eSIMs per call, all of the same plan.
- A daily and a monthly spend cap, in USD, may be set on the key. A null cap means no limit of that kind. Caps use UTC day and UTC month.
- Prepaid balance is the business account linked to the key. The order is refused when the balance cannot cover the total.
Place an order
POST /api/v1/bulk/orders
planSlug is the slug from GET /api/plans. quantity is an integer from 1 to 50. contactEmail is optional and defaults to the address on the key. locale is optional and defaults to en. Traveler install emails use that locale. The summary email to the operator is always English.
Travelers
travelers is optional. When you send it, it must contain exactly quantity objects of { name, email }. Each person receives their own one-tap install email, and the nickname on the eSIM is their name. The operator receives one summary listing every traveler and their install links. Without travelers, each install email goes to contactEmail (or the key's contact address).
A traveler is matched to a profile by position after the profiles are sorted by ICCID. A retry keeps the same person on the same profile.
Payment
Omit the Stripe fields to debit the prepaid balance. Or send exactly one of stripePaymentIntentId or stripeInvoiceId. The payment must already be succeeded or paid, in USD, for at least the order total. A payment already tied to another live order is rejected.
The prices in the status response are what the business was charged, in USD. A short or failed provision returns the missing units to the prepaid balance, including when the original payment was a card or invoice.
curl -sS -X POST https://vigxoesim.com/api/v1/bulk/orders \
-H "Authorization: Bearer $VIGXO_API_KEY" \
-H "Idempotency-Key: 4f0b1c2e-7a11-4d5e-9c3a-1b2d3e4f5a6b" \
-H "Content-Type: application/json" \
-d '{
"planSlug": "<slug from GET /api/plans>",
"quantity": 2,
"locale": "en",
"contactEmail": "ops@example.com",
"travelers": [
{ "name": "Ada Lovelace", "email": "ada@example.com" },
{ "name": "Grace Hopper", "email": "grace@example.com" }
]
}'Accepted response
HTTP/1.1 202 Accepted
{ "orderId": "…", "status": "pending" }Idempotency
Idempotency-Key is required, up to 200 characters. The same key and the same body return the original response and do not debit or provision again. The same key with a different body is 409. A key whose first request is still in progress is 409.
A 402 is stored on the key. After you add balance or raise a cap, send a new Idempotency-Key. Validation errors (400) are not stored, so you can correct the body and reuse the key. A Stripe reference that is not paid yet is also not stored.
Order status
GET /api/v1/bulk/orders/{orderId} with the same API key. Another key's order is 404.
curl -sS https://vigxoesim.com/api/v1/bulk/orders/$ORDER_ID \ -H "Authorization: Bearer $VIGXO_API_KEY"
status is pending, provisioning, fulfilled, partial, or failed. partial means some eSIMs are ready and the missing units were credited back. failed means none were delivered and the charge was credited back when a business account was linked.
The response fields are:
orderId,status,quantity,provisionedunitPriceUsd,totalUsd,refundedUsd,currencyesims[]:nickname,travelerEmail,iccid,qrCodeUrl,lpaString,smdpAddress,activationCode,dataTotalMb,expiresAt,status
eSIMs appear in this list only once an ICCID exists. Poll until status is fulfilled, partial, or failed.
Dashboard and refunds
Orders are attached to the business user on the key, so they show in that account's dashboard. When an order names more than one traveler, each eSIM can be resent to that traveler from the dashboard.
A full failure or a short delivery credits the prepaid balance automatically. A later refund of unused profiles cancels those profiles with our network partner and returns only the units that were not already credited. Installed profiles are not revoked and are not refunded: revoking a profile that is already on a phone does not return its cost. A customer refund is all-or-nothing while every profile is still unused. An admin can refund the unused portion of a partial order.
Error codes
| HTTP | code |
|---|---|
| 400 | validation, invalid_request, invalid_locale, travelers_mismatch, idempotency_key |
| 401 | Missing, unknown, or revoked API key |
| 402 | insufficient_balance, spend_cap, stripe_not_paid, stripe_amount, no_business_account, stripe_unavailable |
| 403 | This key cannot place bulk orders |
| 404 | Unknown plan, or an order that is not this key’s |
| 409 | idempotency_conflict, idempotency_in_progress, payment_already_used |