Node and React quickstart
This page gets the Monaiq client installed and authorized in a Node application, and points at the React and assertion pieces that build on it.
The package is @sidub-inc/licensing-client. It is written in TypeScript and works in plain Node
and in React.
Install
Section titled “Install”npm install @sidub-inc/licensing-clientConfigure and get an authorization
Section titled “Configure and get an authorization”import { LicensingClient } from '@sidub-inc/licensing-client';
const client = new LicensingClient({ licenseServiceUri: 'https://api.monaiq.com/licensing', encodedCredential: process.env.MONAIQ_CREDENTIAL // SIDUB_LIC_...});
const authorization = await client.getAuthorization();licenseServiceUri is the licensing API and is required. getAuthorization() returns the
authorization for the credential you configured, which is what tells you what this customer is
licensed for.
Identifying yourself
Section titled “Identifying yourself”You have two ways to give the client a credential, and you pick one:
encodedCredential, the portable string startingSIDUB_LIC_that carries everything in one value. This is the simpler option and the one above.- The parts separately:
seatId,serviceKeyId,serviceKeyPublicMemberandruntimeToken. Use this when your configuration already holds them individually. They are the same four values the encoded string carries.
Either way the client calls the runtime operations — {licenseServiceUri}/runtime and
{consumptionServiceUri}/runtime — and presents the runtime token as Authorization: Bearer. It
appends /runtime itself, so set licenseServiceUri and consumptionServiceUri to the plain
addresses. The token is opaque: never decode, parse or display it.
Other settings
Section titled “Other settings”The constructor also accepts consumptionServiceUri and billableResourceId for
metered features, covered in Consumption and metering, plus timeout,
validateSignatures, cacheEnabled and cacheMaxSize. The
Node client reference lists them with what each one does.
In React
Section titled “In React”The package ships React bindings on top of the same client: LicensingProvider puts a licensing
context into your component tree, and useLicensingContext reads it from a component. It is the
same client underneath, so nothing you learn here is wasted when you move from a script to a
component tree. See Node client reference.
Selling from inside your app
Section titled “Selling from inside your app”The same package carries a second client, PurchaseClient, for an application that sells your
own offerings to the person using it. It is separate from LicensingClient on purpose: nothing
about it needs a credential of yours.
- The catalog reads are anonymous.
listOfferings(issuerClientId)returns your storefront ashttps://monaiq.com/marketplace/{issuerClientId}shows it, andgetOffering(issuerClientId, offeringId)returns one offering’s review with the features it grants, so the app never bakes in an offering id. - Checkout is the buyer’s. Your app signs the buyer in with their Monaiq identity and gives the
client a
getAccessTokenfunction;createCheckoutsends that token, and the license is minted for the buyer. There is no API key and no customer email on this path, so no secret of yours ships in the app.
import { PurchaseClient } from '@sidub-inc/licensing-client';
const purchase = new PurchaseClient({ purchaseServiceUri: 'https://api.monaiq.com/purchase', getAccessToken: () => acquireBuyerToken() // MSAL or native auth in your shell});
const requestId = crypto.randomUUID(); // keep it: a retry must send the same idconst session = await purchase.createCheckout({ requestId, offeringId, issuerClientId });
if (session.sessionUrl) { await openInSystemBrowser(session.sessionUrl); // paid: the hosted Stripe Checkout page}
const result = await purchase.pollResult(session.sessionId);// result.encodedCredential is the buyer's SIDUB_LIC_... credentialA paid offering returns a Stripe Checkout URL to open in the system browser; a free one completes
at once with no URL. Poll the result either way rather than waiting for a redirect, and pass
originContext: 'mobile_app' from a mobile shell. Failures are LicensingError values with the
server’s code (BuyerTokenInvalid, CheckoutResultForbidden, RequestIdInUse and so on) and
correlationId.
The Node client reference lists the client’s methods and their errors.
Assertions
Section titled “Assertions”Rather than reading an authorization and writing your own conditionals, you can express the condition as an assertion. The package ships six:
ServiceAccessAssertionFeatureExistsAssertionRateLimitAssertionQuotaAssertion, for an allowanceCompositeAssertion, which combines other assertionsNotAssertion, which negates one
RateLimitAssertion is the one to reach for when a feature is rate limited; see
Consumption and metering.
Getting the calls written for you
Section titled “Getting the calls written for you”If you would rather not wire the call sites by hand, the AI-assisted path returns the base wiring and a feature check for your own project, and can plumb the credential in for you. See AI-assisted setup.
- Credentials and keys for minting and rotating
MONAIQ_CREDENTIAL. - Endpoints for the addresses used above.