@myo-devs/node
v0.1.0
Published
Official Node.js SDK for the Myo Platform
Maintainers
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/nodeGetting 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 production3. 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 time5. 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 usedReal-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(), notclient.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.widgetUrlQuerying 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 usedMulti-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 verificationVerifying 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
