New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@open-qr/sdk

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@open-qr/sdk

Dependency-free TypeScript client for the OpenQR REST API: generate QR codes and manage dynamic (editable) codes with scan analytics.

latest
Source
npmnpm
Version
0.2.1
Version published
Weekly downloads
9
Maintainers
1
Weekly downloads
 
Created
Source

@open-qr/sdk

Dependency-free TypeScript client for the OpenQR REST API. Generate static QR codes and manage dynamic (editable) codes with scan analytics. Works in Node ≥18, edge runtimes and the browser — it uses the global fetch and ships no dependencies.

Install

pnpm add @open-qr/sdk
# npm install @open-qr/sdk

Quickstart

Create a free API key at https://openqr.uk/api, then:

import { OpenQR } from "@open-qr/sdk";

const qr = new OpenQR({ apiKey: "oqr_…" });

const svg = await qr.generate({ data: "https://openqr.uk" });

The key is sent as Authorization: Bearer oqr_… on every request — header only, never a query string.

Options

new OpenQR({
  apiKey: "oqr_…",
  baseUrl: "https://openqr.uk", // default; override for self-hosting
  fetch: customFetch,           // optional; defaults to global fetch
});

Generate QR codes

// SVG markup (string)
const svg = await qr.generate({ data: "https://openqr.uk", size: 512, margin: 4 });

// PNG bytes (Uint8Array)
const png = await qr.generate({ data: "https://openqr.uk", format: "png", dark: "232E3A", light: "FFFFFF" });

// Apply a saved theme by id or name
await qr.generate({ data: "https://openqr.uk", theme: "Brand" });

// Build a shareable GET URL without making a request (no key embedded)
const url = qr.qrUrl({ data: "https://openqr.uk", format: "png" });

Dynamic (editable) codes

A dynamic code is a re-pointable short link on oqr.to — encode the returned short_url in a QR and change where it points later.

// Create
const code = await qr.createDynamicCode({ destination: "https://example.com/menu", label: "Spring menu" });
console.log(code.short_url); // https://oqr.to/spring-menu
console.log(code.rateLimit); // { limit, remaining, reset } from X-RateLimit-* headers

// List
const codes = await qr.listDynamicCodes({ limit: 50 });

// Bulk create (up to 200)
const created = await qr.bulkCreateDynamicCodes({
  codes: [
    { destination: "https://example.com/menu", label: "Spring menu" },
    { destination: "https://example.com/wifi", label: "Guest wifi" },
  ],
  theme: "Brand",
});

// Update (send only what changes) — destination, label, slug, tags, folder_id, style/theme
await qr.updateDynamicCode(code.id, { destination: "https://example.com/summer-menu", slug: "summer-menu" });

// Delete
await qr.deleteDynamicCode(code.id);

Scan analytics

const { scans, analytics } = await qr.getScans(code.id, { days: 30 });
console.log(scans.total, scans.topCountry);
console.log(analytics.by_country, analytics.daily);

Folders

const folders = await qr.listFolders();
const folder = await qr.createFolder("Campaigns");
await qr.renameFolder(folder.id, "Q3 Campaigns");
await qr.updateFolder(folder.id, { name: "Q3 Campaigns" }); // object-shaped equivalent
await qr.deleteFolder(folder.id); // codes inside are un-filed, not deleted

Themes

A theme is a reusable QR style you can apply by id or name on generation and dynamic-code endpoints.

const themes = await qr.listThemes();
const theme = await qr.createTheme({
  name: "Brand",
  style: { fgColor: "#232E3A", bgColor: "#FFFFFF", dotType: "rounded", cornerSquareType: "extra-rounded", margin: 4 },
});
await qr.deleteTheme(theme.id); // already-styled codes keep their look

Errors

Every non-2xx response throws an OpenQRError carrying the HTTP status, a stable code, the server's message, and (where present) rate-limit metadata.

import { OpenQR, OpenQRError } from "@open-qr/sdk";

try {
  await qr.createDynamicCode({ destination: "http://localhost" });
} catch (err) {
  if (err instanceof OpenQRError) {
    console.error(err.status);    // 400
    console.error(err.code);      // "bad_request"
    console.error(err.message);   // "Destinations can't point to private or internal addresses."
    console.error(err.retryAfter); // seconds (on 429)
    console.error(err.rateLimit); // { limit, remaining, reset } (on 429)
  }
}
statuscodeWhen
400bad_requestInvalid body, missing field, or a disallowed destination
401unauthorizedMissing/invalid/revoked API key
404not_foundCode, folder or theme not found or not owned by your key
409conflictRequested custom slug already taken
429rate_limitedDynamic-code creation limit hit (20/hour) — see retryAfter
500server_errorUnexpected server-side failure

License

MIT. See LICENSE.

Note: this package is not yet published to npm — publishing (npm publish, requires an npm token) is the remaining step.

Keywords

qr

FAQs

Package last updated on 18 Aug 2026

Related posts