Simulators
PayPal changelog
What changed in each PayPal simulator release, newest first.
v0.0.10 — 2026-11-06
- The docs link the live feed and keep PayPal’s own boot note. The connect section sends you to the live feed when no requests arrive, and the scenario limits state only the scenarios this simulator does not ship.
v0.0.9 — 2026-11-05
-
Setting the clock never stamps records before the timeline events it fired. When
POST /_rystic/clock {"time": ...}fires timeline events due at its target, the next request’s records stamp after theirs instead of reusing their instant; a set past every event still stamps one millisecond past its target, as before. -
A paced clock keeps wall time, and
rystic run --speed 0stops it. UnderRYSTIC_PACE, each tick moves the clock by the wall time that passed since the last, so a tick missed while the twin was busy no longer makes timeline events fire late.rystic runhands the twin only the pace it resolved, so--speed 0, a scenario without events,--tapeand--livekeep the clock manual even when your shell exportsRYSTIC_PACE. -
Swagger UI to read and call the twin from the browser.
/_rystic/swagger, linked from the state UI header, is Swagger UI over the published API trimmed to the operations this twin serves; Try it out sends each request to the twin. -
A request with no credential is refused on every route, as PayPal refuses it. The twin answers before it reads the path or body: 401
AUTHENTICATION_FAILUREon the payment routes, 401invalid_clienton both token routes, and the empty 404 five of the measured-refusal routes answer either way.DELETE /v2/checkout/orders/{id}now answers 401AUTHENTICATION_FAILUREwithout a bearer, where it answered 405; send a placeholder bearer on every request. -
A slow client no longer holds up the others. The simulator reads a request’s whole body before it starts serving it and sends the answer after, so a client that uploads slowly, or reads a large answer slowly, no longer delays other clients’ requests. Answers are unchanged; one larger than 4 MiB still makes other requests wait while it is sent.
-
The call log shows what each call asked for and whether it succeeded. Each
GET /_rystic/callsentry now carriesargs, the call’s query and body arguments with credentials redacted (long values cut, file contents left out), andok, false for an answer that is not 2xx. A path the simulator does not serve is markedunknown_route: true.?tail=Nreturns only the last N calls, anddroppedcounts the calls the log no longer keeps. -
The docs are one page, with a page per feature. The archive ships
README.mdin place ofHOWTO.md, with the same sections in the same order as every Rystic simulator’s page, andCHANGELOG.mdbeside it. The payment lifecycle and the PayPal Business UI each have their own page underdocs/features/, and every example on these pages runs as written against a fresh simulator. -
The Scenarios table is easier to scan. Each row says in a line what the scenario is for, and a list below the table says what each scenario holds.
-
Pro starts with a 14-day trial. Free has ended, so every simulator is on Pro and Enterprise, and the docs name only those plans.
-
Limitations is shorter to read. It opens with the known issues and one sentence counting the rest. The detailed lists follow, and the website folds them behind “Show all limitations”.
-
The page has no Plans section. The Quickstart names the plans that run the simulator, and the pricing page lists what each plan includes.
-
The docs read more plainly, and they mark differences from PayPal. Sentences are shorter, and “Differs from PayPal” marks where the simulator departs from PayPal’s sandbox, such as its credential checks, webhook delivery, the void event, the capture fee and the return after a buyer approves. Rules with several outcomes, such as auth, the routes that refuse requests, the recorded events and the scenario’s timeline, are tables. The main page keeps to this simulator’s own credentials, registers, ids and clock, and links the shared pages for seeding and reset.
v0.0.8 — 2026-10-12
-
A world can carry its own timeline. A
--seedfile, or a complete world document posted toPOST /_rystic/seed, may addcredentials, binding presented credentials to actors, andevents: calls the twin makes on its own API at set sim times as one of those actors, through the same handlers and egress as your requests. A top-levelcredentialsoreventskey the twin used to ignore now takes effect.RYSTIC_PACE=<speed>plays the clock, and the timeline, in real time, and an event’satmay be+<duration>./_rystic/inject,--injectandRYSTIC_INJECTnow needstate_setinstead ofscenarios. -
A timeline call can hand what it minted to later events. A
callevent may addbind,{"<name>": "<JSON Pointer>"}, saving fields of its answer, such as an ID the twin minted; a later event uses one as${name}in a call’s path, headers or body or in a seed event’s record keys and values (a register name cannot be bound). A schedule naming a${name}no earlier call binds is refused at load, and an event whose binding call failed records an error instead of firing. -
design_studiocarries a timeline. As the clock moves past2026-03-01T00:00:00Z, the world opens an order for Wildflower Daycare’s open invoice, charges Oakridge Bakery’s saved wallet for its hosting renewal, refunds 500.00 of Saltmarsh Brewing’s deposit, and authorizes then captures Quill and Ink Stationery’s March care plan, each a call on the twin’s own API under the world’s bound tokens. Those calls take the first order, capture and authorization IDs, so a test that advances the clock before creating its own sees its IDs minted later in the sequence. -
A clock jump fires each timeline event at its own time. When one
POST /_rystic/clockor paced tick passes several events, each fires with the clock at itsat, so the records it creates carry that time, and the clock then lands where the move asked. An event already due when the clock moves fires at the current time. -
A clock jump stamps each timeline event at its exact instant. When a clock move passes timeline events, the records each one makes carry exactly its
at, to the millisecond, whatever traffic came before it, so one jump leaves the same records as stepping the clock to each event in turn. -
A timeline call can carry raw bytes, XML or a JSON array. A
callevent may sendbody_textorbody_base64instead ofbody; the twin sends it as written, under the route’s own content type (XML, bytes, JSON or a form), so a scheduled call can upload an object’s bytes or post an XML document, and${name}fills inbody_text. Abodymay be a JSON array where the route reads one. A call that answers XML binds from its elements by JSON Pointer, such as/InitiateMultipartUploadResult/UploadId.
v0.0.7 — 2026-10-11
-
check.shfails fast on a port that never answers. Its port check and boot wait give each/_rystic/versionprobe two seconds, so an address where something accepts connections but never replies fails the check with a message instead of hanging. -
Every link the twin hands out leads back to the twin. An order’s, authorization’s, capture’s or refund’s
links[].hrefand an error’sinformation_linknow carry the origin you reached the twin on, with PayPal’s path kept, so a client that followsself,captureorrefundcalls the twin rather than PayPal with its token. A buyerapprovelink and a documentation link now answer 404 from the twin; a twin started withrystic run --interceptkeeps PayPal’s hosts in its links, whichrystic execroutes to the twin. -
The order read accepts your client ID and secret.
GET /v2/checkout/orders/{id}now answers HTTP Basicclient_id:secretas the sandbox does, beside a bearer token; the other payment routes still answer Basic with 401. -
The guide lists what the twin serves and what it does not, from the model.
HOWTO.mdand the docs page now carry the served operations and the known gaps generated from the twin’s model and its open issues: the spec operations not served, the branches the fidelity suite does not measure, what the model leaves out, and the known differences from the sandbox. -
The scripts in this archive are MIT-licensed.
check.shand the archive’s other scripts are published under the MIT License at https://github.com/Rystic-Inc/rystic-scripts , so you can copy, change and share them.LICENSE.txtno longer covers them; it still governs the twin itself.
v0.0.6 — 2026-09-30
-
PayPal-Debug-Idkeeps its spelling. A 404 on an authorization, capture or refund read now sendsPayPal-Debug-Idinstead ofPaypal-Debug-Id; the value still repeats the body’sdebug_id. -
The state UI shows the account as PayPal Business. On Pro and Enterprise,
/_rystic/uiopens a live PayPal Business-style view of the twin — Home with a derived balance, Activity with gross, fee and net, and each transaction’s details — where you can refund captures, capture or void authorizations and capture approved orders through the API, approve a waiting order as a chosen buyer, and watch your integration’s calls, the egress events, stored request IDs and OAuth tokens.
v0.0.5 — 2026-09-26
- The guide starts from an API key, says what each plan reaches, and documents the payment events.
HOWTO.mdnow opens withrystic login rys_…, says what Free, Pro and Enterprise boot and which control-plane routes each answers, states which routes check a bearer token (and which seven refuse a minted token marked expired), and corrects the claim that the twin emits no webhook events: authorization capture and capture refund writePAYMENT.CAPTURE.COMPLETEDandPAYMENT.CAPTURE.REFUNDEDtoGET /_rystic/egress, and authorization void writes the twin’s ownauthorization_voidedrecord.SCENARIOS.mdsays what each plan boots.check.shfinds the API keyrystic loginstored as well as a license file, looked up in the CLI’s order, andrystic featuresmarks the features and commands that need Pro or Enterprise.
v0.0.4 — 2026-09-26
- Only
design_studioships as a named scenario. The older scenarios are now test-only fixtures and are no longer accepted by--scenario,RYSTIC_SCENARIO, orPOST /_rystic/scenario. Tests and evaluations can load their unchanged register maps and clocks fromsim/testdata/scenarios/through the control plane.
v0.0.3 — 2026-09-25
-
A new world,
design_studio, now the default.--scenario design_studioboots Website Design Contractors’ business account: 57 completed orders, one per invoice its eight PayPal clients paid, each with its capture,invoice_idthe studio’s invoice number andcustom_idthe client, the same invoices the studio’s Slack, Resend and Stripe worlds name. A lease that grants no scenarios boots it. -
The HOWTO now names what the twin does not do. Its scope section lists the six measured-refusal routes with their status codes, that there are no list routes, and that webhooks, bearer verification, asynchronous settlement and token expiry are not modeled; the worlds section documents
GET /_rystic/scenariosandPOST /_rystic/scenariofor switching worlds without a restart.
v0.0.2 — 2026-09-24
-
More accurate authentication errors. Requests without credentials now return PayPal-compatible 401 responses before resource lookup across checkout and payment endpoints. OAuth token requests with a missing or unsupported grant type return the corresponding
unsupported_grant_typeerror.Order validation and replay. Multiple purchase units require reference IDs. PATCH rejects removal of required amounts, empty purchase units, unsupported moves, invalid currencies, and missing reference selectors without changing state. Order reads reject XML-only response requests. Replayed order creation returns the current order after a successful PATCH.
-
Complete PATCH validation errors. Invalid order updates now report structural errors in request order, including repeated errors, before applying changes or validating amount values. Replacing the entire purchase-unit array is rejected. Failed compound updates preserve the original order and payment state.
-
USD refunds retain the original capture processing fee instead of returning a prorated amount. Ordinary USD refunds report zero PayPal fee and net equal to gross, including partial refunds and the final remainder. Replays preserve the stored refund and do not move money again.
Direct-card creation and order capture use the existing synthetic USD capture policy already used by authorization capture and scenario seeds: 3.49% plus USD 0.49, rounded to cents. This is deterministic simulator pricing, not a claim about a merchant’s current PayPal rate. Non-USD capture pricing and platform-fee return rules are unchanged and are not newly validated.
v0.0.1 — 2026-09-24
- Exercise PayPal checkout, authorizations, captures and refunds locally with twelve payment-history worlds, deterministic reset and clock control, validated retries and error contracts, and a packaged installation check.