Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

TypeScript SDK

The official TypeScript SDK provides full type safety, async/await support, and convenient methods for all API operations.

Terminal window
npm install @mando/sdk
# or
yarn add @mando/sdk
# or
pnpm add @mando/sdk
  • Node.js 18+ or modern browser
  • TypeScript 5.0+ (optional but recommended)
import { MandoClient } from '@mando/sdk';
const client = new MandoClient({
apiKey: process.env.MANDO_API_KEY!,
baseUrl: 'https://www.mando.fi/api' // optional, this is the default
});
// List all products
const products = await client.plu.list();
console.log(products.data);
const client = new MandoClient({
// Required
apiKey: 'your-api-key',
// Optional
baseUrl: 'https://www.mando.fi/api',
timeout: 30000, // 30 seconds
retries: 3,
retryDelay: 1000, // 1 second base delay
});
// List all products
const products = await client.plu.list();
// With pagination
const page = await client.plu.list({
page: 1,
pageSize: 50
});
// With filters
const active = await client.plu.list({
active: true,
groupId: 'beverages'
});
const product = await client.plu.get('550e8400-e29b-41d4-a716-446655440000');
console.log(product.data.name);
const newProduct = await client.plu.create({
name: 'Espresso',
price: 3.50,
groupId: 'beverages',
taxId: 'standard-vat'
});
console.log(newProduct.data.id);
const updated = await client.plu.update('product-id', {
price: 4.00,
active: true
});
import { MandoClient, MandoError } from '@mando/sdk';
try {
const product = await client.plu.get('invalid-id');
} catch (error) {
if (error instanceof MandoError) {
console.error(`Error ${error.status}: ${error.message}`);
console.error(`Code: ${error.code}`);
// Handle specific errors
if (error.status === 404) {
console.log('Product not found');
} else if (error.status === 429) {
// Rate limited - retry after delay
const retryAfter = error.retryAfter || 60;
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
}
} else {
throw error;
}
}

Iterate through all pages automatically:

// Async iterator for all products
for await (const product of client.plu.listAll()) {
console.log(product.name);
}
// Or collect all at once
const allProducts = await client.plu.listAll().toArray();

All responses are fully typed:

import type { Plu, Customer, Sale } from '@mando/sdk';
async function getProductNames(): Promise<string[]> {
const response = await client.plu.list();
return response.data.map((plu: Plu) => plu.name);
}
const client = new MandoClient({
apiKey: 'your-key',
headers: {
'X-Custom-Header': 'value'
}
});
client.onRequest((config) => {
console.log(`Making request to ${config.url}`);
return config;
});
client.onResponse((response) => {
console.log(`Received ${response.status}`);
return response;
});
const controller = new AbortController();
// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);
try {
const products = await client.plu.list({
signal: controller.signal
});
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request was cancelled');
}
}

The SDK works in modern browsers:

<script type="module">
import { MandoClient } from 'https://cdn.jsdelivr.net/npm/@mando/sdk/dist/browser.mjs';
const client = new MandoClient({
apiKey: 'your-key'
});
const products = await client.plu.list();
console.log(products);
</script>
import { MandoClient } from '@mando/sdk';
async function syncProducts() {
const client = new MandoClient({
apiKey: process.env.MANDO_API_KEY!
});
// Get all products
const products = await client.plu.listAll().toArray();
// Update prices
for (const product of products) {
if (product.price < 1.00) {
await client.plu.update(product.id, {
price: 1.00
});
console.log(`Updated ${product.name} to minimum price`);
}
}
console.log(`Processed ${products.length} products`);
}
syncProducts();