npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@marmarteam/sdk

v0.1.4

Published

TypeScript client for the Marmar Clinical Decision Support API

Readme

Marmar CDS TypeScript SDK

Typed client for integrating with the Marmar Clinical Decision Support (CDS) API. The SDK provides:

  • A strongly-typed MarmarClient over the core REST API
  • Built‑in error handling via ApiError
  • Webhook signature helpers for secure event handling
  • Generated TypeScript types for all OpenAPI and FHIR schemas

Installation

npm install @marmarteam/sdk

The package targets modern Node and browser environments with fetch available. For Node < 18 or custom runtimes, see Client configuration below.

Quickstart

import { createMarmarClient } from '@marmarteam/sdk';

const client = createMarmarClient({
  baseUrl: 'https://cds.marmar.life/v1',
  apiKey: process.env.MARMAR_API_KEY!,
  tenantCode: process.env.MARMAR_TENANT_CODE!,
});

const patient = await client.createOrUpdatePatient({
  externalId: 'mrn-123',
  demographics: {
    firstName: 'Ada',
    lastName: 'Lovelace',
    sex: 'FEMALE',
  },
});

const assessmentQueued = await client.createAssessment({
  patient: {
    patientId: patient.patientId,
  },
  medications: [
    {
      name: 'Metformin',
      dosage: { amount: 500, unit: 'mg', frequency: 'BID' },
    },
  ],
});

console.log(`Assessment ${assessmentQueued.assessmentId} queued at ${assessmentQueued.createdAt}`);

const roster = await client.listPatients();
console.log(`Loaded ${roster.patients.length} patients`);

Client configuration

createMarmarClient accepts the following configuration:

import type { CreateMarmarClientConfig } from '@marmarteam/sdk';

const config: CreateMarmarClientConfig = {
  baseUrl: 'https://cds.marmar.life/v1',
  apiKey: process.env.MARMAR_API_KEY!,
  tenantCode: process.env.MARMAR_TENANT_CODE!,
  // Optional: custom fetch implementation (for Node < 18, tests, or edge runtimes)
  // fetch: yourCustomFetch,
};
  • baseUrl: Base URL for the Marmar CDS API. The SDK appends relative paths such as /patients and /assessments.
  • apiKey: Tenant API key. Sent as X-API-Key and X-Marmar-Api-Key.
  • tenantCode: Human‑readable tenant code used to scope tenant‑specific operations.
  • fetch: Optional custom fetch implementation. If omitted, the global fetch is used.

Per‑request overrides and options are available via RequestOptions:

const roster = await client.listPatients({
  tenantCode: 'another-tenant', // override configured tenant for this call
  signal: abortController.signal,
  headers: {
    'X-Request-Id': 'example-id',
  },
});

MarmarClient methods

Tenants

registerTenant

Register a new tenant and obtain credentials (primarily for sandbox / provisioning flows).

const registration = await client.registerTenant({
  organizationName: 'Example Health',
  contactEmail: '[email protected]',
});

console.log(registration.tenantCode, registration.apiKey);

Patients

createOrUpdatePatient

Create or update a patient profile for the current tenant.

const patient = await client.createOrUpdatePatient({
  externalId: 'mrn-123',
  demographics: {
    firstName: 'Ada',
    lastName: 'Lovelace',
    sex: 'FEMALE',
  },
});

console.log(patient.patientId, patient.created ? 'created' : 'updated');

listPatients

List patients for the current tenant.

const patients = await client.listPatients();

for (const item of patients.patients) {
  console.log(item.patientId, item.externalId);
}

Assessments

createAssessment

Queue a medication safety assessment for a patient.

const assessmentQueued = await client.createAssessment({
  patient: {
    patientId: patient.patientId,
  },
  medications: [
    {
      name: 'Metformin',
      dosage: { amount: 500, unit: 'mg', frequency: 'BID' },
    },
  ],
});

getAssessment

Retrieve an assessment by identifier.

const assessment = await client.getAssessment(assessmentQueued.assessmentId);

console.log(assessment.assessmentId, assessment.summary?.text);

Webhooks

configureTenantWebhook

Configure outbound webhook delivery for the tenant.

await client.configureTenantWebhook({
  url: 'https://example.org/webhooks/marmar',
  secret: process.env.MARMAR_WEBHOOK_SECRET!,
  events: ['assessment.completed'],
});

The same secret is used to generate and verify webhook signatures (see below).

Webhook verification

The SDK includes helpers for securely verifying webhook signatures and generating signatures for tests:

  • verifyWebhookSignature
  • signWebhookPayload

Verifying incoming webhooks

import { verifyWebhookSignature } from '@marmarteam/sdk';

const webhookSecret = process.env.MARMAR_WEBHOOK_SECRET!;

// Example using Express with a raw body parser
app.post(
  '/webhooks/marmar',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const signature = req.header('X-Marmar-Signature')!;
    const timestamp = req.header('X-Marmar-Timestamp')!;
    const payload = req.body; // Buffer or string

    const result = verifyWebhookSignature({
      payload,
      signature,
      secret: webhookSecret,
      timestamp,
      // Optional: toleranceSeconds (defaults to 300 seconds)
      // toleranceSeconds: 600,
    });

    if (!result.valid) {
      console.warn('Invalid Marmar webhook:', result.reason);
      return res.sendStatus(400);
    }

    const eventJson = payload.toString('utf-8');
    const event = JSON.parse(eventJson);

    // Handle AssessmentCompletedEvent
    // ...

    return res.sendStatus(204);
  },
);

Generating signatures (tests and local tooling)

import { signWebhookPayload } from '@marmarteam/sdk';

const secret = 'test-secret';
const timestamp = Math.floor(Date.now() / 1000).toString();
const payload = { type: 'assessment.completed' };

const signature = signWebhookPayload(secret, payload, timestamp);

Error handling

API errors throw an instance of ApiError, which includes the HTTP status and parsed response body when available.

import { ApiError } from '@marmarteam/sdk';

try {
  const assessment = await client.getAssessment('non-existent-id');
  console.log(assessment);
} catch (error) {
  if (error instanceof ApiError) {
    console.error('Marmar API error', {
      status: error.status,
      statusText: error.statusText,
      body: error.body,
    });
  } else {
    console.error('Unexpected error', error);
  }
}

Using generated types and FHIR helpers

The SDK exports the full OpenAPI types from the Marmar CDS API so you can type your own HTTP calls and data pipelines.

import type { components, operations } from '@marmarteam/sdk';

type PatientRequest = components['schemas']['PatientRequest'];
type PatientResponse = components['schemas']['PatientResponse'];
type AssessmentQueuedResponse = components['schemas']['AssessmentQueuedResponse'];

type SubmitFhirBundleResponse =
  operations['submitFhirBundle']['responses'][200]['content']['application/json'];

You can also use the FHIR types when constructing bundles for ingestion:

import type { components } from '@marmarteam/sdk';

type FhirBundle = components['schemas']['FhirBundle'];

const bundle: FhirBundle = {
  resourceType: 'Bundle',
  type: 'collection',
  entry: [
    // Patient, MedicationStatement, Condition, etc.
  ],
};

The FHIR endpoints are currently accessed via standard HTTP clients; the SDK provides the types so that your requests and responses remain type‑safe.

Environment support

  • Node: Recommended on Node 18+ where fetch is available by default. For older Node versions, supply a fetch implementation.
  • Browser / front‑end: Works with modern browsers that provide fetch. Do not expose secret API keys directly in public clients.

Further reading

For full API reference, FHIR details, and end‑to‑end integration guides, see the Marmar CDS documentation at https://docs.cds.marmar.life.