| 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.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
MaintainX SDK Patterns
Overview
Production-grade patterns for building robust MaintainX API integrations with proper error handling, pagination, and type safety.
Prerequisites
- Completed
maintainx-install-auth setup
- Understanding of REST API principles
- TypeScript/Node.js familiarity
Core API Endpoints
Available Endpoints
| Resource | Endpoint | Methods | Description |
|---|
| Work Orders | /workorders | GET, POST | Maintenance tasks |
| Work Requests | /workrequests | GET, POST | Maintenance requests |
| Assets | /assets | GET | Equipment tracking |
| Locations | /locations | GET | Facility/area hierarchy |
| Users | /users | GET | Team members |
| Parts | /parts | GET | Inventory items |
| Procedures | /procedures | GET | Standard checklists |
Instructions
Step 1: Type-Safe API Client
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
interface PaginatedResponse<T> {
[key: string]: T[];
nextCursor: string | null;
}
interface WorkOrder {
id: string;
title: string;
description?: string;
status: WorkOrderStatus;
priority: WorkOrderPriority;
assignees?: User[];
asset?: Asset;
location?: Location;
dueDate?: string;
completedAt?: string;
createdAt: string;
updatedAt: string;
}
type WorkOrderStatus = 'OPEN' | 'IN_PROGRESS' | 'ON_HOLD' | 'DONE';
type WorkOrderPriority = 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH';
{
: ;
: ;
?: ;
?: ;
?: ;
?: ;
: | | ;
}
{
: ;
: ;
?: ;
?: ;
}
{
: ;
: ;
: ;
: ;
: ;
}
{
?: ;
?: ;
}
{
?: ;
?: ;
?: ;
?: ;
?: ;
?: ;
?: ;
}
{
?: ;
?: [];
}
{
: ;
() {
apiKey = config?. || process..;
(!apiKey) {
();
}
. = axios.({
: config?. || ,
: config?. || ,
: {
: ,
: ,
},
});
.();
}
() {
....( {
.();
config;
});
....(
response,
{
(error.) {
{ status, data } = error.;
message = data?. || data?. || ;
.();
}
error;
}
);
}
(?: ): <<>> {
response = ..(, { params });
response.;
}
(: ): <> {
response = ..();
response.;
}
(: <>): <> {
response = ..(, data);
response.;
}
(?: ): <<>> {
response = ..(, { params });
response.;
}
(: ): <> {
response = ..();
response.;
}
(?: ): <<>> {
response = ..(, { params });
response.;
}
(: ): <> {
response = ..();
response.;
}
(?: ): <<>> {
response = ..(, { params });
response.;
}
(: ): <> {
response = ..();
response.;
}
}
Step 2: Cursor-Based Pagination
import { MaintainXClient } from '../api/maintainx-client';
interface PaginationOptions {
limit?: number;
maxPages?: number;
delayMs?: number;
}
export async function* paginate<T>(
fetchFn: (cursor?: string) => Promise<{ items: T[]; nextCursor: string | null }>,
options: PaginationOptions = {}
): AsyncGenerator<T[], void, unknown> {
const { limit = 100, maxPages = Infinity, delayMs = 0 } = options;
let cursor: string | undefined;
let pageCount = 0;
do {
const response = await fetchFn(cursor);
yield response.items;
cursor = response.nextCursor || undefined;
pageCount++;
if (delayMs > 0 && cursor) {
( (r, delayMs));
}
} (cursor && pageCount < maxPages);
}
(): <[]> {
: [] = [];
( batch (
(cursor) => {
response = client.({ ...params, cursor, : options. || });
{ : response., : response. };
},
options
)) {
allWorkOrders.(...batch);
}
allWorkOrders;
}
() {
workOrders = (
client,
{ : },
{ : , : }
);
.();
workOrders;
}
Step 3: Retry with Exponential Backoff
interface RetryConfig {
maxRetries: number;
baseDelayMs: number;
maxDelayMs: number;
retryableStatuses: number[];
}
const defaultConfig: RetryConfig = {
maxRetries: 3,
baseDelayMs: 1000,
maxDelayMs: 30000,
retryableStatuses: [429, 500, 502, 503, 504],
};
export async function withRetry<T>(
operation: () => Promise<T>,
config: Partial<RetryConfig> = {}
): Promise<T> {
const { maxRetries, baseDelayMs, maxDelayMs, retryableStatuses } = {
...defaultConfig,
...config,
};
let lastError: Error;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error: any) {
lastError = error;
const status = error.?.;
(status && !retryableStatuses.(status)) {
error;
}
(attempt === maxRetries) {
error;
}
exponentialDelay = baseDelayMs * .(, attempt);
jitter = .() * ;
delay = .(exponentialDelay + jitter, maxDelayMs);
.();
( (r, delay));
}
}
lastError!;
}
() {
(
client.({ : }),
{ : }
);
}
Step 4: Batch Operations
interface BatchConfig {
batchSize: number;
concurrency: number;
delayBetweenBatches: number;
}
export async function processBatch<T, R>(
items: T[],
processor: (item: T) => Promise<R>,
config: Partial<BatchConfig> = {}
): Promise<R[]> {
const { batchSize = 10, concurrency = 5, delayBetweenBatches = 100 } = config;
const results: R[] = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
const batchResults = await Promise.all(
batch.map(item => processor(item))
);
results.push(...batchResults);
if (i + batchSize < items.length) {
await new ( (r, delayBetweenBatches));
}
}
results;
}
(): <[]> {
(
workOrderData,
client.(data),
{ : , : }
);
}
Step 5: Query Builder Pattern
class WorkOrderQueryBuilder {
private params: WorkOrderQueryParams = {};
status(status: WorkOrderStatus): this {
this.params.status = status;
return this;
}
priority(priority: WorkOrderPriority): this {
this.params.priority = priority;
return this;
}
assignedTo(userId: string): this {
this.params.assigneeId = userId;
return this;
}
forAsset(assetId: string): this {
this.params.assetId = assetId;
return this;
}
atLocation(locationId: string): this {
this.params.locationId = locationId;
;
}
(: , : ): {
.. = start.();
.. = end.();
;
}
(: ): {
.. = count;
;
}
(): {
{ .... };
}
() {
client.(.());
}
}
() {
query = ()
.()
.()
.();
results = query.(client);
results;
}
Output
- Type-safe MaintainX client with full TypeScript support
- Cursor-based pagination utilities
- Retry logic with exponential backoff
- Batch processing helpers
- Fluent query builder
Error Handling
| Pattern | Use Case |
|---|
| Retry with backoff | Transient errors (429, 5xx) |
| Pagination | Large result sets |
| Batch processing | Bulk operations |
| Query builder | Complex filtering |
Resources
Next Steps
For core workflows, see maintainx-core-workflow-a (Work Orders) and maintainx-core-workflow-b (Assets).