@masivo/core
v1.0.1
Published
Masivo core SDK — shared logic for all Masivo SDK packages
Readme
@masivo/core
Official Masivo core SDK — shared logic for all Masivo SDK packages.
This is an internal package. It is consumed by
@masivo/clientand@masivo/rn. You can also use it directly if you are building your own Masivo SDK wrapper or running in a Node.js backend context.
Important: This SDK requires a CLIENT API key. Do not use SERVER API keys — they will be rejected and the SDK will warn you about exposed server credentials. Create a CLIENT key in the Masivo dashboard.
Installation
npm install @masivo/corepnpm add @masivo/coreyarn add @masivo/coreQuick Start
import { createClient } from "@masivo/core";
const masivo = createClient({ apiKey: "your-client-api-key" });
await masivo.sendAnalyticsEvent({
type: "ADD_TO_CART",
customer_id: "customer-123",
brand_id: "brand-456",
product: {
sku: "SKU-001",
amount: 1,
value: 29.99
}
});
// Clean up when the user logs out or the process ends
masivo.destroy();Events are sent on the analytics path: they feed tracking, journeys, and related flows without applying behavioral or punch-card loyalty rewards from the client. Use your backend with a SERVER key when you need full loyalty campaign execution.
Allowed Event Types
This SDK uses CLIENT API keys, which can only emit:
- Tracking events —
ADD_TO_CART,EMPTY_CART, and other tracking types. - Custom event types — Any custom event type you have created in the Masivo platform.
Default event types like PURCHASE, ABANDONED_CART, BIRTHDAY, REGISTRATION, and TIER_ADJUSTMENT are not allowed from the client SDK. These must be sent from your backend using a SERVER API key directly via the Masivo REST API.
API
createClient(config)
Creates a Masivo client instance. Multiple calls with the same apiKey share a single AuthManager singleton — one bearer token, one background refresh timer — no matter how many client instances are created. The client handles authorization automatically: it exchanges your CLIENT API key for a bearer token on the first event, then refreshes it proactively every 5 minutes in the background.
| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| config.apiKey | string | Yes | Your Masivo CLIENT API key |
| config.brandId | string \| null | No | Default brand ID injected into events that have a platform but no explicit brand_id |
Returns a MasivoClient with the following methods:
client.sendAnalyticsEvent(event)
Sends an event to Masivo on the analytics path. Events are buffered internally and sent in batches for efficiency.
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| type | string | Yes | Event type (e.g. ADD_TO_CART, custom type) |
| customer_id | string | Yes | External customer identifier |
| brand_id | string \| null | Yes | Brand identifier, null if not applicable |
| ...rest | unknown | No | Any additional event data |
Returns Promise<SendEventResult>:
{
success: boolean;
status: number; // HTTP status code
data: unknown; // Response payload
}client.flush()
Forces an immediate send of all buffered events. Useful before navigating away or logging out.
await masivo.flush();client.destroy()
Stops the background token refresh interval, clears all internal state, and removes the AuthManager instance from the singleton registry. Call this on logout to avoid memory leaks. After calling destroy(), the next createClient call with the same apiKey will start fresh.
masivo.destroy();client.getToken()
Returns the current Bearer token, waiting for the initial authorization if necessary. Intended for sibling SDK packages (@masivo/rn) that need to make authenticated HTTP requests using the same credentials.
const token = await masivo.getToken();Error Handling
import { createClient, MasivoError, MasivoServerKeyError, MasivoAuthError, MasivoNetworkError } from "@masivo/core";
const masivo = createClient({ apiKey: "your-client-api-key" });
try {
await masivo.sendAnalyticsEvent({
type: "ADD_TO_CART",
customer_id: "customer-123",
brand_id: null
});
} catch (error) {
if (error instanceof MasivoServerKeyError) {
// You used a SERVER key instead of a CLIENT key
console.error(error.message);
} else if (error instanceof MasivoNetworkError) {
// Network failure (no connectivity, DNS, timeout)
console.error("Network error:", error.message);
} else if (error instanceof MasivoAuthError) {
// Invalid API key or authorization failure
console.error("Auth error:", error.message, error.details);
} else if (error instanceof MasivoError) {
// API returned an error (400, 422, etc.)
console.error("API error:", error.status, error.message);
}
}| Error class | When | Properties |
| --- | --- | --- |
| MasivoServerKeyError | SERVER API key used instead of CLIENT | message |
| MasivoNetworkError | Fetch fails (no connectivity, DNS, etc.) | message |
| MasivoAuthError | Authorization fails (invalid/expired key) | message, status, details |
| MasivoError | API returns an error response | message, status, details |
Token Management
The SDK manages authentication transparently via the AuthManager singleton:
- On the first event, it exchanges your CLIENT API key for a bearer token via the authorize endpoint, sending an
x-masivo-sdk: clientheader so the server verifies the key type. - If you use a SERVER key, the server rejects the request and the SDK throws a
MasivoServerKeyErrorwith clear instructions. - The token is proactively refreshed every 5 minutes in the background, so requests never fail due to expiry.
- If a request returns
401, the SDK invalidates the cached token and retries once with a fresh token. - Concurrent requests share the same boot promise to avoid redundant authorization calls.
- Singleton per
apiKey— multiplecreateClientcalls with the same key share oneAuthManagerinstance (one token state, one refresh timer). Callingdestroy()removes the instance from the registry so the next client creation starts clean.
Batching Behavior
Events are queued and sent in bulk for efficiency:
| Trigger | Condition |
| --- | --- |
| Queue size | Flush when 100 events are queued |
| Idle | Flush after 30 seconds with no new events |
| Max wait | Flush after 60 seconds regardless of activity |
| Manual | Call client.flush() to send immediately |
Compatibility
- Node.js >= 18 (native
fetch) - React Native (built-in
fetch) - Browsers (built-in
fetch) - Deno, Bun, or any runtime with global
fetch
Zero external dependencies.
Links
License
MIT
