One build, fourteen apps: see what users made of Memory Tin

Documentation

Connect your backend

Documentation menu

Your user id is not a secret, so knowing it must not grant access to that user's designs. Every SDK request carries two things:

  1. your app's public SDK key (tl_pk_…) in the x-tweaklane-key header, and
  2. a user token in Authorization: Bearer <token>, issued by your backend for the signed-in user.

The SDK asks your app's token provider for a token when it needs one, and once more with a forced refresh after an HTTP 401.

Option A: sign tokens on your backend

A user token is an HS256 JWT signed with your secret server key:

Claim Value
iss your TweakLane app id (shown in the dashboard)
sub your user id, 1–256 characters
aud "tweaklane"
iat issued at, seconds since the epoch
exp expiry; the lifetime is at most 3600 seconds (configurable per app)

Node 18+, no dependencies:

import { createHmac } from "node:crypto";

export function tweakLaneToken(userId, { appId, secretKey, ttlSeconds = 900 }) {
  const now = Math.floor(Date.now() / 1000);
  const encode = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
  const header = encode({ alg: "HS256", typ: "JWT" });
  const claims = encode({ iss: appId, sub: userId, aud: "tweaklane", iat: now, exp: now + ttlSeconds });
  const signature = createHmac("sha256", secretKey).update(`${header}.${claims}`).digest("base64url");
  return `${header}.${claims}.${signature}`;
}

Serve it from an endpoint your app already authenticates with its own session, and return it to the SDK's token provider.

Option B: let TweakLane mint the token

Your backend calls POST /tokens with the secret key:

curl -X POST "{TWEAKLANE_URL}/tokens" \
  -H "Authorization: Bearer tl_sk_…" \
  -H "Content-Type: application/json" \
  -d '{"userId": "user-123", "ttlSeconds": 900}'
{ "token": "eyJhbGciOiJIUzI1NiIs…", "expiresAt": 1794050100 }

expiresAt is the token's exp in seconds since the epoch. ttlSeconds is optional: 60 seconds up to your app's maximum token lifetime, which is also the default.

Anonymous users

Apps without accounts can let the SDK get a token with only the public key. The SDK sends a random install id it keeps on the device:

curl -X POST "{TWEAKLANE_URL}/tokens/anonymous" \
  -H "x-tweaklane-key: tl_pk_…" \
  -H "Content-Type: application/json" \
  -d '{"installId": "6f1c2a9e-4b7d-4c1e-9a55-0d2f7c3e8b61"}'

The install id is 16–64 characters of A–Z a–z 0–9 -. The token's subject is anon:<installId> and it lives 900 seconds. Anonymous tokens are off by default; switch them on per app in the dashboard.

How tokens are checked

The API looks up the app by iss, requires the public key to belong to that app, verifies the signature with that app's secret (HS256 only; alg: none and other algorithms are refused), and checks aud, exp, iat (60 s clock skew) and the lifetime cap. The user id comes only from the verified sub: a request can read and write only that user's data in that app.

Rotating the secret key

Rotating in the dashboard keeps the previous secret valid for a grace period you choose (0–720 hours), so tokens signed with either key are accepted until it ends. The new secret is shown once.

Next: API: auth and tokens.