darvin
v1.0.0
Published
Production-ready Node.js SDK for dar.vin APIs (v3 links + public shorten + QR + webhook helpers) with ESM/CommonJS + TypeScript support.
Maintainers
Readme
📖 darvin
A clean and production-ready Node.js wrapper for the dar.vin API.
Create short links (anonymous or account-linked), manage links, fetch analytics, get QR PNGs, and verify webhook signatures.
✨ Features
- 🔐 API key auth (
BearerorX-API-Key) - 🔌 Simple function API and configurable client API
- 📚 Full TypeScript declarations with IntelliSense
- 📦 Dual module support: CommonJS (
require) and ESM (import) - 🛡️ Built-in errors for API failures, validation failures, and timeouts
- ⚡ Zero dependencies, native
fetchonly - 📄 Cursor pagination helpers (
iterateLinks,listAllLinks) - 🧾 Public shorten endpoint support (
/api/shorten) with optional API key - 🖼️ QR PNG generation helper (
/api/qr/:code) - 🔐 Webhook signature helpers (
HMAC-SHA256)
📦 Installation
npm install darvin🔑 Authentication
Account endpoints can use an API key from the darvin dashboard:
Authorization: Bearer drv_<token>(default)X-API-Key: drv_<token>
You can pass apiKey directly or set DARVIN_API_KEY.
Note:
- v3 account endpoints (
/api/v3/*) require API key - public shorten endpoint (
/api/shorten) works without API key
🚀 Quick Start
CommonJS (auto mode)
const darvin = require("darvin");
darvin.configure({ apiKey: process.env.DARVIN_API_KEY });
(async () => {
// If apiKey exists, this uses account endpoint.
// If not, it falls back to public shorten endpoint.
const created = await darvin.shorten("https://example.com/some/long/url");
console.log(created);
})();ESM
import darvin, { createClient } from "darvin";
const client = createClient({
apiKey: process.env.DARVIN_API_KEY,
timeoutMs: 15000
});
const page = await client.listLinks({ limit: 20, q: "docs" });
console.log(page.data.length, page.next_cursor);
const analytics = await client.getLinkAnalytics(page.data[0].id, { bucket: "day" });
console.log(analytics.totals.clicks);Public shorten (with or without API key)
import { createClient } from "darvin";
const client = createClient({ apiKey: process.env.DARVIN_API_KEY });
const anon = await client.createPublicLink({
long_url: "https://uzunlink.com",
custom_ending: "testabiolalaka",
secret_key: "test123"
});
// If apiKey exists, request is sent with auth and can be account-linked.
// If apiKey is missing, it still works as anonymous shorten.
console.log(anon.result, anon.id, anon.deduped);QR Code PNG
import { createClient } from "darvin";
const client = createClient();
const pngBuffer = await client.getQrCodePng("testabiolalaka");
console.log(pngBuffer.length); // PNG bytesWebhook signature verification
import { verifyWebhookSignature } from "darvin";
const result = verifyWebhookSignature({
secret: process.env.DARVIN_WEBHOOK_SECRET,
timestamp: req.headers["x-darvin-timestamp"],
signature: req.headers["x-darvin-signature-256"],
body: rawBodyString
});
if (!result.ok) {
res.status(401).end("bad signature");
}📚 API Methods
All methods exist on:
- configured default export (
configure(...)+ direct calls), and - explicit client instances (
createClient(...)).
createClient(config?)
Creates an isolated API client.
Config:
apiKey?: string(defaults toprocess.env.DARVIN_API_KEY)baseUrl?: string(default:https://dar.vin/api/v3)timeoutMs?: number(default:10000)authHeader?: "bearer" | "x-api-key"(default:"bearer")defaultHeaders?: Record<string, string>
configure(config)
Sets a global default client used by top-level methods (darvin.listLinks(), etc).
listLinks(options?)
Calls GET /links.
Options:
cursor?: stringlimit?: number(1..100)q?: string
iterateLinks(options?)
Async generator over all link items across paginated GET /links results.
listAllLinks(options?)
Collects all pages from GET /links into a single array.
createLink(input, options?)
Calls POST /links.
Input:
long_url: string(required)custom_ending?: stringsecret_key?: stringdedupe?: boolean
shorten(longUrl, options?)
Smart shorten helper:
mode: "auto"(default): key varsa account, yoksa publicmode: "account":POST /api/v3/links(key required)mode: "public":POST /api/shorten
createPublicLink(input, options?)
Calls POST https://dar.vin/api/shorten.
Input:
long_url: string(required)custom_ending?: stringsecret_key?: stringdedupe?: booleanoptions.useApiKey?: boolean(defaulttrue; key varsa header eklenir)
shortenPublic(longUrl, options?)
Convenience wrapper for public shorten endpoint.
getQrCodePng(code, options?)
Calls GET https://dar.vin/api/qr/:code and returns PNG bytes (Buffer in Node.js runtime).
signWebhookPayload(secret, timestamp, body)
Generates sha256=<hex> signature from ${timestamp}.${body} with HMAC-SHA256.
verifyWebhookSignature(input)
Validates darvin webhook signature and timestamp freshness.
Returns:
{ ok: true, reason: null }{ ok: false, reason: "invalid_timestamp" | "stale_timestamp" | "invalid_signature" }
getLink(id, options?)
Calls GET /links/:id.
updateLink(id, input, options?)
Calls PATCH /links/:id.
Input:
long_url?: stringis_disabled?: booleantags?: string[]notes?: string | null
deleteLink(id, options?)
Calls DELETE /links/:id. Returns true on success.
getLinkAnalytics(id, options?)
Calls GET /analytics/links/:id.
Options:
from?: string | Dateto?: string | Datebucket?: "hour" | "day"
getLinkClickTotal(id, options?)
Helper that returns analytics.totals.clicks.
❗ Error Types
DarvinApiError
Thrown for non-2xx responses.
Properties:
statusdataurlretryAfterSecondscode
DarvinTimeoutError
Thrown when request exceeds timeoutMs.
Properties:
timeoutMsurl
DarvinValidationError
Thrown for invalid SDK inputs.
⚙️ Requirements
- Node.js
>=18.0.0
📝 License
MIT © 2026
