SDKs

LinkSnap ships SDKs in three languages, with feature parity across all three. Pick the one for your stack:

Language Package Install
Node.js @forjio/linksnap-node npm install @forjio/linksnap-node
Python forjio-linksnap pip install forjio-linksnap
Go github.com/hachimi-cat/saas-linksnap/sdk/go go get github.com/hachimi-cat/saas-linksnap/sdk/go

All three:

  • Wrap the same REST API surface: every resource exposed as a typed method.
  • Support both static API keys and OIDC device-flow sessions, backed by @forjio/sdk (Node), forjio_sdk (Python), and the Go equivalent.
  • Use minimal dependencies (Node: @forjio/sdk only; Python: httpx only; Go: stdlib + @forjio/sdk Go).
  • Are open source: code is in the saas-linksnap repo under sdk/<lang>/.

When to use which

If your existing stack is in Node, Python, or Go: use the matching SDK. There's no perf or feature reason to use one over another — pick your language.

If your stack is in another language (Ruby, PHP, Rust, Java, Elixir, etc.): use the raw API. Bearer auth is trivial — one header — so an SDK isn't strictly necessary.

Two ways to authenticate

Every SDK supports the same two auth modes (see API authentication for the underlying mechanics):

  1. Static API key — minted in the portal, suitable for CI and headless servers.
  2. OIDC device-flow session — for CLIs and dev tooling where a human can complete a browser handshake.

Static API key

Node.js:

import { LinkSnapClient } from '@forjio/linksnap-node';

const linksnap = new LinkSnapClient({
  apiKey: process.env.LINKSNAP_API_KEY,
});

const link = await linksnap.links.create({
  url: 'https://example.com/long/path',
  slug: 'promo',
});

Python:

from forjio_linksnap import LinkSnapClient

ls = LinkSnapClient(api_key=os.environ["LINKSNAP_API_KEY"])
link = ls.links.create({
    "url": "https://example.com/long/path",
    "slug": "promo",
})
ls.close()

Go:

import linksnap "github.com/hachimi-cat/saas-linksnap/sdk/go"

c := linksnap.NewClient(linksnap.ClientOptions{
    APIKey: os.Getenv("LINKSNAP_API_KEY"),
})
link, err := c.Links.Create(ctx, linksnap.LinksCreateInput{
    URL:  "https://example.com/long/path",
    Slug: "promo",
}, "")

Device-flow session

Every SDK re-exports startDeviceFlow / pollDeviceToken from @forjio/sdk. The Python and Go signatures are the snake_case / PascalCase equivalents.

Node.js:

import { LinkSnapClient, Session, startDeviceFlow, pollDeviceToken } from '@forjio/linksnap-node';

const start = await startDeviceFlow({
  issuer: 'https://huudis.com',
  clientId: 'oc_linksnap_cli',
});

console.log(`Open ${start.verification_uri_complete} to approve`);

const tokens = await pollDeviceToken({
  issuer: 'https://huudis.com',
  clientId: 'oc_linksnap_cli',
  deviceCode: start.device_code,
});

const session = new Session({ ...tokens });
const linksnap = new LinkSnapClient({ session });

After login, the SDK auto-attaches Authorization: Bearer <access> and refreshes when expired.

Resource surface

Every SDK exposes the same resources, with one-to-one method names:

  • links.{ list, get, create, update, delete, bulk, export, import }
  • stats.{ show, export, workspace }
  • qr.{ list, get, create, delete, download, stats }
  • tags.{ list }
  • domains.{ list, add, verify, remove }
  • workspaces.{ list, current, switch }
  • billing.{ plan, usage }
  • apiKeys.{ list, create, delete }

The Node TypeScript types double as the API contract documentation — if you want to know exactly what fields a Link has, look at sdk/node/src/types.ts in the repo.

Versioning

All SDKs follow semantic versioning:

  • MAJOR bumps for breaking changes (rare; we'll batch them).
  • MINOR bumps for new features.
  • PATCH bumps for fixes.

Current versions are pre-1.0 (0.x). We may make small breaking changes between minor versions and document them in the changelog. Once we hit 1.0, the major/minor/patch contract becomes strict.

Open source

The SDKs live in the LinkSnap repo:

Contributions welcome. Issues at github.com/hachimi-cat/saas-linksnap/issues.

Next