Preview. The SealBind API is in active development. The v1 shapes below are the intended contract; details may change before general availability.

Offline verification

A license token is a short, signed string you ship with your software. Your app verifies it at runtime using the account’s Ed25519 public key — no network call required. Verification proves the token is authentic and unexpired. It does not prove live revocation or current device count; use the online validate endpoint for that.

Token format

A token is three dot-separated segments. It is deliberately JWT-shaped but dependency-free, so you can verify it with the standard library in any language:

v1.<payload>.<signature>
  • payload = base64url(JSON.stringify(claims))
  • signing input = the ASCII bytes of the string v1.<payload>
  • signature = base64url(Ed25519_sign(signing input))

The claims for a node-locked license look like this:

claims
{
  "kid": "clx0account00000000000000",   // account id: selects the verifying public key
  "key": "SEAL-XXXX-XXXX-XXXX",         // the license key
  "productId": "clx0product0000000000000",
  "licenseType": "SUBSCRIPTION",         // PERPETUAL | SUBSCRIPTION | TRIAL
  "maxDevices": 3,
  "status": "ACTIVE",
  "iat": 1785958000,                     // issued-at, unix seconds
  "exp": 1785958300                      // expires 300 seconds after iat
}

Fetch the account public key

The public key is served openly and is safe to cache. It is base64-encoded SPKI DER.

request
curl -s https://sealbind.io/api/v1/accounts/ACCOUNT_ID/public-key
response
{
  "accountId": "clx0account00000000000000",
  "algorithm": "ed25519",
  "format": "spki-der-base64",
  "publicKey": "MCowBQYDK2VwAyEA<...base64 SPKI DER...>"
}

Verify in Node

Pure standard library — no dependencies. Pass the token and the account public key (the publicKey field above). Returns the decoded claims on success, or null if the signature or format is bad.

verify.mjs
import { createPublicKey, verify } from "node:crypto";

export function verifyLicenseToken(token, publicKeyB64) {
  const parts = token.split(".");
  if (parts.length !== 3 || parts[0] !== "v1") return null;
  const [, payloadB64, signatureB64] = parts;

  const publicKey = createPublicKey({
    key: Buffer.from(publicKeyB64, "base64"),
    format: "der",
    type: "spki",
  });

  const signingInput = Buffer.from("v1." + payloadB64, "ascii");
  const signature = Buffer.from(signatureB64, "base64url");

  // Ed25519 uses a null digest algorithm in Node's crypto.verify.
  if (!verify(null, signingInput, publicKey, signature)) return null;

  const claims = JSON.parse(
    Buffer.from(payloadB64, "base64url").toString("utf8"),
  );
  if (claims.exp && claims.exp * 1000 < Date.now()) return null;

  return claims;
}

Online validation (authoritative)

When you need the live answer — revocation, suspension, device-count — call the validate endpoint with a vendor API key. This is the source of truth; offline verification is the fast path.

request
curl -s -X POST https://sealbind.io/api/v1/licenses/LICENSE_KEY/validate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fingerprint": "device-abc-123"}'
response
{
  "result": "VALID",
  "license": {
    "key": "SEAL-XXXX-XXXX-XXXX",
    "status": "ACTIVE",
    "licenseType": "SUBSCRIPTION",
    "productId": "clx0product0000000000000",
    "maxDevices": 3,
    "expiresAt": "2027-08-05T00:00:00.000Z"
  },
  "token": "v1.eyJ....Ab12..."
}

result is one of VALID, INVALID, EXPIRED, REVOKED, or DEVICE_LIMIT_EXCEEDED. A fresh offline-verifiable token is returned only when result is VALID. Every validation token expires 300 seconds (five minutes) after issuance, including tokens for perpetual licences.