Skip to content
Skillv1.0.0

mindtickle-sdk-patterns

Sdk Patterns for MindTickle. Trigger: "mindtickle sdk patterns".

by jeremylongshore(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from jeremylongshore/tons-of-skills-marketplace (plugins/saas-packs/mindtickle-pack/skills/mindtickle-sdk-patterns/SKILL.md). Install upstream with npx skills add jeremylongshore/tons-of-skills-marketplace --skill mindtickle-sdk-patterns. Copyright stays with the author (MIT).

MindTickle SDK Patterns

Overview

MindTickle's REST API serves sales enablement workflows including course management, quiz administration, user progress tracking, SCIM user provisioning, and coaching analytics. A structured SDK client is critical because MindTickle uses compound API keys with org-scoped tokens, returns progress data as nested completion trees with module-level granularity, and enforces strict SCIM schema compliance for user sync. These patterns provide org-aware authentication, typed models for training content hierarchies, progress query builders, and mock factories for sales readiness test scenarios.

Prerequisites

  • Node.js 18+, TypeScript 5+
  • MINDTICKLE_API_KEY environment variable (generated in Admin > Integrations > API Keys)
  • MINDTICKLE_ORG_ID for multi-org deployments
  • axios or node-fetch for HTTP transport

Singleton Client

interface MindTickleConfig {
  apiKey: string;
  orgId: string;
  baseUrl?: string;
  timeout?: number;
}

let client: MindTickleClient | null = null;

export function getMindTickleClient(overrides?: Partial<MindTickleConfig>): MindTickleClient {
  if (!client) {
    const config: MindTickleConfig = {
      apiKey: process.env.MINDTICKLE_API_KEY ?? '',
      orgId: process.env.MINDTICKLE_ORG_ID ?? '',
      baseUrl: 'https://api.mindtickle.com/v2',
      timeout: 15_000,
      ...overrides,
    };
    if (!config.apiKey || !config.orgId) throw new Error('MINDTICKLE_API_KEY and MINDTICKLE_ORG_ID are required');
    client = new MindTickleClient(config);
  }
  return client;
}

Error Wrapper

interface MindTickleError { statusCode: number; errorType: string; description: string; requestId: string; }

async function safeMindTickle<T>(fn: () => Promise<T>): Promise<T> {
  try { return await fn(); }
  catch (err: any) {
    const parsed: MindTickleError = {
      statusCode: err.response?.status ?? 500,
      errorType: err.response?.data?.error?.type ?? 'INTERNAL_ERROR',
      description: err.response?.data?.error?.description ?? err.message,
      requestId: err.response?.headers?.['x-request-id'] ?? 'unknown',
    };
    if (parsed.statusCode === 429) {
      const retryMs = parseInt(err.response?.headers?.['retry-after-ms'] ?? '3000', 10);
      await new Promise(r => setTimeout(r, retryMs));
      return fn();
    }
    if (parsed.errorType === 'SCIM_CONFLICT') throw new Error(`User already provisioned (req: ${parsed.requestId})`);
    if (parsed.statusCode === 403) throw new Error(`Org ${process.env.MINDTICKLE_ORG_ID} lacks permission: ${parsed.description}`);
    throw new Error(`MindTickle ${parsed.errorType} (${parsed.statusCode}): ${parsed.description} [${parsed.requestId}]`);
  }
}

Request Builder

class ProgressQueryBuilder {
  private params: Record<string, string> = {};
  forUser(userId: string) { this.params.user_id = userId; return this; }
  inCourse(courseId: string) { this.params.series_id = courseId; return this; }
  completedAfter(date: string) { this.params.completed_after = date; return this; }
  status(s: 'not_started' | 'in_progress' | 'completed') { this.params.status = s; return this; }
  page(n: number) { this.params.page = String(n); return this; }
  pageSize(n: number) { this.params.page_size = String(Math.min(n, 50)); return this; }
  build(): URLSearchParams { return new URLSearchParams(this.params); }
}

Response Types

interface Course { id: string; title: string; moduleCount: number; status: 'draft' | 'published' | 'archived'; createdAt: string; }
interface QuizResult { quizId: string; userId: string; score: number; passingScore: number; passed: boolean; attemptNumber: number; completedAt: string; }
interface UserProgress { userId: string; courseId: string; completedModules: number; totalModules: number; percentComplete: number; lastActivityAt: string; }
interface ScimUser { id: string; userName: string; displayName: string; emails: { value: string; primary: boolean }[]; active: boolean; groups: string[]; }

Middleware Pattern

type Middleware = (req: RequestInit, next: () => Promise<Response>) => Promise<Response>;

const orgScopeMiddleware = (orgId: string): Middleware => (req, next) => {
  req.headers = { ...req.headers as Record<string, string>, 'X-MindTickle-Org': orgId, Authorization: `Bearer ${process.env.MINDTICKLE_API_KEY}` };
  return next();
};
const metricsMiddleware: Middleware = async (req, next) => {
  const start = Date.now();
  const res = await next();
  const endpoint = new URL(req.url as string).pathname;
  console.log(`[mindtickle] ${req.method} ${endpoint} ${res.status} ${Date.now() - start}ms`);
  return res;
};

Testing Utilities

function mockCourse(overrides?: Partial<Course>): Course {
  return { id: 'series_abc', title: 'Q3 Product Training', moduleCount: 8, status: 'published', createdAt: '2025-07-01T00:00:00Z', ...overrides };
}
function mockProgress(userId: string, courseId: string): UserProgress {
  return { userId, courseId, completedModules: 5, totalModules: 8, percentComplete: 62.5, lastActivityAt: '2025-07-15T14:30:00Z' };
}
function mockScimUser(overrides?: Partial<ScimUser>): ScimUser {
  return { id: 'usr_test_001', userName: 'jsmith@acme.com', displayName: 'Jane Smith', emails: [{ value: 'jsmith@acme.com', primary: true }], active: true, groups: ['sales-east'], ...overrides };
}

Error Handling

Pattern When to Use Example
Retry with header delay 429 on progress or analytics endpoints Parse Retry-After-Ms header, wait exact duration, retry once
SCIM conflict resolution 409 when provisioning existing user Fetch existing user by email, update instead of create
Org scope validation 403 on cross-org resource access Verify MINDTICKLE_ORG_ID matches target course owner
Completion tree unwrap Nested module progress with null leaves Flatten tree, filter nulls, compute rollup percentage
Bulk operation chunking Enrolling 500+ users in a course Batch into groups of 50, sequential with rate limit pauses

Resources

Next Steps

Apply in mindtickle-core-workflow-a.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/jeremylongshore-tons-of-skills-marketplace-mindtickle-sd-dda85c/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

jeremylongshore-tons-of-skills-marketplace-mindtickle-sd-dda85c.ocm.jsonjson
{
  "ocm": "1",
  "id": "jeremylongshore-tons-of-skills-marketplace-mindtickle-sd-dda85c",
  "kind": "skill",
  "name": "mindtickle-sdk-patterns",
  "description": "Sdk Patterns for MindTickle. Trigger: \"mindtickle sdk patterns\".",
  "publisher": "jeremylongshore",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general"
    ],
    "tags": [
      "skill-md",
      "saas",
      "mindtickle",
      "sales",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Sdk Patterns for MindTickle. Trigger: \"mindtickle sdk patterns\"."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/jeremylongshore/tons-of-skills-marketplace",
      "path": "plugins/saas-packs/mindtickle-pack/skills/mindtickle-sdk-patterns/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/jeremylongshore/tons-of-skills-marketplace/blob/HEAD/plugins/saas-packs/mindtickle-pack/skills/mindtickle-sdk-patterns/SKILL.md",
      "key": "jeremylongshore/tons-of-skills-marketplace/plugins/saas-packs/mindtickle-pack/skills/mindtickle-sdk-patterns/SKILL.md"
    },
    "compatibility": "Designed for Claude Code",
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit"
    ],
    "license": "MIT"
  },
  "instructions": "# MindTickle SDK Patterns\n\n## Overview\n\nMindTickle's REST API serves sales enablement workflows including course management, quiz administration, user progress tracking, SCIM user provisioning, and coaching analytics. A structured SDK client is critical because MindTickle uses compound API keys with org-scoped tokens, returns progress data as nested completion trees with module-level granularity, and enforces strict SCIM schema compliance for user sync. These patterns provide org-aware authentication, typed models for training content hierarchies, progress query builders, and mock factories fo",
  "cost": {
    "context_tokens": 1576
  }
}

Fetch it by URL: GET /api/v1/registry/jeremylongshore-tons-of-skills-marketplace-mindtickle-sd-dda85c/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.