{"openapi":"3.1.0","info":{"title":"Sīrū public developer sandbox API","version":"0.1.0","description":"Isolated synthetic customers and orders with Stripe test-card checkout. No real eSIM, payment, supplier or production OAuth access. Temporary sessions expire after two hours or service restart; all orders reset on restart. Not durable storage. Deployment origin is supplied at runtime."},"paths":{"/api/v1/sandbox/products":{"get":{"operationId":"listSiruSandboxProducts","summary":"List synthetic sandbox plans","description":"Public test-only plans, with amounts in euro cents. No production catalog, real payments or supplier fulfillment. This path exists only on the separate public developer sandbox deployment. Quotas and reset behavior are documented at that deployment's /docs. This is not a production endpoint.","tags":["Public developer sandbox"],"x-siru-sandbox":true,"security":[],"responses":{"200":{"description":"Synthetic test plan catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxProductList"}}}},"default":{"$ref":"#/components/responses/SandboxErrorResponse"}}}},"/api/v1/sandbox/sessions":{"post":{"operationId":"createSiruSandboxSession","summary":"Create a temporary synthetic customer session","description":"Sandbox only. No signup, personal information or production credentials. A secret Bearer token expires after two hours or a service restart. Synthetic records are held in bounded memory and reset on restart. Maximum 10 new sessions per minute per instance. This is not OAuth.","tags":["Public developer sandbox"],"x-siru-sandbox":true,"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"maxProperties":0}}}},"responses":{"201":{"description":"Temporary secret sandbox token; keep it private.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxSession"}}}},"default":{"$ref":"#/components/responses/SandboxErrorResponse"}}}},"/api/v1/sandbox/checkouts":{"post":{"operationId":"createSiruSandboxCheckout","summary":"Create a Stripe-hosted test-card checkout","description":"Sandbox only. Creates one synthetic EUR 1.00 order with an authoritative server amount. Use Stripe test cards, never a real card. Requires a sandbox session and stable Idempotency-Key. Reuse that key after timeouts. Concurrent retries share the same checkout; unknown outcomes use Stripe idempotency. No eSIM is provisioned. Ten orders per session, 100 new checkouts/hour per instance. A success redirect alone never marks an order paid.","tags":["Public developer sandbox"],"x-siru-sandbox":true,"security":[{"sandboxToken":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"Unique key per intended test order; reuse for retries.","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,100}$","minLength":16,"maxLength":100}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxCheckoutRequest"}}}},"responses":{"201":{"description":"Synthetic order with its Stripe test checkout URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxCheckout"}}}},"default":{"$ref":"#/components/responses/SandboxErrorResponse"}}}},"/api/v1/sandbox/orders":{"get":{"operationId":"listSiruSandboxOrders","summary":"Read this sandbox session's synthetic orders","description":"Sandbox only. Ownership is derived from the temporary Bearer token. No customer selector is accepted. A signed, correlated, test-mode Stripe webhook with matching amount and currency marks an order paid. No payment secrets, installation credentials, real customers or real orders are exposed.","tags":["Public developer sandbox"],"x-siru-sandbox":true,"security":[{"sandboxToken":[]}],"responses":{"200":{"description":"Synthetic orders owned by this sandbox session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxOrders"}}}},"default":{"$ref":"#/components/responses/SandboxErrorResponse"}}}}},"components":{"schemas":{"SandboxProductList":{"type":"object","required":["products","synthetic"],"properties":{"products":{"type":"array","items":{"$ref":"#/components/schemas/SandboxProduct"}},"synthetic":{"type":"boolean","const":true}}},"SandboxProduct":{"type":"object","required":["id","name","amount","currency","countryCode","synthetic"],"properties":{"id":{"type":"string","const":"sandbox-jp-1gb"},"name":{"type":"string"},"amount":{"type":"integer","const":100,"description":"Synthetic test amount in euro cents."},"currency":{"type":"string","const":"eur"},"countryCode":{"type":"string","const":"JP"},"synthetic":{"type":"boolean","const":true}}},"SandboxError":{"type":"object","required":["code","message","hint","docs"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string"},"docs":{"type":"string","const":"/docs"}}},"SandboxSession":{"type":"object","required":["token","tokenType","expiresAt","synthetic"],"properties":{"token":{"type":"string","pattern":"^siru_sandbox_[a-f0-9]{64}$","description":"Secret temporary sandbox credential. Never send it to production."},"tokenType":{"type":"string","const":"Bearer"},"expiresAt":{"type":"string","format":"date-time"},"synthetic":{"type":"boolean","const":true}}},"SandboxCheckoutRequest":{"type":"object","additionalProperties":false,"required":["productId"],"properties":{"productId":{"type":"string","const":"sandbox-jp-1gb"}}},"SandboxCheckout":{"allOf":[{"$ref":"#/components/schemas/SandboxOrder"},{"type":"object","required":["checkoutUrl"],"properties":{"checkoutUrl":{"type":"string","format":"uri","description":"Stripe-hosted test checkout. Never use a real card."}}}]},"SandboxOrder":{"type":"object","required":["id","productId","amount","currency","status","synthetic","createdAt"],"properties":{"id":{"type":"string","pattern":"^[a-f0-9]{64}$"},"productId":{"type":"string","const":"sandbox-jp-1gb"},"amount":{"type":"integer","const":100,"description":"Synthetic test amount in euro cents."},"currency":{"type":"string","const":"eur"},"status":{"type":"string","enum":["pending","paid","expired"]},"synthetic":{"type":"boolean","const":true},"createdAt":{"type":"string","format":"date-time"}}},"SandboxOrders":{"type":"object","required":["orders","synthetic"],"properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/SandboxOrder"}},"synthetic":{"type":"boolean","const":true}}}},"responses":{"SandboxErrorResponse":{"description":"Request rejected or sandbox temporarily unavailable; follow the resolution hint.","headers":{"Retry-After":{"description":"Seconds to wait before retrying a throttled request.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxError"}}}}},"securitySchemes":{"sandboxToken":{"type":"http","scheme":"bearer","bearerFormat":"siru_sandbox_<random-secret>","description":"Temporary synthetic-customer credential from POST /api/v1/sandbox/sessions. Expires after two hours or service restart. Accepted only by the isolated public developer sandbox, never by production. Not an OAuth access token."}}},"servers":[{"url":"https://public-sandbox-public-sandbox.up.railway.app"}]}