SIMWAY
Partners

Sandbox

Same base URL, same routes, same request and response shapes — the integration is byte-identical and only the credential differs. What sandbox adds is four plans that force the failures you cannot otherwise rehearse, which is the part that actually decides whether your integration survives contact with production.

Getting in

A key beginning simway_sk_test_. Ask for one at [email protected]. It arrives with $1,000 of float already on it, and staff can refill it on request.

The float is not money. It appears in no financial figure, it moves no statement row, and nobody invoices you for it.

The four fixture plans

Their plan ids are fixed strings rather than generated ids, precisely so they can be pasted out of this page. All four are priced identically — $19.90 list, 5 GB, 30 days — so you see plausible money and the same three price fields production will give you.

pl_sandbox_insufficient_balance
A 402 that binds its idempotency key.

Always refused with 402 balance.insufficient whatever your sandbox balance is, and refused AFTER the order row is inserted — so the idempotency key binds to the refusal exactly as a real 402 does. This is how you test the rule that a topped-up partner must retry with a new key.

pl_sandbox_supplier_error
Total failure after acceptance, and the automatic refund.

Accepted with 202, then fails provisioning. The order reaches failed with failure_code "supplier_error" and the whole amount is back on the balance. It settles on the first pass rather than spending the five-attempt budget — a failure we were asked to produce will not succeed on the fourth try.

pl_sandbox_slow
A run that outlives your HTTP client.

Completes after 45 seconds, chosen against the 30-second default timeout in most HTTP clients. It is how you prove your retry is safe before a real retry double-charges someone.

pl_sandbox_partial
Some units delivered, some refunded.

Delivers every unit but the last. At quantity 3, two profiles arrive and one does not, so the order settles partial with a one-unit refund. At quantity 1 the single unit IS the last one, so the order fails outright — there is no partial delivery of one profile.

Any other plan ordered with a sandbox key provisions normally after 1.5 seconds — deliberately not instantly, so you cannot ship an integration that has never once handled processing.

What to rehearse, in order

  1. The happy path. Any real plan. Confirm you handle processing and only deliver on a terminal state.
  2. A slow order. pl_sandbox_slow completes after 45 seconds, chosen against the 30-second default timeout in most HTTP clients. Let your client time out and then retry with the same idempotency key. If you get one order back, you are safe. If you get two, you would have double-charged a customer in production.
  3. A supplier failure. pl_sandbox_supplier_error. Confirm your code reads failure_code off the order rather than expecting an HTTP error, and that you notice the refund.
  4. A partial delivery. pl_sandbox_partial at quantity: 3. Two profiles are yours to deliver; one unit’s money is back. This is the case most integrations get wrong, because it is neither success nor failure.
  5. Running out of money. pl_sandbox_insufficient_balance. Confirm you mint a new idempotency key after topping up, because the old one is bound to the refusal permanently. Then send the old key again and watch it return the same 402 — that is the behaviour to design around.
Forcing the 402
curl -X POST 'https://api.simway.pro/partner/v1/orders' \
  -H 'Authorization: Bearer simway_sk_test_ExampleKeyDoNotUse0000000000000000000000000' \
  -H 'Idempotency-Key: 8f3c2a1e-7b64-4d59-9e02-1c5a7f8b3d20' \
  -H 'Content-Type: application/json' \
  -d '{
  "plan_id": "pl_sandbox_insufficient_balance",
  "quantity": 1
}'

What the synthetic profiles look like

Every property here is a decision about what a sandbox artefact should do when it escapes into a real system — because one eventually will.

PropertyValueWhy
ICCID89999…, 19 digits, Luhn-validYour own format validation passes, so you are testing your code and not our fixture. The prefix sits in an ITU-reserved private-network range, so it collides with no real operator.
SM-DP+sandbox.simway.proA host we own that can issue nothing. A sandbox code pasted into a real handset fails at DNS rather than reaching somebody else’s SM-DP+.
Matching idSB-…The tell in a support ticket. Someone will paste one at you eventually.
Activation codeA real LPA:1$… stringBuilt by the same concatenation the live path uses, so one parser handles both.
QR codeA real scannable PNG data URLSame size and quiet zone as live, so your rendering and print layout are tested properly.

Every way sandbox differs from live

The complete list. Nothing else differs.

#Difference
1No supplier is ever called, and no real money moves anywhere.
2Spend comes off the sandbox float, and GET /balance reports that number.
3GET /ledger is ALWAYS empty. Sandbox writes no statement rows, so you cannot exercise statement or reconciliation code here.
4balance_after_cents on a later read of a sandbox order is the CURRENT float, not the balance as it stood after that order — there is no ledger row to read it back from. The exact figure is only on the 202 itself.
5The sandbox rate band applies regardless of your tier.
6The four fixture plans are visible. A live key can never see or order them.
7Sandbox keys keep working while an account is suspended.
8The forced-failure fixture settles on the first pass rather than spending the 5-attempt budget — so you do not wait 8 minutes to see a failure you asked for.
9Prices and margins are real arithmetic on real-looking numbers. The discount and floor logic is identical code.
10Fixture plans carry no country code and are global, so they never appear in GET /destinations.

What you cannot test here

  • Statement rendering and reconciliation. There are no ledger rows in sandbox. Plan for this: it is the one piece of work that only gets exercised after you go live.
  • Real supplier latency and real failure rates. The fixtures produce the shapes, not the distribution.
  • A profile that actually connects. The synthetic SM-DP+ issues nothing.
  • Deposits. The rail is live-mode only, and it refuses a sandbox key in three distinguishable ways: POST /deposits answers 403 forbidden carrying mode: "sandbox", GET /deposits always answers an empty page, and GET /deposits/{id} answers 404 for every well-formed dep_ id — the id is parsed before the mode is consulted, so a wrong-kind id is still the ordinary 400 naming id. Sandbox spend comes off the play-money float, which is refilled on request — a sandbox key that could open an invoice would be sending real cryptocurrency to exercise a code path.

Switching to live

Change the key. That is the whole migration — same base URL, same routes, same shapes. What changes on our side is that money becomes real and a supplier gets called.

The go-live checklist.