Reference

React SDK reference

The provider, components, props, labels, data types and errors of the React SDK, version 0.1.0-beta.0.

This page lists what @shiprev/react exports, the props each export takes and the values it can show or return. For a walkthrough, start with The React components; for what to show your end users, see Show it in your frontend and Self-service.

Version

This page covers version 0.1.0-beta.0, the version published on npm, installed with the beta tag (npm install @shiprev/react@beta). It is a beta: the interface may change before 1.0. New versions are listed in the changelog.

React 19 is the only peer dependency, and the package has no runtime dependencies. The entry module starts with 'use client', so a Next.js App Router page can import it directly: the components render their loading state on the server and read data in the browser. The stylesheet is a separate import, @shiprev/react/styles.css, and is optional; see Styling.

The components display and collect input only. Whether an end user may use a capability is ruled in your backend by the Server SDK.

Exports

ExportKindWhat it is
ShipRevProviderComponentSupplies the network settings and the look to every component below it
ShipRevProviderPropsTypeProps of ShipRevProvider
ShipRevAppearanceTypeThe appearance prop of ShipRevProvider
SignInFormComponentEmail and password sign-in
SignInFormPropsTypeProps of SignInForm
SignUpFormComponentAccount and organization sign-up
SignUpFormPropsTypeProps of SignUpForm
PricingTableComponentYour plans, with a subscribe or switch action each
PricingTablePropsTypeProps of PricingTable
SubscriptionPanelComponentThe organization's plan and period, with cancellation
SubscriptionPanelPropsTypeProps of SubscriptionPanel
UsageMeterComponentUsage of each capability in the current period
UsageMeterPropsTypeProps of UsageMeter
SignInLabelsTypeTexts of SignInForm
SignUpLabelsTypeTexts of SignUpForm
PricingTableLabelsTypeTexts of PricingTable
SubscriptionPanelLabelsTypeTexts of SubscriptionPanel
UsageMeterLabelsTypeTexts of UsageMeter
PublicPlanTypeA plan of your catalog
PublicPlanVersionTypeA published version of a plan
SubscriptionTypeThe organization's subscription
UsageSummaryTypeUsage of every capability of the organization, with its wallet balance
UsageSummaryItemTypeUsage of one capability
IssuedSessionTypeWhat sign-in and sign-up hand you
AccountProfileTypeThe signed-in account
ShipRevErrorClassA failed request

Data types keep the API's snake_case field names, because values pass between the API and your code unchanged.

Provider

ShipRevProvider supplies the network settings and the look to the components. Every component must be rendered inside a provider; outside one, rendering throws.

App.tsx
import { ShipRevProvider, UsageMeter } from '@shiprev/react';
import '@shiprev/react/styles.css';

export function App() {
  return (
    <ShipRevProvider apiBase="/shiprev" getAccessToken={getAccessToken} onUnauthorized={onUnauthorized} appearance={{ primaryColor: '#0f766e' }}>
      <UsageMeter />
    </ShipRevProvider>
  );
}
ShipRevProviderPropsTypeMeaning
apiBasestring, requiredA path on your page's own origin that your server forwards to your brand domain under /rest; requests go to apiBase followed by the endpoint's path, for example /shiprev/public/v1/usage/summary. It must start with a single / and contain no scheme, backslash or control character, otherwise rendering throws. Trailing slashes are ignored. See Forward a path on your own origin
getAccessToken() => string | null | Promise<string | null>, requiredCalled before every request that needs a session. Return the end user's access token, or null when nobody is signed in; the components then show their signed-out state without sending a request. A throw counts as null
onUnauthorized() => Promise<string | null>Called when such a request is answered 401. Return a renewed access token to send the request once more, or null to show the signed-out state; a throw counts as null. A second 401 is not retried, and concurrent 401s share one call. Without it, a 401 shows the signed-out state
appearanceShipRevAppearanceThe look of the components; see below
childrenReactNode, requiredYour interface, with the components anywhere inside it

The provider and the components store nothing: no localStorage, sessionStorage or cookie, and no token kept in memory. Every request is sent with credentials: 'omit' and an x-request-id header of the form rsdk_<uuid>, and never to another origin.

ShipRevAppearance

Each field becomes a CSS variable or attribute on the provider's root element, which has the class sr-root.

ShipRevAppearanceTypeBecomes
primaryColorstring--sr-color-primary
radiusstring--sr-radius
fontFamilystring--sr-font-family
colorScheme'light' or 'dark'The attribute data-sr-scheme; 'dark' switches the stylesheet's default colors

