Maintainx Sdk PatternsSAFE
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Overview
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
4f83675ca38aOBSERVED · 2026-10-09Host compatibility
What the documentation claims. We have not run a compatibility test.
| Host | Status | Notes |
|---|---|---|
| claude-code | mentioned | |
| cursor | mentioned |
What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
--- name: maintainx-sdk-patterns description: 'Learn MaintainX REST API patterns, pagination, filtering, and client architecture. Use when building robust API integrations, implementing pagination, or creating reusable SDK patterns for MaintainX. Trigger with phrases like "maintainx sdk", "maintainx api patterns", "maintainx pagination", "maintainx filtering", "maintainx client design". ' allowed-tools: Read, Write, Edit, Bash(npm:*), Grep version: 1.11.0 license: MIT author: Jeremy Longshore <[email protected]> tags: - saas - maintainx - api compatibility: Designed for Claude Code --- # MaintainX SDK Patterns ## Overview Production-grade patterns for building robust MaintainX API integrations with proper error handling, cursor-based pagination, retry logic, and type safety. ## Prerequisites - Completed `maintainx-install-auth` setup - TypeScript/Node.js familiarity - Understanding of REST API principles ## Instructions ### Step 1: Type-Safe Client with Generics ```typescript // src/maintainx/typed-client.ts import axios, { AxiosInstance, AxiosRequestConfig, AxiosError } from 'axios'; interface PaginatedResponse<T> { cursor: string | null; } interface WorkOrder { id: number; title: string; status: 'OPEN' | 'IN_PROGRESS' | 'ON_HOLD' | 'COMPLETED' | 'CLOSED'; priority: 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH'; description?: string; assignees: Array<{ type: 'USER' | 'TEAM'; id: number }>; assetId?: number; locationId?: number; createdAt: string; updatedAt: string; completedAt?: string; dueDate?: string; categories: string[]; } interface Asset { id: number; name: string; serialNumber?: string; model?: string; manufacturer?: string; locationId?: number; createdAt: string; } interface WorkOrdersResponse extends PaginatedResponse<WorkOrder> { workOrders: WorkOrder[]; } interface AssetsResponse extends PaginatedResponse<Asset> { assets: Asset[]; } export class MaintainXClient { private http: AxiosInstance; constructor(apiKey?: string) { const key = apiKey || process.env.MAINTAINX_API_KEY; if (!key) throw new Error('MAINTAINX_API_KEY required'); this.http = axios.create({ baseURL: 'https://api.getmaintainx.com/v1', headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json' }, timeout: 30_000, }); } async getWorkOrders(params?: Record<string, any>): Promise<WorkOrdersResponse> { const { data } = await this.http.get<WorkOrdersResponse>('/workorders', { params }); return data; } async getWorkOrder(id: number): Promise<WorkOrder> { const { data } = await this.http.get<WorkOrder>(`/workorders/${id}`); return data; } async createWorkOrder(input: Partial<WorkOrder>): Promise<WorkOrder> { const { data } = await this.http.post<WorkOrder>('/workorders', input); return data; } async updateWorkOrder(id: number, input: Partial<WorkOrder>): Promise<WorkOrder> { const { data } = await this.http.patch<WorkOrder>(`/workorders/${id}`, input); return data; } async getAssets(params?: Record<string, any>): Promise<AssetsResponse> { const { data } = await this.http.get<AssetsResponse>('/assets', { params }); return data; } async request<T = any>(method: string, path: string, body?: any): Promise<T> { const config: AxiosRequestConfig = { method, url: path, data: body }; const { data } = await this.http.request<T>(config); return data; } } ``` ### Step 2: Cursor-Based Pagination MaintainX uses cursor-based pagination. The response includes a `cursor` field; pass it as a query parameter to get the next page. ```typescript async function paginate<T>( fetcher: (cursor?: string) => Promise<{ cursor: string | null } & Record<string, T[]>>, key: string, ): Promise<T[]> { const all: T[] = []; let cursor: string | undefined; do { const response = await fetcher(cursor); const items = (response as any)[key] as T[]; all.push(...items); cursor = response.cursor ?? undefined; } while (cursor); return all; } // Usage const allWorkOrders = await paginate( (cursor) => client.getWorkOrders({ limit: 100, cursor, status: 'OPEN' }), 'workOrders', ); console.log(`Total open work orders: ${allWorkOrders.length}`); const allAssets = await paginate( (cursor) => client.getAssets({ limit: 100, cursor }), 'assets', ); console.log(`Total assets: ${allAssets.length}`); ``` ### Step 3: Retry with Exponential Backoff ```typescript async function withRetry<T>( fn: () => Promise<T>, maxRetries = 3, baseDelayMs = 1000, ): Promise<T> { for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await fn(); } catch (err: any) { const status = err?.response?.status; const isRetryable = status === 429 || (status >= 500 && status < 600); if (!isRetryable || attempt === maxRetries) throw err; // Honor Retry-After header if present const retryAfter = err.response?.headers?.['retry-after']; const delayMs = retryAfter ? parseInt(retryAfter) * 1000 : baseDelayMs * Math.pow(2, attempt) + Math.random() * 500; console.warn(`Retry ${attempt + 1}/${maxRetries} after ${delayMs}ms (HTTP ${status})`); await new Promise((r) => setTimeout(r, delayMs)); } } throw new Error('Unreachable'); } // Usage const wo = await withRetry(() => client.getWorkOrder(12345)); ``` ### Step 4: Batch Operations ```typescript import PQueue from 'p-queue'; const queue = new PQueue({ concurrency: 5, interval: 1000, intervalCap: 10 }); async function batchCreateWorkOrders(items: Array<Partial<WorkOrder>>): Promise<WorkOrder[]> { const results = await Promise.all( items.map((item) => queue.add(() => withRetry(() => client.createWorkOrder(item))) ), ); return results as WorkOrder[]; } // Create 50 PMs in controlled batches const pms = Array.from({ length: 50 }, (_, i) => ({ title: `Weekly Inspection -
Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
4f83675ca38afull audit observations/trust-audit/skill/jeremylongshore__maintainx-sdk-patterns.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-09 | 4f83675ca38a | SAFE | B | 89 | first audit |
Questions
What does the Maintainx Sdk Patterns skill do?
Model-agnostic agent-skills platform with a harness-free canonical layer, verified adapters, and the ccpi package manager. Explore at tonsofskills.com.
Is Maintainx Sdk Patterns safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Maintainx Sdk Patterns access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
Which assistants does Maintainx Sdk Patterns work with?
Its documentation mentions claude-code and cursor. That is what the text claims, not a compatibility test we ran.
How current is this page?
The grade is for one exact copy of the source (4f83675ca38a), read on 2026-10-09. The repository is watched, and a new audit runs when it changes — this is the first audit.