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

@myo-devs/node

v0.1.0

Published

Official Node.js SDK for the Myo Platform

Readme

Myo Node.js SDK

Official Node.js SDK for the Myo Platform - Connect your users' personal data and retrieve structured insights via a simple API.

Installation

npm install @myo/node

Getting Started

1. Get your API key

Sign up at myo-app.co to get your developer API key (dev_xxx).

2. Set up environment variables

MYO_API_KEY=dev_xxx
MYO_API_BASE_URL=https://api.myo-app.co  # Optional, defaults to production

3. Initialize the client

import { MyoClient } from '@myo/node';

const client = new MyoClient({
  apiKey: process.env.MYO_API_KEY,
});

4. Create a link token (for user consent)

Before querying a user's data, they must connect via the Myo widget. Create a link token to initiate this flow:

const linkToken = await client.link.tokens.create({
  redirectUri: 'https://yourapp.com/callback',
});

// Return to your frontend:
// - linkToken.linkToken: Pass to @myo/react widget
// - linkToken.widgetUrl: Or redirect user directly
// - linkToken.expiresAt: Token expiration time

5. Query user context

After a user has connected, query their data with natural language:

const response = await client.context.query({
  userId: 'user-uuid-from-widget-callback',
  query: 'What are this user\'s main interests?',
});

console.log(response.response);  // AI-generated answer
console.log(response.model);     // Model used

Real-World Example (Next.js)

Here's how to integrate Myo in a Next.js application with API routes:

API Route: Create Link Token

// app/api/link-token/route.ts
import { NextResponse } from 'next/server';
import { MyoClient } from '@myo/node';

export async function POST() {
  const client = new MyoClient({
    apiKey: process.env.MYO_API_KEY,
  });

  const linkToken = await client.link.tokens.create({
    redirectUri: process.env.NEXT_PUBLIC_APP_URL || 'http://localhost:3000',
  });

  return NextResponse.json({
    linkToken: linkToken.linkToken,
    widgetUrl: linkToken.widgetUrl,
    expiresAt: linkToken.expiresAt,
  });
}

API Route: Query User Context

// app/api/query/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { MyoClient } from '@myo/node';

export async function POST(request: NextRequest) {
  const { userId, query } = await request.json();

  if (!userId || !query) {
    return NextResponse.json(
      { error: 'userId and query are required' },
      { status: 400 }
    );
  }

  const client = new MyoClient({
    apiKey: process.env.MYO_API_KEY,
  });

  const response = await client.context.query({
    userId,
    query,
  });

  return NextResponse.json({
    response: response.response,
    model: response.model,
  });
}

Features

  • Intuitive API - client.link.tokens.create(), not client.createLinkToken()
  • Full TypeScript support - Excellent IDE autocompletion
  • Dual ESM/CJS - Works with both module systems
  • Automatic retries - Built-in retry logic with exponential backoff
  • Webhook utilities - verifyWebhookSignature() for secure webhook handling
  • Actionable errors - Clear error messages that tell you how to fix issues

API Reference

Creating Link Tokens

Link tokens are used to initialize the frontend widget for user consent:

const token = await client.link.tokens.create({
  redirectUri: 'https://myapp.com/callback',
  userEmail: '[email protected]',  // Optional: pre-fill email
  webhookUrl: 'https://myapp.com/webhooks/myo',  // Optional: override default
  state: 'user_123',  // Optional: your internal reference
});

// Pass token.linkToken to your frontend
// Or redirect user to token.widgetUrl

Querying User Context

After a user has connected, query their data with natural language:

const response = await client.context.query({
  userId: '550e8400-e29b-41d4-a716-446655440000',
  query: 'What are this user\'s main interests?',
});
console.log(response.response);  // AI-generated answer
console.log(response.model);     // Model used

Multi-turn Conversations

// First query
const response1 = await client.context.query({
  userId,
  query: 'What does this user like to do?',
});

// Follow-up query with context
const response2 = await client.context.query({
  userId,
  query: 'Can you elaborate on the first hobby?',
  conversationHistory: [
    { role: 'user', content: 'What does this user like to do?' },
    { role: 'assistant', content: response1.response },
  ],
});

Configuring Webhooks

const config = await client.webhooks.configure(
  'https://myapp.com/webhooks/myo'
);
console.log(`Secret: ${config.webhookSecret}`);
// Store this secret securely for signature verification

Verifying Webhook Signatures

import { constructWebhookEvent, WebhookVerificationError } from '@myo/node';
import express from 'express';

const app = express();

app.post('/webhooks/myo', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const event = constructWebhookEvent(
      req.body,
      req.headers['x-myo-webhook-signature'] as string,
      process.env.WEBHOOK_SECRET!,
      { timestampHeader: req.headers['x-myo-webhook-timestamp'] as string }
    );

    if (event.type === 'link.completed') {
      const userId = event.data.user_id;
      // Handle the link completion
    }
  } catch (err) {
    if (err instanceof WebhookVerificationError) {
      return res.status(400).send(err.message);
    }
    throw err;
  }

  res.sendStatus(200);
});

Error Handling

The SDK raises specific exceptions for different error types:

import {
  MyoError,            // Base error
  AuthenticationError, // Invalid API key (401)
  PermissionError,     // No access to resource (403)
  NotFoundError,       // Resource not found (404)
  RateLimitError,      // Rate limit exceeded (429)
  ValidationError,     // Invalid parameters (422)
  APIError,            // Server errors (5xx)
} from '@myo/node';

try {
  const response = await client.context.query({ userId, query });
} catch (err) {
  if (err instanceof AuthenticationError) {
    console.log(`Check your API key: ${err.message}`);
  } else if (err instanceof PermissionError) {
    console.log(`User hasn't linked yet: ${err.message}`);
  } else if (err instanceof RateLimitError) {
    console.log(`Slow down! Retry after ${err.retryAfter} seconds`);
  } else if (err instanceof MyoError) {
    console.log(`API error: ${err.message}`);
  }
}

Configuration

const client = new MyoClient({
  apiKey: 'dev_xxx',                    // Or set MYO_API_KEY env var
  baseUrl: 'https://api.myo.dev',       // Or set MYO_BASE_URL env var
  timeout: 30000,                       // Request timeout in ms
  maxRetries: 3,                        // Retry attempts for failed requests
});

Requirements

  • Node.js 18+

License

MIT