Props every component takes

Each component below also takes these three props, listed again in its table:

  • className: added to the component's root element, which always has the class sr-root.
  • labels: any subset of the component's texts, replacing the English defaults; see Labels.
  • onError: called with a ShipRevError once for each failed request, while the component shows its own error text. A missing session is not a failure: the component shows its signed-out state and does not call onError.

Sign-in form

SignInForm asks for email and password and sends POST /public/v1/auth/login. On success it calls onSignedIn once with the issued session, and keeps nothing.

SignInFormPropsTypeMeaning
onSignedIn(session: IssuedSession) => void, requiredReceives the session; store it where your application keeps its session
logoUrlstringShows this image above the title
productNamestringAdded to the title, and used as the logo's alternative text
forgotPasswordUrlstringShows a link to this address under the password field
signUpUrlstringShows a link to this address under the form
classNamestringAdded to the root element
labelsPartial<SignInLabels>Replaces texts
onError(error: ShipRevError) => voidCalled once for each failed request
AnswerText shown
401errorInvalidCredentials, whatever the answer says
403 or 404errorUnavailable
429errorRateLimited
Anything elseerrorGeneric

An end user whose email address is not confirmed yet is refused with 403 EMAIL_VERIFICATION_REQUIRED: this version shows errorUnavailable, passes the error to onError, and does not ask for the code. Send such end users to the hosted pages; see Sign-in methods.

Sign-up form

SignUpForm asks for an organization name, email and password, and sends POST /public/v1/auth/register. On success it calls onSignedUp once with the issued session.

SignUpFormPropsTypeMeaning
onSignedUp(session: IssuedSession) => void, requiredReceives the session; store it where your application keeps its session
defaultOrganizationNamestringHides the organization field and sends this name instead
logoUrlstringShows this image above the title
productNamestringAdded to the title, and used as the logo's alternative text
signInUrlstringShows a link to this address under the form
classNamestringAdded to the root element
labelsPartial<SignUpLabels>Replaces texts
onError(error: ShipRevError) => voidCalled once for each failed request
AnswerText shown
400The message of the answer, for example the password rules; errorInvalid when there is none
409errorExists
403 or 404errorUnavailable
429errorRateLimited
Anything elseerrorGeneric

The region confirms a new email address before it issues a session, and this version cannot send an invitation, so a sign-up through SignUpForm does not complete: the region creates the account, emails a code and answers 403 EMAIL_VERIFICATION_REQUIRED, which the form shows as errorUnavailable without asking for the code, and onSignedUp is not called. Until a version with this step is published, send end users who sign up with a password to the hosted pages; see Sign-in methods. The texts verifyTitle and verifyBody are shown only when an issued session's account has email_verified set to false, which the region does not issue.

Pricing table

PricingTable lists the primary plans that have a published version, with the price of that version and one line per capability with its allowance; add-on plans are left out. The organization's current plan is marked.

PricingTablePropsTypeMeaning
plansPublicPlan[]Plans you already have; the component then does not read GET /public/v1/catalog/plans. That read needs a session, so a pricing page for signed-out visitors must pass plans
subscriptionSubscription | nullThe organization's subscription, null for none; the component then does not read GET /public/v1/subscriptions
successUrlstringWhere checkout returns after payment; the current page by default
cancelUrlstringWhere checkout returns when abandoned; the current page by default
onSelectPlan(planVersionId: string, intent: 'subscribe' | 'change') => voidTakes the choice over: the component calls it and sends no request itself
onNavigate(url: string) => voidOpens the checkout and payment pages; window.location.assign by default
onPlanChanged(subscription: Subscription) => voidCalled with the new subscription after a change took effect
classNamestringAdded to the root element
labelsPartial<PricingTableLabels>Replaces texts
onError(error: ShipRevError) => voidCalled once for each failed request

What a choice does depends on the organization's subscription:

The organizationIntentChoosing a plan
Has a subscription with status ACTIVE'change'Asks to confirm inline, then sends POST /public/v1/subscriptions/change. When the answer's outcome is APPLIED, the plan is switched and onPlanChanged is called; when it is PAYMENT_REQUIRED, the component opens payment_url
Has none, or one with any other status'subscribe'Sends POST /public/v1/checkout/sessions and opens checkout_url

Before a switch, PricingTable asks only whether to switch, with confirmSwitchPrompt, which says that the change takes effect right away. It does not say that the difference is charged at once, and when the answer is PAYMENT_REQUIRED, the change takes effect only once the payment succeeds. To tell end users this, replace that text through the labels prop.

