Flow Myna

Node.js SDK

Official Flow Myna SDK for Node.js 18+

The official Node.js SDK for Flow Myna provides a modern, TypeScript-first interface for recording process events and managing objects. It includes full TypeScript support, automatic retries, and Promise-based APIs.

Installation

Install with npm

npm install @flowmyna/sdk

Quick Start

Basic Usage

import { FlowMyna } from '@flowmyna/sdk';


// Initialize the client
const client = new FlowMyna({
  apiKey: 'fm_live_your_key_here'
});


// Record an event
await client.recordEvent({
  event: 'Order Placed',
  objects: [
    { type: 'Order', id: 'ORD-123' },
    { type: 'Customer', id: 'CUST-456' }
  ],
  properties: { total: 149.99 }
});


// Upsert an object
await client.upsertObject({
  type: 'Customer',
  id: 'CUST-456',
  properties: {
    name: 'Jane Doe',
    email: 'jane@example.com'
  }
});

Configuration

  • Name
    apiKey
    Type
    string
    Required
    required
    Description
    Your Flow Myna API key (starts with fm_live_)
  • Name
    baseUrl
    Type
    string
    Description
    API base URL. Defaults to https://api.flowmyna.com/api/public/v1
  • Name
    timeout
    Type
    number
    Description
    Request timeout in milliseconds. Default: 30000
  • Name
    maxRetries
    Type
    number
    Description
    Maximum number of retry attempts. Default: 3

Configuration Options

import { FlowMyna } from '@flowmyna/sdk';


// Using environment variable (recommended)
const client = new FlowMyna({
  apiKey: process.env.FLOWMYNA_API_KEY!
});


// With custom configuration
const clientWithOptions = new FlowMyna({
  apiKey: 'fm_live_xxx',
  timeout: 60000,      // 60 second timeout
  maxRetries: 5,       // Retry up to 5 times
});


// For testing/development
const devClient = new FlowMyna({
  apiKey: 'fm_live_xxx',
  baseUrl: 'https://staging-api.flowmyna.com/api/public/v1'
});

recordEvent()

Record a process event with associated objects.

  • Name
    event
    Type
    string
    Required
    required
    Description
    Event name (1-200 characters)
  • Name
    objects
    Type
    EventObject[]
    Required
    required
    Description
    Array of objects involved in the event
  • Name
    timestamp
    Type
    string | Date
    Description
    When the event occurred (ISO 8601 string or Date object)
  • Name
    properties
    Type
    Record<string, unknown>
    Description
    Additional event properties

recordEvent() Examples

// Simple event
await client.recordEvent({
  event: 'Order Created',
  objects: [{ type: 'Order', id: 'ORD-123' }]
});


// With timestamp (Date object)
await client.recordEvent({
  event: 'Order Shipped',
  objects: [
    { type: 'Order', id: 'ORD-123' },
    { type: 'Shipment', id: 'SHIP-456' }
  ],
  timestamp: new Date()
});


// With timestamp (ISO string)
await client.recordEvent({
  event: 'Order Delivered',
  objects: [{ type: 'Order', id: 'ORD-123' }],
  timestamp: '2024-01-15T10:30:00Z'
});


// With properties
await client.recordEvent({
  event: 'Payment Processed',
  objects: [
    { type: 'Order', id: 'ORD-123' },
    { type: 'Payment', id: 'PAY-789' }
  ],
  properties: {
    amount: 149.99,
    currency: 'USD',
    method: 'credit_card'
  }
});


// With object properties (merged on upsert)
await client.recordEvent({
  event: 'Customer Login',
  objects: [{
    type: 'Customer',
    id: 'CUST-456',
    properties: {
      lastLogin: new Date().toISOString(),
      loginCount: 42
    }
  }]
});

upsertObject()

Create or update an object with properties (upsert semantics).

  • Name
    type
    Type
    string
    Required
    required
    Description
    Object type (1-100 characters)
  • Name
    id
    Type
    string
    Required
    required
    Description
    Object ID (1-500 characters)
  • Name
    properties
    Type
    Record<string, unknown>
    Description
    Object properties (merged with existing)

upsertObject() Examples

// Upsert a customer
const result = await client.upsertObject({
  type: 'Customer',
  id: 'CUST-456',
  properties: {
    name: 'Jane Doe',
    email: 'jane@example.com',
    tier: 'gold',
    signupDate: '2023-01-15'
  }
});


console.log(`Object ${result.created ? 'created' : 'updated'}`);
console.log(`Internal ID: ${result.objectId}`);


// Update properties (properties are merged)
await client.upsertObject({
  type: 'Customer',
  id: 'CUST-456',
  properties: {
    lifetimeValue: 5420.00,  // Added
    tier: 'platinum'          // Updated
  }
});


// Upsert without properties (just ensures object exists)
await client.upsertObject({ type: 'Order', id: 'ORD-123' });

Batch Operations

Send multiple events or objects efficiently in a single request.

Batch Examples

// Batch record events (up to 100 per call)
const events = [
  {
    event: 'Case Opened',
    timestamp: '2024-01-01T09:00:00Z',
    objects: [{ type: 'Case', id: 'CASE-001' }],
    properties: { priority: 'high' }
  },
  {
    event: 'Case Assigned',
    timestamp: '2024-01-01T09:15:00Z',
    objects: [
      { type: 'Case', id: 'CASE-001' },
      { type: 'Agent', id: 'AGENT-A' }
    ]
  },
  {
    event: 'Case Resolved',
    timestamp: '2024-01-01T14:30:00Z',
    objects: [{ type: 'Case', id: 'CASE-001' }]
  }
];


const result = await client.recordEventBatch(events);
console.log(`Processed: ${result.processed}, Failed: ${result.failed}`);


