One handler, two entries
server/handler.ts exports the options and the handler:
(Request) => Promise<Response>, so it runs anywhere the Fetch API does. The options
are exported separately because a platform that mounts you under a prefix needs basePath.
- Cloudflare Workers
- Vercel
- Express or Node
server/worker.ts:wrangler.toml:Point the manifest at it
sandboxBaseUrl is used for dev installs and sandbox projects. It defaults to baseUrl.
Both must be https.
The routes Tappify calls
createTappifyHandler routes all of them; you fill in the ones you declared. A path it routes
with no handler registered comes back as a 404 naming the missing one, so a contribution you
declared and never wired is loud rather than silent.
Verifying the caller
Every route except health carriesAuthorization: Bearer <install token> — RS256, five
minutes, audience ext:<your extension id> — and X-Tappify-Event-Id, the idempotency key.
The handler verifies the token for you against Tappify’s JWKS. Verify it yourself only when
you are not using the handler:
https://api.tappify.ai/api/v1/extensions/.well-known/jwks.json and rotate with a 24-hour
overlap, so both keys are served through the change.
Before you publish
Health has to answer 200 within three seconds, onbaseUrl and on sandboxBaseUrl if you
declared one, or the publish stops. A redirect counts as a failure: serve the route from the
url you declared.
tappify extension dev --live serves your bundle from your machine but still relays
procedures to the url in your manifest. Run the handler locally with pnpm run dev:worker,
give it a public address, and pass that to --server <url> for the length of the session —
Tappify calls you from its own servers, so a localhost url is not one it can reach. See
Local server during live preview.