A refused checkout shows one of these texts:

AnswerText shown
ACTIVE_SUBSCRIPTION_EXISTSpastDue when the error's details.status is PAST_DUE, otherwise activeSubscription
CHECKOUT_PENDING_CONFIRMATIONpendingConfirmation, as a notice rather than an error
CHECKOUT_IN_PROGRESScheckoutInProgress
PAYMENT_PROVIDER_UNAVAILABLE, PAYMENT_PROVIDER_NOT_CONFIGURED, or any other 503paymentsUnavailable
Any other 409activeSubscription
Any other 404planNotFound
Any other 400planNotPurchasable
Any other 403unverifiedEmail
Anything elsecheckoutGeneric

A refused change shows one of these texts:

AnswerText shown
SUBSCRIPTION_NOT_ACTIVEsubscriptionNotActive
PLAN_CHANGE_CONFLICTplanChangeConflict
PLAN_UNCHANGEDplanUnchanged
CHECKOUT_IN_PROGRESScheckoutInProgress
PLAN_CHANGE_NOT_ALLOWEDplanChangeNotAllowed
PAYMENT_PROVIDER_UNAVAILABLE or PAYMENT_PROVIDER_NOT_CONFIGUREDpaymentsUnavailable
Any other 403unverifiedEmail
Anything elseplanChangeGeneric

unverifiedEmail is shown for every other 403, including INSUFFICIENT_ROLE, which refuses members who are not an owner or admin of the organization (see Who may do what). To tell the two apart, read code in onError, or replace the text through labels.

Subscription panel

SubscriptionPanel shows the organization's plan, its status and the date its period renews, ends or ended, with a cancel action that asks for confirmation first.

SubscriptionPanelPropsTypeMeaning
subscriptionSubscription | nullThe organization's subscription, null for none; the component then does not read GET /public/v1/subscriptions
pricingUrlstringShows a link to your pricing page
allowCancelbooleanfalse hides the cancel action; true by default
onCanceled(subscription: Subscription) => voidCalled with the subscription the cancellation returned
classNamestringAdded to the root element
labelsPartial<SubscriptionPanelLabels>Replaces texts
onError(error: ShipRevError) => voidCalled once for each failed request
StatusText shownPeriod line
ACTIVEstatusActiverenewsOn, or cancelsOn when canceled_at is set
PAST_DUEstatusPastDuerenewsOn, or cancelsOn when canceled_at is set
PENDING_CONFIRMATIONstatusPendingrenewsOn, or cancelsOn when canceled_at is set
CANCELEDstatusCanceledendedOn

The cancel action is shown when allowCancel is on, the subscription has not ended and no cancellation is scheduled. Confirming sends POST /public/v1/subscriptions/cancel; what that does to each kind of subscription is in Cancel and resume. A failed cancellation shows cancelError.

Before a cancellation, SubscriptionPanel shows confirmCancelPrompt, which says that the subscription stays active until the end of the period. That holds for a subscription paid through checkout; one without a card, or activated in the operator console, ends at once. If your end users can have such a subscription, replace that text through the labels prop.

Usage meter

UsageMeter reads GET /public/v1/usage/summary and shows, for each capability, the amount used in the current period out of the allowance, with a bar.

UsageMeterPropsTypeMeaning
summaryUsageSummaryA summary you already have; the component then does not read it
capabilityKeysstring[]Shows only these capabilities, in this order. Without it, every capability in the order of the answer
showWalletBalancebooleanAlso shows the organization's wallet balance; false by default
classNamestringAdded to the root element
labelsPartial<UsageMeterLabels>Replaces texts
onError(error: ShipRevError) => voidCalled once for each failed request

Amounts are shown as the decimal strings the API returns. The bar and usedOfAllowance are shown when the allowance is a number greater than 0; otherwise only usedOnly.

Labels

Every text a component shows is a key of its labels type. Pass any subset through the labels prop; keys you leave out keep the default. A {name} in a default is replaced by the component.

tsx
<SubscriptionPanel labels={{ cancel: 'End subscription', renewsOn: 'Next renewal: {date}' }} />

Sign-in form texts

SignInLabelsDefault
titleSign in
emailLabelEmail
passwordLabelPassword
submitSign in
submittingSigning in…
forgotPasswordForgot password?
signUpPromptDon't have an account?
signUpLinkCreate an account
errorRequiredPlease enter your email and password.
errorInvalidCredentialsInvalid email or password.
errorUnavailableSign-in is not available on this site.
errorRateLimitedToo many attempts. Please wait a moment and try again.
errorGenericCould not sign in. Please try again.

