Already using React? Install
@elapse/react and compose <Authorize> and
<Meter> yourself, so your app ships one copy of React instead of two.Your server does not change
Everything before the page is the same for every language. Follow the Quickstart — it has a cURL tab beside every call, so creating the Product, creating the Checkout session and handlingsubscription.canceled work in Python, Go, Ruby, PHP or anything
that speaks HTTP. Your secret key stays there, where it belongs.
Only the Quickstart’s last step — rendering the meter — is written in React. This page is that step
in your stack instead.
Your page
Thecs_… session id is created per subscriber by your server, so the page asks for one when the
subscriber starts:
mount renders the authorisation step, opens the signing window, and
replaces itself with the live meter when the subscriber accepts.
The build carries its own React, react-dom and motion (~65 KB gzipped), so you install nothing and
your framework never sees them.
Options
A second
mount on the same element replaces the first rather than stacking.
Which of the two fires
onAuthorised and onStarted are alternatives, not a sequence. Exactly one of them fires when the
subscriber signs, and which one is decided by the Product’s start_mode:
Merchant mode exists for a resource that has to be ready first — a container to boot, a runner to
warm, a stream to open. You do that work, then call
subscriptions.start from your server, and the
meter begins. Until you do, the subscriber is charged nothing; a session you never start is
cancelled and refunded in full after fifteen minutes.
So a checkout-mode integration listens for onStarted, and a merchant-mode one listens for
onAuthorised and starts the meter itself. Passing both, as above, is the safe default while you
are deciding.
Where access is really decided
onStarted and onStopped are for your interface — reveal the product, hide it again. They are
browser callbacks, so they are not proof of anything: a closed laptop fires no callback, and
neither does a tab that crashed.
Entitlement belongs on your webhook endpoint, where subscription.created and
subscription.canceled arrive signed from Elapse. Grant on one, revoke on the other, and verify
the signature before you parse the body. Signatures has the scheme and a
test vector; the events catalogue has every payload you can receive.
While you are building, elapse listen --forward localhost:3000/webhooks delivers them to your
laptop with no tunnel.
Pause and Resume
LeaveonPauseRequest and onResumeRequest out and the meter shows no such buttons.
Pass them and it shows both — as requests to you. Nothing is signed in the browser and nothing
reaches Elapse from it. Your server answers by calling subscriptions.pause and
subscriptions.resume, and the meter follows once the change confirms. Paused seconds are never
billed.
The subscriber never gets a Stop button for a meter you started; stopping it stays yours, through
whatever control your own page offers. Subscriptions has the rule.