The trust model
The platform signs tokens with an Ed25519 private key. Your app verifies them with the platform’s public key only. That asymmetry is the whole point: a hosted app can check that a token is genuine, but it can never forge one — unlike a shared secret, which anyone holding it could mint tokens with. Every token also carriesaud — your app’s audience — so a token minted for one app can never be replayed
against another.
There are two kinds of token:
- Session — authenticates an embed or storefront request as a workspace. Reusable until it expires (15 minutes).
- Provision — one-time, server-to-server. It delivers a workspace’s freshly minted API key when the app is installed.
The workspace always comes from a verified token — never from the request body or a query parameter.So a caller can only ever act as the tenant the platform minted the token for. There’s no way to ask your app about someone else’s workspace.
The lifecycle
Provisioning is retry-safe
The provision token is one-time — ajti on it blocks replay. But “one-time” has a subtle trap: if your
onProvision work fails after the token is spent (a locked database, say), a naive design would strand the
workspace forever, because the platform’s retry carries the same, now-spent token.
The SDK avoids this. It consumes the jti only after your onProvision succeeds, and releases it on
failure. So a transient error just means the platform’s retry works. The starter wires this up for you with a
releaseJti hook.
Where the SDK draws the line
The security-critical protocol lives in@sentralbee/app-sdk:
- verifying platform tokens (
createTokenVerifier,createSessionAuth,mountInstall), - encryption-at-rest for the secrets you store (
createCypher), - webhook signature verification (
verifyWebhookSignature), - the authenticated public-API client (
sentralbeeClient).
Where to next
- Install lifecycle — the provision and uninstall handlers.
- The manifest — declare what your app is and may do.
- The embed UI — build the interface merchants see.

