JavaScript SDK
@perkamo/sdk-js is a thin TypeScript client around the v1 HTTP API. Use it from trusted server-side JavaScript or TypeScript.
Create the Space and server key in Spaces and Secret keys before wiring the SDK.
Create a client
ts
import { createPerkamoClient } from "@perkamo/sdk-js";
const perkamo = createPerkamoClient({
baseUrl: "https://api.perkamo.com",
tenant: "commerce-test",
apiKey: () => process.env.PERKAMO_SECRET_KEY,
timeoutMs: 5000,
});| Option | Required | Description |
|---|---|---|
baseUrl | yes | Perkamo API base URL without a trailing slash. |
tenant | yes | Space slug used by emitted events. |
apiKey | yes | Server API key string or async supplier. |
fetch | no | Custom fetch-compatible adapter. |
timeoutMs | no | Request timeout in milliseconds. |
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 profile 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 profile
ts
const profile = await perkamo.profile("customer_123");
if (profile.flags.perks.welcome_member) {
showWelcomeBadge();
}Profile streams
The SDK exposes subscribeProfile(userId, streamToken, onProfile, onError?) as a preview helper for the planned profile stream flow. Do not depend on it as stable v1 API behavior yet: the public stable v1 HTTP controller currently documents server-key REST endpoints, not browser-token /v1/client/* routes.
When profile streams are enabled for an integration, they must use short-lived tokens minted by the customer backend. Never pass a tenant server API key into browser code.
Configure browser-token metadata and allowed origins in Browser SDK.
ts
const subscription = perkamo.subscribeProfile("customer_123", streamToken, (profile) =>
renderProgress(profile.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 = {
tenant: "commerce-test",
user_id: "customer_123",
event: "purchase.completed",
transaction_id: createTransactionId(),
context: { order_id: "order_1092" },
};
assertSafeEventInput(input);