@custral/js is the browser-facing, publishable-key surface, separate
from the secret-key @custral/sdk. It is the protocol
layer the other browser packages build on:
CustralUsage: report per-customer usage events against a Custral usage module, and read them back.CustralErrorand friends: one error hierarchy tocatch, whatever failed.request(): the raw{data, error, reqId}envelope, unwrapped, if you are calling an endpoint the package does not wrap yet.
Looking for the chat widget? It is
@custral/widget, which
builds on this package. CustralChat used to ship here under
@custral/ui@1.x; it moved, because the only thing that ever used it was the
widget itself.Install
socket.io-client is an optional peer, needed only if you import the
@custral/js/socket subpath. Usage tracking and the error types pull in nothing.
Usage tracking
CustralUsage records that a customer consumed a metered product. It is safe to
call from a browser at the moment of consumption, which is the point: your own
application is the only thing that knows a unit was used.
key is a publishable (pk_…) or secret (sk_…) key; moduleId is the usage
module (umod_…) events are recorded against. baseUrl defaults to
https://api.custral.com and timeoutMs to 30 seconds.Records one event. It needs a customer, plus a product or an
event name such
as report_created. user is the person inside the account: your own user id
or their email. quantity defaults to 1 and occurredAt to now. An
occurredAt that cannot be read is refused by name rather than throwing a bare
RangeError. If an identifier matches no record, the result’s unmatched
names that side (["customer"]). The event is kept, but counts toward no
record’s usage.Reads recorded events back, newest first. Requires a secret key holding
usage:read; a publishable key is refused with insufficient_scope.Reading events is paged at 50 by default (200 max). A usage event is written
per metered call in your own application, so this is the one list whose length
is not bounded by anything a person does in the workspace. Filter by date to
total a period rather than paging to the end.
key option was called publishableKey under @custral/ui. That spelling
still works and is deprecated: the same client now takes a secret key too, so the
old name described only half of what it accepts.
Errors
Every call throws aCustralError subclass. Custral’s API answers HTTP 200 with
the failure inside the envelope, so status alone is not the signal, and this is
the one place that is decided.
Every one carries
code, statusCode and requestId. Quote the req_… when
you contact support: it is what makes a failure findable in our logs.
Realtime
@custral/js/socket is a subpath, not part of the base entry, because
socket.io-client is browser-only and around 40KB. Import it only where you
actually open a socket.
Troubleshooting
insufficient_scope from getEvents
insufficient_scope from getEvents
Reading events needs a secret key (
sk_…) holding usage:read. Writing
one with track() is publishable-key authed so it can be called from a
browser; reading them back is not, or a client-side key would let anyone
enumerate your workspace’s usage.CustralUsage: a key is required
CustralUsage: a key is required
The constructor needs
key (or the deprecated publishableKey). Create one
in Settings → Applications.Which package do I want?
Which package do I want?
@custral/js in the browser with a publishable key for usage tracking.
@custral/widget for the React chat widget.
@custral/ui for React hooks over records and objects.
@custral/sdk on a server with a secret key for
records, objects, and webhooks.I was using @custral/ui 1.x
I was using @custral/ui 1.x
CustralUsage and the error types are now in @custral/js; CustralChat is
in @custral/widget. Change the import and nothing else.