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

@mirats/diy-publisher-sdk

v1.0.3

Published

Node.js SDK for Mirats Publisher Platform API

Readme

Mirats Publisher Platform SDK for Node.js

npm version License: ISC

A comprehensive Node.js SDK for interacting with the Mirats Publisher Platform API. This SDK provides a simple, intuitive, and type-safe interface to access surveys, generate links, retrieve qualification criteria, and manage your survey operations programmatically.

Features

  • Simple API - Clean, intuitive methods for all API operations
  • Secure - Handles authentication automatically with your API keys
  • Lightweight - Minimal dependencies, fast performance
  • Error Handling - Comprehensive error handling with detailed error messages
  • Well Documented - Extensive documentation and examples
  • Promise-based - Modern async/await support
  • Type-safe - Clear parameter and return types

Table of Contents

Installation

Install the package using npm:

npm install @mirats/diy-publisher-sdk

Or using yarn:

yarn add @mirats/diy-publisher-sdk

Quick Start

Get started in minutes:

const MiratsPublisherSDK = require('@mirats/diy-publisher-sdk');

// Initialize the SDK
const sdk = new MiratsPublisherSDK({
  baseUrl: "https://api.publisher.miratsquanto.com/api/v1/publisher",
  webApiKey: "your_web_api_key",
  secretKey: "your_secret_key"
});

// Fetch surveys
async function fetchSurveys() {
  try {
    const result = await sdk.getAllSurveys({
      country: "US",
      rows: 10
    });
    
    console.log(`Found ${result.surveysCount} surveys`);
    return result.surveys;
  } catch (error) {
    console.error('Error:', error.message);
    throw error;
  }
}

Configuration

The SDK requires a configuration object with your API credentials.

Configuration Object

{
  baseUrl: "https://api.publisher.miratsquanto.com/api/v1/publisher",  // Optional
  webApiKey: "your_web_api_key",                                        // Required
  secretKey: "your_secret_key"                                          // Required
}

Configuration Fields

| Field | Type | Required | Default | Description | |-------|------|----------|---------|-------------| | baseUrl | string | No | https://api.publisher.miratsquanto.com/api/v1/publisher | Base URL for the API endpoint | | webApiKey | string | Yes | - | Your Web API Key (used as authorizationKey in request bodies) | | secretKey | string | Yes | - | Your Secret Key (used as publisher-authentication-key header) |

Getting Your API Keys

  1. Register on the Mirats Publisher Platform
  2. Navigate to your project settings
  3. Generate your Web API Key and Secret Key
  4. Keep your keys secure and never commit them to version control

Environment Variables (Recommended)

For better security, use environment variables:

const sdk = new MiratsPublisherSDK({
  baseUrl: process.env.MIRATS_API_BASE_URL,
  webApiKey: process.env.MIRATS_WEB_API_KEY,
  secretKey: process.env.MIRATS_SECRET_KEY
});

API Reference

Important: The fields loi and ir are deprecated and will be removed in a future version. Please use length_of_interview and incidence_rate instead. The maximum number of surveys per page (rows) has been increased from 100 to 500.

getAllSurveys(options)

Retrieves a paginated list of live surveys with advanced filtering options.

Parameters:

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | options.country | string | Yes | ISO 2-letter country code (e.g., "US", "IN", "GB") | | options.language | string | No | Language name (e.g., "English", "Spanish") | | options.rows | number | No | Number of surveys per page (1-500, default: 50) | | options.page | number | No | Page number for pagination (starts from 1, default: 1) | | options.lengthOfInterviewGTE | number | No | Minimum length of interview in minutes | | options.lengthOfInterviewLTE | number | No | Maximum length of interview in minutes | | options.CPIGTE | number | No | Minimum Cost Per Interview (CPI) | | options.CPILTE | number | No | Maximum Cost Per Interview (CPI) | | options.incidenceRateGTE | number | No | Minimum incidence rate (percentage) | | options.incidenceRateLTE | number | No | Maximum incidence rate (percentage) | | options.collectPII | boolean | No | Filter surveys that collect PII (Personally Identifiable Information) | | options.surveyGroupExists | boolean | No | Filter by whether a survey group exists |

Returns: Promise<Object>

Response structure:

{
  success: boolean,
  surveys: Array<Survey>,
  surveysCount: number,
  pagination: {
    totalDocuments: number,
    rows: number,
    page: number,
    totalPages: number
  },
  projectName: string,
  projectNumber: number,
  organisation: string
}

Survey Object Structure:

{
  _id: string,
  cost_per_interview: {
    value: number,
    currency_code: string
  },
  surveyNumber: number,
  survey_number: number,
  length_of_interview: number,          // Length of interview in minutes
  incidence_rate: number,              // Incidence rate as a percentage
  cpi: number,                          // Cost per interview
  country: string,
  countryCode: string,
  country_code: string,
  required_completes: number,
  overall_completes: number,
  revenue_per_click: number,
  survey_created_date: string,          // ISO 8601 date-time
  survey_last_updated_date: string        // ISO 8601 date-time
}

getSingleSurvey(surveyNumber)

Retrieves detailed information about a specific survey by its survey number.

Parameters:

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | surveyNumber | number or string | Yes | The unique survey number |

Returns: Promise<Object>

Response structure:

{
  length_of_interview: string,          // Length of interview in minutes
  incidence_rate: string,              // Incidence rate as a percentage
  survey_created_date: string,          // ISO 8601 date
  survey_last_updated_date: string,      // ISO 8601 date
  surveyNumber: number,
  qualification: Array<QualificationItem>,
  projectName: string,
  projectNumber: number,
  organisation: string
}

generateSurveyLink(surveyNumber)

Generates test and live links for a specific survey.

Parameters:

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | surveyNumber | number or string | Yes | The unique survey number |

Returns: Promise<Object>

Response structure:

{
  testLink: string,   // URL for testing the survey
  liveLink: string    // URL for live survey distribution
}

getSurveyQualification(surveyNumber)

Retrieves qualification criteria for a specific survey, including questions, valid options, quotas, and question types.

Parameters:

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | surveyNumber | number or string | Yes | The unique survey number |

Returns: Promise<Object>

Response structure:

{
  surveyNumber: number,
  qualification: Array<QualificationItem>,
  projectName: string,
  projectNumber: number,
  organisation: string
}

Examples

Example 1: Fetch Surveys with Filters

const MiratsPublisherSDK = require('@mirats/diy-publisher-sdk');

const sdk = new MiratsPublisherSDK({
  webApiKey: process.env.MIRATS_WEB_API_KEY,
  secretKey: process.env.MIRATS_SECRET_KEY
});

async function findSurveys() {
  try {
    const result = await sdk.getAllSurveys({
      country: "US",
      language: "English",
      rows: 25,
      page: 1,
      lengthOfInterviewGTE: 5,
      lengthOfInterviewLTE: 15,
      CPIGTE: 1.0,
      CPILTE: 3.0,
      incidenceRateGTE: 10,
      incidenceRateLTE: 30
    });

    console.log(`Found ${result.surveysCount} surveys`);
    console.log(`Total available: ${result.pagination.totalDocuments}`);
    console.log(`Page ${result.pagination.page} of ${result.pagination.totalPages}`);

    result.surveys.forEach(survey => {
      console.log(`
        Survey #${survey.surveyNumber}
        CPI: $${survey.cpi}
        Length of Interview: ${survey.length_of_interview} minutes
        Incidence Rate: ${survey.incidence_rate}%
        Country: ${survey.country}
        Created: ${survey.survey_created_date}
        Last Updated: ${survey.survey_last_updated_date}
      `);
    });

    return result;
  } catch (error) {
    console.error('Failed to fetch surveys:', error.message);
    throw error;
  }
}

Example 2: Get Survey Details and Qualification

async function analyzeSurvey(surveyNumber) {
  try {
    // Get survey details
    const survey = await sdk.getSingleSurvey(surveyNumber);
    
    console.log(`Survey: ${survey.surveyNumber}`);
    console.log(`Project: ${survey.projectName}`);
    console.log(`Length of Interview: ${survey.length_of_interview} minutes`);
    console.log(`Incidence Rate: ${survey.incidence_rate}%`);

    // Get qualification criteria
    const qualification = await sdk.getSurveyQualification(surveyNumber);
    
    console.log(`\nQualification Criteria:`);
    qualification.qualification.forEach((q, index) => {
      console.log(`\n${index + 1}. ${q.question}`);
      console.log(`   Type: ${q.questionType}`);
      console.log(`   Valid Options: ${JSON.stringify(q.validOptions)}`);
      if (Object.keys(q.quotas).length > 0) {
        console.log(`   Quotas: ${JSON.stringify(q.quotas)}`);
      }
    });

    return { survey, qualification };
  } catch (error) {
    console.error(`Error analyzing survey ${surveyNumber}:`, error.message);
    throw error;
  }
}

Example 3: Generate and Use Survey Links

