TypeScript SDK
Installation (Coming Soon)
npm install @xqr/sdkQuick Start
import { XQR } from "@xqr/sdk";
const xqr = new XQR({ apiKey: process.env.XQR_API_KEY! });
// Create a short linkconst link = await xqr.links.create({ url: "https://example.com", customSlug: "my-link", labels: ["campaign"],});
console.log(link.shortUrl); // https://xqr.co/my-linkLinks
// Create a link with routing rulesconst 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-paginationfor await (const link of xqr.links.list({ label: "campaign" })) { console.log(link.shortCode, link.scanCount);}
// Update a linkawait xqr.links.update(link.id, { url: "https://example.com/updated", enabled: false,});
// Delete a linkawait xqr.links.delete(link.id);
// Bulk createconst 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 codeconst 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 templateconst 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 templateconst branded = await xqr.qr.templates.render(template.id, { content: "https://example.com/campaign", size: 30,});Analytics
// Get workspace summaryconst summary = await xqr.analytics.summary({ period: "30d" });console.log(`Total scans: ${summary.totalScans}`);console.log(`Growth: ${summary.scansChangePct}%`);
// Get timeseries dataconst timeseries = await xqr.analytics.timeseries({ period: "7d", granularity: "hour",});for (const point of timeseries) { console.log(`${point.timestamp}: ${point.scans} scans`);}
// Get geography breakdownconst geo = await xqr.analytics.geography({ period: "30d" });geo.forEach((g) => console.log(`${g.country}: ${g.percentage}%`));
// Get device breakdownconst devices = await xqr.analytics.devices({ period: "30d" });
// Get stats for a specific linkconst linkStats = await xqr.analytics.linkStats(link.id, { period: "90d" });console.log(`${linkStats.totalScans} scans, ${linkStats.uniqueVisitors} unique`);
// Top performing linksconst top = await xqr.analytics.topLinks({ period: "30d", limit: 5 });Link-in-Bio
// Create a bio pageconst 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" }, ],});
// Publishawait xqr.bio.publish(page.id);console.log(page.htmlUrl); // https://xqr.bio/janedoe
// Update linksawait xqr.bio.update(page.id, { links: [ ...page.links, { title: "LinkedIn", url: "https://linkedin.com/in/janedoe", icon: "linkedin" }, ],});
// Unpublishawait xqr.bio.unpublish(page.id);Assets
// Upload a fileconst upload = await xqr.assets.upload("./logo.png");console.log(upload.id); // Asset UUID
// Publish to CDNconst published = await xqr.assets.publish(upload.id);console.log(published.publicUrl); // https://cdn.xqr.co/...
// List assetsfor await (const asset of xqr.assets.list()) { console.log(`${asset.filename} (${asset.status})`);}Webhooks
// Create a webhookconst 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 deliveriesconst 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?
Thanks for your feedback!