JavaScript / Node.js Examples
Complete code examples for using the TakeTheme API with JavaScript and Node.js.
Setup
Using Fetch (Node.js 18+)
const API_KEY = process.env.TAKETHEME_API_KEY;
const BASE_URL = "https://api.taketheme.com/api/v1";
async function apiRequest(endpoint, options = {}) {
const response = await fetch(`${BASE_URL}${endpoint}`, {
...options,
headers: {
tt-api-key: ` ${API_KEY}`,
"Content-Type": "application/json",
...options.headers,
},
body: options.body ? JSON.stringify(options.body) : undefined,
});
if (!response.ok) {
const error = await response.json();
throw new Error(`API Error: ${error.message}`);
}
return response.json();
}
Products
List All Products
// Using fetch
const { data: products, pagination } = await apiRequest("/products?limit=25");
console.log(`Found ${pagination.total_count} products`);
products.forEach((product) => {
console.log(`- ${product.title} ($${product.price})`);
});
Get a Single Product
// Using fetch
const { data: product } = await apiRequest("/products/prod_abc123");
console.log(product.title, product.variants);
Create a Product
// Using fetch
const { data: newProduct } = await apiRequest("/products", {
method: "POST",
body: {
title: "Premium T-Shirt",
description: "Comfortable cotton t-shirt",
price: 29.99,
currency: "USD",
status: "active",
variants: [
{
title: "Small",
sku: "TSHIRT-S",
price: 29.99,
inventory_quantity: 100,
},
{
title: "Medium",
sku: "TSHIRT-M",
price: 29.99,
inventory_quantity: 150,
},
{ title: "Large", sku: "TSHIRT-L", price: 29.99, inventory_quantity: 75 },
],
images: [{ src: "https://example.com/tshirt.jpg", alt: "Premium T-Shirt" }],
},
});
console.log(`Created product: ${newProduct.id}`);
Update a Product
// Using fetch
const { data: updated } = await apiRequest("/products/prod_abc123", {
method: "PATCH",
body: {
price: 34.99,
status: "active",
},
});
Delete a Product
// Using fetch
await apiRequest("/products/prod_abc123", { method: "DELETE" });
Orders
List Orders
// Fetch recent orders
const { data: orders } = await apiRequest("/orders?status=pending&limit=50");
// With date filtering
const { data: recentOrders } = await apiRequest(
"/orders?created_at_min=2024-01-01T00:00:00Z"
);
Create an Order
const { data: order } = await apiRequest("/orders", {
method: "POST",
body: {
customer: {
email: "customer@example.com",
first_name: "John",
last_name: "Doe",
},
line_items: [
{
variant_id: "var_abc123",
quantity: 2,
price: 29.99,
},
],
shipping_address: {
first_name: "John",
last_name: "Doe",
address1: "123 Main Street",
city: "New York",
province: "NY",
postal_code: "10001",
country: "US",
phone: "+1-555-123-4567",
},
shipping_line: {
title: "Standard Shipping",
price: 5.99,
},
},
});
console.log(`Order created: ${order.order_number}`);
Fulfill an Order
const { data: fulfillment } = await apiRequest(
`/orders/${orderId}/fulfillments`,
{
method: "POST",
body: {
line_items: [{ id: "li_abc123", quantity: 2 }],
tracking_number: "1Z999AA10123456784",
tracking_company: "UPS",
tracking_url:
"https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784",
notify_customer: true,
},
}
);
Cancel an Order
const { data: cancelled } = await apiRequest(`/orders/${orderId}/cancel`, {
method: "POST",
body: {
reason: "customer_request",
restock: true,
notify_customer: true,
},
});
Customers
Search Customers
const { data: customers } = await apiRequest(
"/customers?email=john@example.com"
);
// Search by multiple criteria
const { data: vipCustomers } = await apiRequest(
"/customers?tags=vip&orders_count_min=10"
);
Create a Customer
const { data: customer } = await apiRequest("/customers", {
method: "POST",
body: {
email: "newcustomer@example.com",
first_name: "Jane",
last_name: "Smith",
phone: "+1-555-987-6543",
addresses: [
{
address1: "456 Oak Avenue",
city: "Los Angeles",
province: "CA",
postal_code: "90001",
country: "US",
default: true,
},
],
tags: ["newsletter", "loyalty-program"],
accepts_marketing: true,
},
});
Inventory
Update Stock Levels
// Set absolute quantity
await apiRequest("/inventory/var_abc123", {
method: "POST",
body: {
location_id: "loc_main",
available: 100,
},
});
// Adjust by delta
await apiRequest("/inventory/var_abc123/adjust", {
method: "POST",
body: {
location_id: "loc_main",
adjustment: -5,
reason: "Damaged stock",
},
});
Webhooks
Register a Webhook
const { data: webhook } = await apiRequest("/webhooks", {
method: "POST",
body: {
topic: "orders/created",
address: "https://your-app.com/webhooks/orders",
format: "json",
},
});
console.log(`Webhook registered: ${webhook.id}`);
Verify Webhook Signatures
import crypto from "crypto";
function verifyWebhook(payload, signature, secret) {
const hmac = crypto.createHmac("sha256", secret);
hmac.update(payload);
const digest = hmac.digest("base64");
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}
// Express.js middleware
app.post(
"/webhooks/orders",
express.raw({ type: "application/json" }),
(req, res) => {
const signature = req.headers["x-taketheme-signature"];
if (!verifyWebhook(req.body, signature, WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(req.body);
console.log("Order created:", event.data.order_number);
res.status(200).send("OK");
}
);
Pagination Helper
async function* paginate(endpoint, params = {}) {
let cursor = null;
do {
const url = new URL(`${BASE_URL}${endpoint}`);
Object.entries(params).forEach(([key, value]) => {
url.searchParams.set(key, value);
});
url.searchParams.set("limit", "100");
if (cursor) url.searchParams.set("cursor", cursor);
const response = await fetch(url, {
headers: { tt-api-key: ` ${API_KEY}` },
});
const { data, pagination } = await response.json();
for (const item of data) {
yield item;
}
cursor = pagination.next_cursor;
} while (cursor);
}
// Usage
for await (const product of paginate("/products")) {
console.log(product.title);
}
// Collect all
const allProducts = [];
for await (const product of paginate("/products")) {
allProducts.push(product);
}
Error Handling
class TakeThemeError extends Error {
constructor(response, data) {
super(data.message || data.name || "Unknown error");
this.status = data.status || response.status;
this.code = data.code; // Only present on some errors like rate limits
}
}
async function apiRequest(endpoint, options = {}) {
const response = await fetch(`${BASE_URL}${endpoint}`, {
...options,
headers: {
"tt-api-key": API_KEY,
"Content-Type": "application/json",
...options.headers,
},
body: options.body ? JSON.stringify(options.body) : undefined,
});
const data = await response.json();
if (!response.ok) {
throw new TakeThemeError(response, data);
}
return data;
}
// Usage
try {
await apiRequest("/products", {
method: "POST",
body: { title: "" }, // Invalid: empty title
});
} catch (error) {
if (error instanceof TakeThemeError) {
if (error.status === 400) {
console.log(`Validation error: ${error.message}`);
} else if (error.status === 429) {
console.log("Rate limited, retry later");
} else if (error.status === 401) {
console.log("Authentication failed");
} else {
console.log(`Error: ${error.message}`);
}
}
}
Complete Example: Sync Products
import fs from "fs/promises";
const API_KEY = process.env.TAKETHEME_API_KEY;
const BASE_URL = "https://api.taketheme.com/api/v1";
async function syncProducts() {
console.log("Starting product sync...");
// Read local product data
const localProducts = JSON.parse(
await fs.readFile("./products.json", "utf-8")
);
// Fetch existing products
const existingProducts = new Map();
for await (const product of paginate("/products")) {
existingProducts.set(product.sku, product);
}
console.log(`Found ${existingProducts.size} existing products`);
// Sync each product
for (const local of localProducts) {
const existing = existingProducts.get(local.sku);
try {
if (existing) {
// Update existing
await apiRequest(`/products/${existing.id}`, {
method: "PATCH",
body: {
title: local.title,
price: local.price,
inventory_quantity: local.stock,
},
});
console.log(`Updated: ${local.sku}`);
} else {
// Create new
await apiRequest("/products", {
method: "POST",
body: local,
});
console.log(`Created: ${local.sku}`);
}
} catch (error) {
console.error(`Failed to sync ${local.sku}:`, error.message);
}
// Rate limit safety
await new Promise((r) => setTimeout(r, 100));
}
console.log("Sync complete!");
}
syncProducts().catch(console.error);