Sign-up form texts

SignUpLabelsDefault
titleCreate an account
organizationLabelOrganization name
emailLabelEmail
passwordLabelPassword
submitCreate account
submittingCreating account…
signInPromptAlready have an account?
signInLinkSign in
verifyTitleCheck your inbox
verifyBodyWe sent a verification email to {email}. Open the link in it to finish setting up your account.
errorRequiredPlease fill in all fields.
errorInvalidPlease check your details and try again.
errorExistsAn account with this email already exists.
errorUnavailableSign-up is not available on this site.
errorRateLimitedToo many attempts. Please wait a moment and try again.
errorGenericCould not create your account. Please try again.

Pricing table texts

PricingTableLabelsDefault
titlePlans
perMonth/ month
perYear/ year
subscribeSubscribe
switchPlanSwitch to this plan
currentPlanCurrent plan
redirectingRedirecting…
confirmSwitchPromptSwitch to {plan}? The change takes effect right away.
confirmSwitchConfirm switch
keepCurrentPlanKeep current plan
switchingSwitching…
planChangedYour plan has been switched.
loadingLoading plans…
signedOutSign in to see the plans.
emptyNo plans are available right now.
loadErrorCould not load the plans. Please try again.
activeSubscriptionYour organization already has an active subscription. Manage it from Billing.
pastDueYour subscription has a payment issue. Update your payment method from Billing.
pendingConfirmationWe've received your payment and are confirming your subscription.
checkoutInProgressA checkout is already being started. Please wait a moment and try again.
paymentsUnavailablePayments are not available right now. Please try again later.
planNotFoundThis plan is no longer available.
planNotPurchasableThis plan is not available for purchase.
unverifiedEmailPlease verify your email address before subscribing.
checkoutGenericCould not start checkout.
subscriptionNotActiveYour subscription is not active. Resolve any payment issue from Billing first.
planChangeConflictYour subscription changed while switching. Reload the page and try again.
planUnchangedYou are already on this plan.
planChangeNotAllowedYour subscription cannot be switched to this plan. Contact support for help.
planChangeGenericCould not switch your plan.

Subscription panel texts

SubscriptionPanelLabelsDefault
titleSubscription
emptyYou don't have a subscription yet.
renewsOnRenews on {date}
cancelsOnCanceled; access continues until the period ends on {date}
endedOnEnded on {date}
statusActiveActive
statusPastDuePayment past due
statusPendingConfirming payment
statusCanceledEnded
changePlanChange plan
cancelCancel subscription
confirmCancelPromptYour subscription stays active until {date} and then ends.
confirmCancelConfirm cancellation
keepSubscriptionKeep subscription
cancelingCanceling…
loadingLoading subscription…
signedOutSign in to see your subscription.
loadErrorCould not load your subscription. Please try again.
cancelErrorCould not cancel your subscription. Please try again.

{date} is the end of the current period, formatted in English and in UTC, for example Jan 31, 2027.

Usage meter texts

UsageMeterLabelsDefault
titleUsage
usedOfAllowance{used} of {allowance}
usedOnly{used} used
walletBalanceWallet balance
emptyNo usage to show for this period.
loadingLoading usage…
signedOutSign in to see your usage.
loadErrorCould not load your usage. Please try again.

Data types

The fields are those of the Public API; times are ISO 8601 strings.

IssuedSession

IssuedSessionTypeMeaning
access_tokenstringThe end user's session token; return it from getAccessToken, and send it to your backend, which verifies it with the Server SDK
token_type'Bearer'Always Bearer
expires_innumberSeconds until the access token expires
refresh_tokenstring, optionalRenews the session with POST /public/v1/auth/refresh
accountAccountProfileThe signed-in account

AccountProfile

AccountProfileTypeMeaning
account_idstringThe account
emailstringIts email address
identity_idstringThe account's identity ID
gate_type'seller' or 'buyer'The sign-in gate that issued the session; 'buyer' for your end users
statusstringThe account's status
email_verifiedbooleanWhether the email address is confirmed
display_namestring | null, optionalDisplay name
localestring, optionalPreferred locale
timezonestring, optionalPreferred time zone
current_organization_idstring, optionalThe organization the session acts for
current_project_idstring, optionalYour application
current_rolestring, optionalThe account's role in that organization
organization_slugstring, optionalSlug of that organization
membershipsAccountMembership[]Every organization the account belongs to; see below