// Batch upsert objects
const customers = Array.from({ length: 100 }, (_, i) => ({
  type: 'Customer',
  id: `CUST-${String(i).padStart(3, '0')}`,
  properties: { index: i }
}));


const upsertResult = await client.upsertObjectBatch(customers);
console.log(`Upserted ${upsertResult.processed} objects`);

health()

Verify API key and get workspace/dataset information.

Health Check

// Check API key and connection
const health = await client.health();


console.log(`Status: ${health.status}`);
console.log(`Workspace: ${health.workspaceName}`);
console.log(`Dataset: ${health.datasetName}`);
console.log(`Key Name: ${health.apiKeyName}`);


// Use in startup validation
async function validateFlowMynaConnection(): Promise<boolean> {
  try {
    const health = await client.health();
    console.log('✓ Connected to Flow Myna');
    console.log(`  Workspace: ${health.workspaceName}`);
    console.log(`  Dataset: ${health.datasetName}`);
    return true;
  } catch (error) {
    console.error('✗ Flow Myna connection failed:', error);
    return false;
  }
}

Error Handling

Error Handling

import { FlowMyna } from '@flowmyna/sdk';
import {
  FlowMynaError,
  AuthenticationError,
  ValidationError,
  RateLimitError,
  ServerError
} from '@flowmyna/sdk/errors';


const client = new FlowMyna({ apiKey: 'fm_live_xxx' });


try {
  await client.recordEvent({
    event: 'Order Placed',
    objects: [{ type: 'Order', id: 'ORD-123' }]
  });
} catch (error) {
  if (error instanceof AuthenticationError) {
    // Invalid, revoked, or expired API key
    console.error('Authentication failed:', error.message);
  } else if (error instanceof ValidationError) {
    // Invalid request data
    console.error('Validation error:', error.message);
  } else if (error instanceof RateLimitError) {
    // Rate limited (429)
    console.error(`Rate limited. Retry after: ${error.retryAfter}`);
  } else if (error instanceof ServerError) {
    // Server error (5xx)
    console.error('Server error:', error.message);
  } else if (error instanceof FlowMynaError) {
    // Base exception for all SDK errors
    console.error('Flow Myna error:', error.message);
  }
}

TypeScript Types

The SDK exports all types for full TypeScript support:

TypeScript Types

import {
  FlowMyna,
  FlowMynaConfig,
  EventRequest,
  EventObject,
  EventResponse,
  ObjectUpsertRequest,
  ObjectUpsertResponse,
  EventBatchResponse,
  ObjectBatchResponse,
  HealthResponse
} from '@flowmyna/sdk';


// Typed event
const event: EventRequest = {
  event: 'Order Placed',
  objects: [
    { type: 'Order', id: 'ORD-123' }
  ],
  timestamp: new Date().toISOString(),
  properties: {
    total: 149.99,
    currency: 'USD'
  }
};


// Typed configuration
const config: FlowMynaConfig = {
  apiKey: process.env.FLOWMYNA_API_KEY!,
  timeout: 30000,
  maxRetries: 3
};


const client = new FlowMyna(config);


// Response is fully typed
const response: EventResponse = await client.recordEvent(event);
console.log(response.eventId);

AI-Assisted Integration

Want an AI assistant to help integrate Flow Myna into your codebase? We provide a comprehensive prompt that guides the AI through analyzing your code, suggesting events to track, and implementing the integration step-by-step.

Complete Example

E-commerce Integration

import { FlowMyna } from '@flowmyna/sdk';
import { FlowMynaError } from '@flowmyna/sdk/errors';


// Types for your application
interface Order {
  id: string;
  customerId: string;
  customerEmail: string;
  customerName: string;
  total: number;
  currency: string;
  channel: string;
  items: OrderItem[];
  createdAt: Date;
}


interface OrderItem {
  productId: string;
  quantity: number;
  price: number;
}


// Initialize client
const client = new FlowMyna({
  apiKey: process.env.FLOWMYNA_API_KEY!
});


// Validate connection on startup
async function init() {
  const health = await client.health();
  console.log(`Connected to ${health.workspaceName}`);
}


async function processOrder(order: Order) {
  try {
    // Upsert customer with details
    await client.upsertObject({
      type: 'Customer',
      id: order.customerId,
      properties: {
        email: order.customerEmail,
        name: order.customerName
      }
    });


    // Record order creation
    await client.recordEvent({
      event: 'Order Created',
      objects: [
        {
          type: 'Order',
          id: order.id,
          properties: {
            total: order.total,
            currency: order.currency,
            itemsCount: order.items.length
          }
        },
        { type: 'Customer', id: order.customerId }
      ],
      properties: { channel: order.channel }
    });


    // Record each item
    for (const item of order.items) {
      await client.recordEvent({
        event: 'Item Added',
        objects: [
          { type: 'Order', id: order.id },
          { type: 'Product', id: item.productId }
        ],
        properties: {
          quantity: item.quantity,
          price: item.price
        }
      });
    }


  } catch (error) {
    if (error instanceof FlowMynaError) {
      console.error(`Failed to record order ${order.id}:`, error.message);
    }
    throw error;
  }
}


async function importHistoricalOrders(orders: Order[]) {
  const events = orders.map(order => ({
    event: 'Order Created',
    timestamp: order.createdAt.toISOString(),
    objects: [
      { type: 'Order', id: order.id },
      { type: 'Customer', id: order.customerId }
    ]
  }));


  // Send in batches of 100
  for (let i = 0; i < events.length; i += 100) {
    const batch = events.slice(i, i + 100);
    const result = await client.recordEventBatch(batch);
    console.log(`Imported batch: ${result.processed} events`);
  }
}


// Start the application
init();