SDKsStable · 3 min read

JavaScript SDK

Backend JavaScript and TypeScript SDK setup for trusted Perkamo API calls.


Use @perkamo/sdk from trusted server-side JavaScript or TypeScript. Do not bundle this package with a server API key into browser, mobile or embedded widget code.

Install

bash

npm install @perkamo/sdk

ts

import { createPerkamoClient } from "@perkamo/sdk";

const perkamo = createPerkamoClient({
apiKey: () => process.env.PERKAMO_SECRET_KEY,
});

Only apiKey is required for a normal hosted API integration.

Advanced client options:

OptionRequiredDescription
apiKeyyesServer API key string or async supplier.
baseUrlnoAPI endpoint override supplied by Perkamo support.
fetchnoCustom fetch-compatible adapter.
timeoutMsnoOptional request timeout override. Defaults to none.

The SDK defaults to the hosted Perkamo API. You normally do not need to pass an API URL.

Identify a customer

Use your application's stable user id as the Perkamo customer id. Send e-mail, name and internal customer metadata as trusted customer traits from backend code:

ts

import type { PerkamoCustomerTraits } from "@perkamo/sdk";

const optionalLocale: string | undefined = undefined;
const traits: PerkamoCustomerTraits = {
email: "customer@example.test",
name: "Customer Test",
crm_id: "crm_123",
locale: optionalLocale,
};

await perkamo.identify("customer_123", traits);

You can also pass traits inline:

ts

await perkamo.identify("customer_123", {
email: "customer@example.test",
name: "Customer Test",
crm_id: "crm_123",
});

Only send non-secret facts your application is allowed to share with Perkamo. Calling identify() again updates traits for the same customer. A common pattern is to call it from trusted backend code after registration, login, email verification, consent changes or customer updates. Keep emit() for behavioral events such as purchases, lessons, referrals and app actions.

Undefined object properties in traits are omitted by JSON serialization. Remove undefined values from arrays before sending customer traits. Event context remains stricter: strip undefined values before calling emit() or batch(). Perkamo Console uses common identity traits such as e-mail, name, phone, external id, customer id and CRM id for customer display and operator search.

Emit one event

ts

await perkamo.emit(
"customer_123",
"purchase.completed",
{ order_id: "order_1092", amount: 12900, currency: "CZK" },
{ txId: "order_1092", occurredAt: new Date("2026-06-01T10:00:00.000Z") },
);

For business-critical events, always pass a stable txId. The SDK can generate one when omitted, but natural ids make retries and support investigations clearer.

Use Events to confirm the emitted event and Customers to inspect the resulting customer state.

Send a batch

ts

await perkamo.batch([
{
user_id: "customer_123",
event: "lesson.finished",
transaction_id: "lesson:intro:user:customer_123",
context: { lesson_id: "intro" },
occurred_at: new Date().toISOString(),
},
]);

Batch accepts up to 100 events. Each event requires an explicit transaction_id.

Read a customer

ts

const customer = await perkamo.customer("customer_123");

if (customer.flags.perks.welcome_member) {
showWelcomeBadge();
}

Read the event catalog

Use program() or eventCatalog() from trusted backend code when an internal admin tool needs the configured event keys and labels for the active Space.

ts

const events = await perkamo.eventCatalog();

for (const item of events) {
console.log(item.event, item.title);
}

Do not use this as a wallet editing API. Send operators to the Perkamo Console for audited manual wallet or perk changes.

Handle API errors

ts

import { PerkamoApiError } from "@perkamo/sdk";

try {
await perkamo.emit("customer_123", "purchase.completed", {}, { txId: "order_1092" });
} catch (error) {
if (error instanceof PerkamoApiError) {
console.error(error.status, error.requestId, error.retryAfter);
}
}

requestId, retryAfter and rateLimit are populated when the API or edge gateway returns the corresponding headers.

Customer streams

The SDK exposes subscribeCustomer(userId, streamToken, onCustomer, onError?) for the preview customer stream endpoint. See Realtime streaming before depending on streaming behavior.

Customer streams use dedicated short-lived stream:read tokens returned by the customer backend. Never pass a server API key into browser code.

Configure signing key metadata and Space-level allowed websites in Security.

ts

const subscription = perkamo.subscribeCustomer(
"customer_123",
streamToken,
(customer) => renderProgress(customer.wallets.points ?? 0),
);

subscription.close();

Core helpers

@perkamo/sdk-core is runtime-neutral and contains event validation, canonical JSON and transaction id helpers.

ts

import { assertSafeEventInput, createTransactionId } from "@perkamo/sdk-core";

const input = {
user_id: "customer_123",
event: "purchase.completed",
transaction_id: createTransactionId(),
context: { order_id: "order_1092" },
};

assertSafeEventInput(input);