AccountMembership

AccountMembershipTypeMeaning
membership_idstringThe membership
organization_idstringThe organization
organization_namestringIts name
organization_typestringIts type
project_idstring | nullThe application the organization belongs to
rolestringThe account's role in it

PublicPlan

PublicPlanTypeMeaning
plan_idstringThe plan
namestringIts name, shown by PricingTable
type'PRIMARY' or 'ADDON'PricingTable lists PRIMARY plans only
statusDRAFT, ACTIVE or ARCHIVEDThe plan's status
latest_versionPublicPlanVersion, optionalThe latest published version; a plan without one is not listed

PublicPlanVersion

PublicPlanVersionTypeMeaning
plan_version_idstringThe version; this is what an end user subscribes to
versionnumberVersion number within the plan
currencystringCurrency code
price_amountnumberBase price in major units of currency
billing_intervalMONTHLY or YEARLYHow often it is billed
external_price_refstring | null, optionalThe price at your payment provider
rulesPublicEntitlementRule[], optionalWhat the version grants, one rule per capability; see below

PublicEntitlementRule

PublicEntitlementRuleTypeMeaning
rule_idstringThe rule
capability_idstringThe capability it grants
capability{ key, name }, optionalThe capability's key and name
allowancenumberThe allowance per period
reset_intervalstring, optionalWhen the allowance resets
overage_unit_pricenumber, optionalPrice per unit beyond the allowance

Subscription

SubscriptionTypeMeaning
subscription_idstringThe subscription
project_idstringYour application
organization_idstringThe organization that holds it
plan_version_idstringThe plan version subscribed to
plan_namestring, optionalThe plan's name
plan_versionnumber, optionalThe version number
statusPENDING_CONFIRMATION, ACTIVE, PAST_DUE or CANCELEDSee Self-service
originCHECKOUT_SESSION or CUSTOMER_MANAGED_PAYMENTHow it was started
external_sub_refstring | null, optionalThe subscription at your payment provider
current_period_startstringStart of the current period
current_period_endstringEnd of the current period
canceled_atstring | null, optionalSet when a cancellation at the end of the current period is scheduled
created_atstringWhen it was created

UsageSummary

UsageSummaryTypeMeaning
project_idstringYour application
organization_idstringThe organization
wallet_balancestringThe organization's wallet balance, a decimal string
itemsUsageSummaryItem[]One item per capability

UsageSummaryItem

UsageSummaryItemTypeMeaning
capability_keystringThe capability's key, as capabilityKeys names it
capability_namestringIts name, shown by UsageMeter
allowancestringThe allowance of the current period, a decimal string
usedstringUsage counted so far, a decimal string
remainingstringWhat is left, a decimal string
overage_policystringThe capability's overage policy; see Overage policies
reset_intervalstringWhen the allowance resets
period_startstringStart of the current period
period_endstringEnd of the current period

Errors

Every failure passed to onError is a ShipRevError, which extends Error; its message is the message of the answer, or a generic one.

ShipRevErrorTypeMeaning
statusnumberThe HTTP status; 0 when no answer arrived
codestringThe error code of the answer; see Error codes. Otherwise one of the codes below
requestIdstring, optionalThe request ID of the answer; quote it when you contact us
detailsunknown, optionalThe details of the answer, for example the subscription's status for ACTIVE_SUBSCRIPTION_EXISTS
CodeWhen
HTTP_ERRORThe answer was an error without an error body, or a success whose body was not JSON
NETWORK_ERRORNo answer arrived; status is 0
UNKNOWN_ERRORAnything else was thrown, including an error thrown by your onSignedIn or onSignedUp; status is 0

Styling

The stylesheet is optional. Without it, the components render unstyled, with class names that start with sr-. With it, every rule sits in the shiprev cascade layer, so any style of yours outside a layer wins. Change the look through appearance or these variables:

Variableappearance fieldDefaultDefault with colorScheme 'dark'
--sr-color-primaryprimaryColor#4f46e5#4f46e5
--sr-color-text#18181b#f4f4f5
--sr-color-muted#71717a#a1a1aa
--sr-color-border#e4e4e7#3f3f46
--sr-color-surface#ffffff#18181b
--sr-color-danger#dc2626#f87171
--sr-radiusradius8px8px
--sr-font-familyfontFamilyThe system UI fontThe system UI font

The package loads no fonts, images or icons.

© 2026 ShipRev