Skip to content

TypeScript SDK

Installation (Coming Soon)

Terminal window
npm install @xqr/sdk

Quick Start

import { XQR } from "@xqr/sdk";
const xqr = new XQR({ apiKey: process.env.XQR_API_KEY! });
// Create a short link
const link = await xqr.links.create({
url: "https://example.com",
customSlug: "my-link",
labels: ["campaign"],
});
console.log(link.shortUrl); // https://xqr.co/my-link
// Create a link with routing rules
const link = await xqr.links.create({
url: "https://example.com/default",
customSlug: "global-promo",
labels: ["promo", "q1"],
routingRules: [
{
destination: "https://example.de/promo",
priority: 1,
conditions: { countries: ["DE", "AT", "CH"], countryMode: "include" },
},
],
expiresAt: new Date("2026-09-30"),
});
// List links with auto-pagination
for await (const link of xqr.links.list({ label: "campaign" })) {
console.log(link.shortCode, link.scanCount);
}
// Update a link
await xqr.links.update(link.id, {
url: "https://example.com/updated",
enabled: false,
});
// Delete a link
await xqr.links.delete(link.id);
// Bulk create
const result = await xqr.links.bulkCreate([
{ url: "https://example.com/page-1" },
{ url: "https://example.com/page-2", customSlug: "page-2" },
{ url: "https://example.com/page-3", labels: ["batch"] },
]);
console.log(`Created: ${result.created.length}, Errors: ${result.errors.length}`);

QR Codes

// Generate a one-off QR code
const qrBuffer = await xqr.qr.generate({
content: "https://example.com",
format: "png",
size: 20,
errorCorrection: "H",
foreground: "#8B5CF6",
background: "#FFFFFF",
});
fs.writeFileSync("qr.png", qrBuffer);
// Create a reusable template
const template = await xqr.qr.templates.create({
name: "Brand Primary",
design: {
foreground: "#8B5CF6",
background: "#FFFFFF",
errorCorrection: "H",
logoUrl: "https://cdn.xqr.co/logo.png",
dotStyle: "rounded",
cornerStyle: "rounded",
},
});
// Render using template
const branded = await xqr.qr.templates.render(template.id, {
content: "https://example.com/campaign",
size: 30,
});

Analytics

// Get workspace summary
const summary = await xqr.analytics.summary({ period: "30d" });
console.log(`Total scans: ${summary.totalScans}`);
console.log(`Growth: ${summary.scansChangePct}%`);
// Get timeseries data
const timeseries = await xqr.analytics.timeseries({
period: "7d",
granularity: "hour",
});
for (const point of timeseries) {
console.log(`${point.timestamp}: ${point.scans} scans`);
}
// Get geography breakdown
const geo = await xqr.analytics.geography({ period: "30d" });
geo.forEach((g) => console.log(`${g.country}: ${g.percentage}%`));
// Get device breakdown
const devices = await xqr.analytics.devices({ period: "30d" });
// Get stats for a specific link
const linkStats = await xqr.analytics.linkStats(link.id, { period: "90d" });
console.log(`${linkStats.totalScans} scans, ${linkStats.uniqueVisitors} unique`);
// Top performing links
const top = await xqr.analytics.topLinks({ period: "30d", limit: 5 });
// Create a bio page
const page = await xqr.bio.create({
title: "Jane Doe",
slug: "janedoe",
bio: "Designer & Developer",
theme: "minimal",
links: [
{ title: "Portfolio", url: "https://janedoe.com" },
{ title: "GitHub", url: "https://github.com/janedoe", icon: "github" },
{ title: "Twitter", url: "https://twitter.com/janedoe", icon: "twitter" },
],
});
// Publish
await xqr.bio.publish(page.id);
console.log(page.htmlUrl); // https://xqr.bio/janedoe
// Update links
await xqr.bio.update(page.id, {
links: [
...page.links,
{ title: "LinkedIn", url: "https://linkedin.com/in/janedoe", icon: "linkedin" },
],
});
// Unpublish
await xqr.bio.unpublish(page.id);

Assets

// Upload a file
const upload = await xqr.assets.upload("./logo.png");
console.log(upload.id); // Asset UUID
// Publish to CDN
const published = await xqr.assets.publish(upload.id);
console.log(published.publicUrl); // https://cdn.xqr.co/...
// List assets
for await (const asset of xqr.assets.list()) {
console.log(`${asset.filename} (${asset.status})`);
}

Webhooks

// Create a webhook
const webhook = await xqr.webhooks.create({
url: "https://your-app.com/webhooks/xqr",
events: ["link.created", "link.scanned"],
description: "Production webhook",
});
console.log(webhook.signingSecret); // Save this!
// List deliveries
const deliveries = await xqr.webhooks.deliveries(webhook.id);

Error Handling

import { XQR, XQRError, RateLimitError, ValidationError } from "@xqr/sdk";
try {
const link = await xqr.links.create({ url: "invalid" });
} catch (err) {
if (err instanceof ValidationError) {
console.error("Bad input:", err.message);
} else if (err instanceof RateLimitError) {
console.error(`Rate limited. Retry after ${err.retryAfter}s`);
} else if (err instanceof XQRError) {
console.error(`API error ${err.code}: ${err.message}`);
console.error(`Request ID: ${err.requestId}`);
}
}

Configuration

const xqr = new XQR({
apiKey: process.env.XQR_API_KEY!,
// Optional configuration
baseUrl: "https://xqr.co/api/v1", // Custom base URL
timeout: 30_000, // Request timeout (ms)
maxRetries: 3, // Auto-retry on 429/5xx
debug: false, // Log requests to console
});

Stay Updated

Watch the GitHub repository for the SDK release announcement, or subscribe to the changelog RSS feed.

Was this page helpful?