Skip to content

Sandbox testing ​

Summary: a sandbox key talks to the same API at the same URL and gets the same validation and the same error codes as production, but no order ever reaches a pharmacy, nothing ships and nothing is billed. Orders walk a simulated lifecycle that sends real, signed webhooks to your sandbox endpoints.

What is the same as production ​

  • Signing, rate limits and validation work exactly as in production.
  • Order checks and order create apply the same rules: missing prescriber details, the patient's sex, unknown or retired SKUs, ship-to states, duplicate order ids and idempotency all fail the same way, with the same codes. A body that passes in sandbox passes the same checks in production.
  • Webhooks are signed and retried the same way.

What is different ​

Sandbox
PharmacyNone. pharmacyId stays null and no pharmacy is ever contacted.
LifecycleSimulated: received, then routed at once, shipped about 30 seconds later, delivered about 60 seconds after that.
TrackingtrackingNumber is SANDBOX-<axiomOrderId> and carrier is SANDBOX.
BillingNothing is billed. GET /invoices and GET /billing/orders return empty lists.
Credit limitsNot applied. POST /orders/check lists credit_cap and exposure_cap in notChecked.
Clinic agreementsEnforced in sandbox by default only for partner-attested accounts. For e-signature accounts, sandbox orders for an unsigned clinic pass unless we switch enforcement on for your sandbox; ask us when you test that path. When the check is skipped, notChecked includes agreement.
DataSandbox orders, tickets, notices and idempotency keys are separate from production ones and invisible to production keys, and the reverse. A sandbox key never changes a real clinic. Enrolling a clinic with a sandbox key checks the request exactly as production does and records only the clinic's external_id, so later sandbox orders for it pass a partner-attested agreement check. Clinic updates, bank details and identity changes from a sandbox key are checked and answered with "saved": false, and a sandbox order never creates a clinic. A sandbox key sees and manages only sandbox webhook endpoints. Sandbox orders send no email to anyone at a clinic.

Because a sandbox order is routed almost immediately, the window to edit it (which needs received) is a fraction of a second, and the window to cancel it (which needs routed or earlier) is about 30 seconds.

A test plan ​

Work through these before you ask to go live. Each one is a request you should be able to send, and a response your code should handle.

ScenarioHow to cause itExpect
Happy pathA complete order to a state in the SKU's availableStates201, then order.status_changed for routed, shipped, delivered
Check refuses, no payment takenLeave out physician.phone and physician.addressCheck: wouldAccept: false with prescriber_incomplete. Your checkout must stop before payment.
Missing order details at createThe same body sent to POST /orders422 prescriber_incomplete with blockers
Unknown product"sku": "NOT-A-REAL-SKU"422 unknown_product, reason: unrecognised
State not coveredA state missing from the SKU's availableStates (and from every pharmacy's licences)422 ship_state_not_licensed or no_pharmacy_can_fill
Retry after a timeoutSend the same create twice with the same key and bodyThe same 201 both times, one order
Key reused for a different orderSame key, different body409 idempotency_key_reused
Header and body keys differChange only the body's idempotency_key400 idempotency_key_mismatch
Duplicate order idA new key, same partner_order_id409 partner_order_id_duplicate with the existing axiomOrderId
CancelCancel within about 30 seconds of create200, status: cancelled, and an order.status_changed
Cancel too lateCancel after it shows shipped409 order_not_cancellable
Bad signatureChange one character of the body after signing401 hmac_invalid
Clock skewSign with a timestamp 10 minutes old401 hmac_timestamp_skew
Webhook verificationChange the stored endpoint secretYour receiver rejects the next delivery
Webhook outageMake your endpoint answer 503 for a few minutesRetries arrive; the portal shows the attempts; replay works

Tools in the partner portal ​

  • Requests shows the requests your keys made that passed authentication, with their status and error code. A request refused during signing or the account checks (for example 401 hmac_invalid or 403 production_not_enabled) is not listed.
  • Deliveries shows each webhook delivery with its attempt count and its latest response code, and lets you replay one.
  • Go-live shows which go-live items are done.