Orders
Create an order
Create a new eSIM order
POST
Authentication
This endpoint requires HMAC-SHA256 signature authentication. See Authentication guide for details.Using the playground
Using the playground
The playground below cannot sign for you. It sends whatever you type, and
this endpoint rejects anything unsigned — so filling in a body and pressing
send returns
401. That is the endpoint working, not a fault.To use it, generate the signature elsewhere and paste it in:- Build the signature over the exact body string you are about to send — copy it out of the playground first, or paste a body you have already hashed.
- Paste the result into
X-Esim-Story-Signature, with the same timestamp you signed with inX-Esim-Story-Timestamp. - Send within 5 minutes of that timestamp, and do not edit the body afterwards — either one invalidates the signature.
Headers
string
required
Your partner access key. Used for authentication.
string
required
HMAC-SHA256 signature of the request. Generated using your secret key. See
Authentication guide
for signature generation details.
string
required
Unix timestamp in seconds (UTC). Must be within 5 minutes of server
time, in either direction.
Request body
string
required
Your order identifier in your system. Must be unique within your partner
account. Re-sending the same value is safe — see
Idempotency.
array
required
One entry per product you want to order.
One order carries at most 100 eSIMs in total, counted across every entry —
there is no separate limit on how many entries or destinations you combine.
Split a larger batch across several orders, each with its own
external_order_id. Contact support if your volume needs a higher ceiling.Get
option_id values from List products, which
always carries the current catalogue and your price. Only option_id and
qty go in the payload — there is no field to override the country,
duration or data allowance.Response
A successful request returns201 Created.
201 means the order was accepted and provisioning was requested. It does not
contain the eSIM. That arrives later, one delivery per unit, on your
webhook.
array
required
One entry per unit ordered — a product with
qty: 2 produces two entries.Webhooks
The eSIM is not in this response. Once each unit is issued, it arrives as its own signedPOST to your webhook URL — see Webhooks for
the payload, retries, and how to verify the signature.
Idempotency
external_order_id is the idempotency key. It is unique per partner account,
and re-sending a request with an external_order_id you have already used is
safe:
- If the order exists but no eSIMs were issued yet (a previous attempt failed during provisioning), provisioning is retried and no duplicate order items are created.
- If the order was already fully provisioned, the original
topup_idvalues are returned unchanged. No second eSIM is issued and you are not charged twice.
422 provisioning failures and 5xx responses safe to retry
verbatim. Always retry with the same external_order_id — generating a new one
will create a genuinely new order.
In sandbox
Testing provisioning failures
Sandbox issues an eSIM for every order, so a provisioning422 never occurs there on its own. To exercise your error handling, start the external_order_id with one
of these:
It is a prefix match, so append your own suffix to keep each test order unique —
SANDBOX-FAIL-001, SANDBOX-FAIL-002, and so on.
These prefixes do nothing in production. An order sent there with a name
beginning SANDBOX-FAIL is provisioned normally.
The simulation reproduces the aftermath, not just the status code. As in
production, the order and its items are created before provisioning is
attempted — so a simulated failure leaves an order that exists with no
topup_id, and retrying it with the same external_order_id succeeds and
issues the eSIM. That fail-then-retry sequence is the part worth rehearsing:
it is what a real provider outage looks like from your side.Errors
400 Bad Request
The request body could not be parsed as JSON. Theerror value is the raw
parser message and its exact wording is not stable — do not match on it.
- Malformed or truncated JSON in the request body
- Missing or empty request body
401 Unauthorized
Authentication failed. The body is always this shape:Invalid signature. is the one worth debugging carefully — the
Authentication guide lists its causes in
order of likelihood, and a test vector to check your signing code against.
422 Unprocessable Entity
Validation or provisioning errors. The body always has anerrors array of
strings.
Invalid request payload — the order is rejected before anything is created,
so nothing is charged and no order record exists:
A single invalid entry rejects the whole request — products are never partially
ordered.
Provisioning failed — the eSIM could not be issued. Four variants, told
apart by their prefix. All four are retryable with the same
external_order_id:
A
422 from provisioning means the order record was already created but no
eSIM was issued. Retry with the same external_order_id — the retry is
idempotent and will not create a duplicate order. See
Idempotency. A 422 from payload validation creates nothing,
so fix the payload and send it as a new request.429 Too Many Requests
Rate limit exceeded. Check theRetry-After response header (in seconds) before retrying. See Rate Limits.
500 Internal Server Error
Returned for unexpected server-side failures. The response body is not guaranteed to be JSON — do not parse it. Treat any5xx as retryable with the
same external_order_id.
Debugging by symptom
The tables above are indexed by status code. This one is indexed by what you actually see first, including the two failures that return no error at all.Last modified on October 28, 2026