async function generateSurveyLinks(surveyNumber) {
  try {
    const links = await sdk.generateSurveyLink(surveyNumber);
    
    console.log('Survey Links Generated:');
    console.log(`Test Link: ${links.testLink}`);
    console.log(`Live Link: ${links.liveLink}`);
    
    // Use test link for quality assurance
    // Use live link for actual survey distribution
    
    return links;
  } catch (error) {
    console.error('Failed to generate links:', error.message);
    throw error;
  }
}

Example 4: Pagination - Fetch All Surveys

async function fetchAllSurveys(country) {
  const allSurveys = [];
  let currentPage = 1;
  let hasMorePages = true;

  try {
    while (hasMorePages) {
      const result = await sdk.getAllSurveys({
        country: country,
        rows: 500,  // Maximum per page
        page: currentPage
      });

      allSurveys.push(...result.surveys);
      
      hasMorePages = currentPage < result.pagination.totalPages;
      currentPage++;
      
      console.log(`Fetched page ${result.pagination.page} of ${result.pagination.totalPages}`);
    }

    console.log(`Total surveys fetched: ${allSurveys.length}`);
    return allSurveys;
  } catch (error) {
    console.error('Error fetching all surveys:', error.message);
    throw error;
  }
}

Example 5: Filter Surveys by Multiple Criteria

async function findTargetSurveys() {
  try {
    const result = await sdk.getAllSurveys({
      country: "US",
      language: "English",
      lengthOfInterviewGTE: 10,      // At least 10 minutes
      lengthOfInterviewLTE: 20,     // At most 20 minutes
      CPIGTE: 1.5,                   // Minimum $1.50 CPI
      CPILTE: 3.0,                   // Maximum $3.00 CPI
      incidenceRateGTE: 15,          // At least 15% incidence rate
      collectPII: false,             // Don't collect PII
      rows: 50
    });

    // Filter further in your application if needed
    const highValueSurveys = result.surveys.filter(survey => 
      survey.cpi >= 2.0 && survey.incidence_rate >= 20
    );

    console.log(`Found ${highValueSurveys.length} high-value surveys`);
    return highValueSurveys;
  } catch (error) {
    console.error('Error finding target surveys:', error.message);
    throw error;
  }
}

Error Handling

The SDK provides comprehensive error handling with detailed error information.

Error Object Structure

When an error occurs, the SDK throws an error object with the following properties:

{
  message: string,    // Human-readable error message
  status: number,     // HTTP status code (if available)
  code: number,       // API error code (if available)
  data: object       // Full error response from API (if available)
}

Error Handling Examples

Basic Error Handling

try {
  const surveys = await sdk.getAllSurveys({ country: "US" });
} catch (error) {
  console.error('Error:', error.message);
  
  if (error.status) {
    console.error('HTTP Status:', error.status);
  }
  
  if (error.code) {
    console.error('API Error Code:', error.code);
  }
  
  if (error.data) {
    console.error('Error Details:', error.data);
  }
}

Handling Specific Error Types

async function safeGetSurveys(country) {
  try {
    return await sdk.getAllSurveys({ country });
  } catch (error) {
    // Handle network errors
    if (!error.status) {
      console.error('Network error:', error.message);
      throw new Error('Unable to connect to API. Please check your internet connection.');
    }
    
    // Handle authentication errors
    if (error.status === 401 || error.status === 403) {
      console.error('Authentication failed:', error.message);
      throw new Error('Invalid API credentials. Please check your webApiKey and secretKey.');
    }
    
    // Handle validation errors
    if (error.status === 400) {
      console.error('Invalid request:', error.message);
      throw new Error(`Invalid request: ${error.message}`);
    }
    
    // Handle server errors
    if (error.status >= 500) {
      console.error('Server error:', error.message);
      throw new Error('API server error. Please try again later.');
    }
    
    // Re-throw unknown errors
    throw error;
  }
}

Retry Logic Example

async function getSurveysWithRetry(country, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await sdk.getAllSurveys({ country });
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      
      // Retry on network errors or 5xx errors
      if (!error.status || error.status >= 500) {
        console.log(`Attempt ${attempt} failed, retrying...`);
        await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
        continue;
      }
      
      // Don't retry on client errors (4xx)
      throw error;
    }
  }
}

Requirements

  • Node.js version 14.0.0 or higher
  • npm version 6.0.0 or higher (or yarn)

Dependencies

  • axios ^1.6.0 - HTTP client for API requests

License

ISC

Support

For issues, questions, or contributions:


Made with ❤️ by the Mirats Team