WeTransact external API sandbox ================================ This sandbox runs the production external-API code over an in-memory database; only Microsoft is faked. Authenticate every /api and /sandbox call with header x-api-key: . Seeded subscriptions 11111111-1111-1111-1111-111111111111 NXT AP Intelligence (flat rate, no dimensions) 22222222-2222-2222-2222-222222222222 NXT AP On Demand (six metered dimensions ap_transaction_t1 .. ap_transaction_t6) Endpoints GET /api/v1.0/subscriptions?includeMeters=true (includeMeters=true lists metered subscriptions only, as in production) GET /api/v1.0/subscriptions/{id}?includeMeters=true POST /api/v1.0/subscriptions/{id}/actions/charge?dimensionId=&quantity=&effectiveStartTime= GET /api/v1.0/financials GET /api/v1.0/usage?subscriptionId=&from=&to= (what "Microsoft" accepted, aggregated per dimension per day) POST /sandbox/reset (forget every charge) Charge semantics (production code) Dedupe key = (subscription, dimension, hour of effectiveStartTime). Only ACCEPTED reports block locally; the fake Microsoft dedupes on the same key and answers Duplicate, exactly like the real one. 200 accepted | 400 bad input | 404 unknown subscription/dimension | 409 already reported this hour 422 Microsoft rejected | 429 throttled | 502 Microsoft unreachable (retryable=true, outcome unknown) Fault injection: header X-Sandbox-Outcome: (case-insensitive; unknown values answer 400) Transport / WeTransact side unavailable -> Microsoft never reached: 502, Retryable=true, no verdict. Retry lands (200). lost -> Microsoft ACCEPTED but the response was lost: 502, Retryable=true. Retry with the same effectiveStartTime answers 409 Microsoft.Status=Duplicate. A retry loop must survive this. throttled -> forced 429, empty body. The production concurrency limiter (10 in flight, 5 queued) also runs here, so a real burst of parallel charges gets real 429s too. Microsoft verdicts (relayed under Microsoft.StatusCode / Microsoft.Status / Microsoft.Message) duplicate -> 409 Duplicate Microsoft had already accepted this hour; stays 409 on retry resource-not-found -> 422 ResourceNotFound unknown resource / subscription at Microsoft resource-not-authorized -> 422 ResourceNotAuthorized (Microsoft 403) publisher not allowed for this resource resource-not-active -> 422 ResourceNotActive subscription suspended or not yet activated (alias: rejected) invalid-dimension -> 422 InvalidDimension dimension not in the plan (Microsoft: BadArgument + details) invalid-quantity -> 422 InvalidQuantity quantity <= 0 (Microsoft: BadArgument + details) bad-argument -> 422 BadArgument malformed request expired -> 422 Expired effectiveStartTime older than 24h at Microsoft server-error -> 502 InternalServerError Microsoft 5xx; Retryable=true, resend the same hour Without the header the fake accepts (200) unless it already accepted that hour (409 Duplicate). Deployment: one instance only (state is in memory); SANDBOX_API_KEY is mandatory outside Development. Reset is not atomic with charges still in flight: let your calls finish before you call /sandbox/reset.