Skip to main content

SDK API Client

Syntropy provides two client factories for different use cases:

ClientKey typeUse case
createSyntropyPublicClientPublishable (syn_pk_)Client-side apps (React Native, browser) -- identify, track, devices only
createSyntropyApiClientSecret (syn_sk_)Server-side -- full admin access (list, segments, import, queue, etc.)

Both clients are exported from:

  • @eclosion-tech/syntropy-node
  • @eclosion-tech/syntropy-react-native
  • @eclosion-tech/syntropy-nextjs
  • @eclosion-tech/syntropy-express
  • @eclosion-tech/syntropy-browser

Public Client (Client-Side)

Use createSyntropyPublicClient in React Native, browser, or any client-side code. Publishable keys are safe to embed -- they only grant access to customer write operations.

import { createSyntropyPublicClient } from "@eclosion-tech/syntropy-react-native";

const customers = createSyntropyPublicClient({
accountId: "project_uuid",
publishableKey: "syn_pk_xxx",
baseUrl: "https://syntropy.chat/api",
});

// Identify (upsert) a customer
await customers.identify({
externalId: "user_123",
email: "user@example.com",
name: "Jane Doe",
metadata: { plan: "pro" },
});

// Track an event
await customers.track({
name: "purchase_completed",
externalId: "user_123",
payload: { amount: 99.99, currency: "USD" },
});

// Register a push device
await customers.registerDevice({
externalId: "user_123",
platform: "ios",
pushToken: "expo_push_token",
active: true,
});

Public Endpoints

The public client calls these endpoints (CORS-enabled, rate-limited):

MethodEndpointScope
POST/api/{accountId}/customers/identifycustomers:write
POST/api/{accountId}/customers/trackcustomer_events:write
POST/api/{accountId}/customers/devicescustomer_devices:write

Admin Client (Server-Side)

Use createSyntropyApiClient with a secret key for full access from backend services.

import { createSyntropyApiClient } from "@eclosion-tech/syntropy-node";

const api = createSyntropyApiClient({
baseUrl: "https://syntropy.chat/api",
apiKey: process.env.SYNTROPY_API_KEY,
});

const scope = {
organizationId: "org_uuid",
projectId: "project_uuid",
};

Source Maps

await api.sourceMaps.upload(scope, {
file, // Blob/File/Buffer-compatible form value in your runtime
version: "1.2.3",
filename: "main.js.map",
});

const { sourceMaps } = await api.sourceMaps.list(scope);

Chat Schemas

const created = await api.chatSchemas.create(scope, {
name: "Lead Intake v1",
schema: {
type: "object",
properties: {
name: { type: "string" },
email: { type: "string", format: "email" },
},
},
});

const { schemas } = await api.chatSchemas.list(scope);
await api.chatSchemas.update(scope, created.schema.id, {
description: "Updated schema description",
});

Customers

await api.customers.upsert(scope, {
externalId: "user_123",
email: "user@example.com",
name: "Jane Doe",
metadata: { plan: "pro" },
});

await api.customers.trackEvent(scope, {
name: "purchase_completed",
externalId: "user_123",
payload: { amount: 99.99, currency: "USD" },
});

await api.customers.registerDevice(scope, "customer_uuid", {
platform: "ios",
pushToken: "expo_push_token",
active: true,
});

Segments and Eligibility

await api.customers.upsertSegment(scope, {
name: "Pro Customers",
definition: {
logic: "and",
conditions: [
{ field: "status", operator: "eq", value: "active" },
{ field: "metadata.plan", operator: "eq", value: "pro" },
],
},
});

const eligibility = await api.customers.evaluateEligibility(scope, {
externalId: "user_123",
channel: "email",
topic: "product_updates",
});

CSV Import

await api.customers.importCsv(scope, {
csv: csvString,
hasHeader: true,
dryRun: false,
source: "customer_io_csv_import",
});

Shared Queue Jobs

Use queue APIs when producers should only need a project API key. Required scopes:

  • queue_jobs:write (or project:admin) for enqueue
  • queue_jobs:read (or project:admin) for monitoring
await api.queue.enqueue(scope, {
task: "alerts.process",
payload: {
trigger: "manual",
},
idempotencyKey: "syntropy:alerts.process:manual",
});

const { jobs } = await api.queue.list(scope, {
status: "running",
limit: 20,
});

const job = await api.queue.get(scope, "job_uuid", { eventLimit: 100 });

const { events } = await api.queue.listEvents(scope, {
since: new Date(Date.now() - 30_000).toISOString(),
});

Error Handling

The client throws SyntropyApiError for non-2xx responses.

import {
createSyntropyApiClient,
SyntropyApiError,
} from "@eclosion-tech/syntropy-node";

try {
await api.customers.list(scope);
} catch (error) {
if (error instanceof SyntropyApiError) {
console.error(error.status, error.responseBody);
}
}