Trigger.dev public tokens: keep the Sume key server-side

Trigger.dev v4.6.2 hardened authorization for public tokens. Whatever token your browser holds, a Sume API key must never be one of them. Here is the split.

4 min readSume
All posts

Keep the Sume API key on your server and give the browser only your own, narrowly scoped credentials. The Trigger.dev changelog lists v4.6.2 (Sep 16, 2026) with "Authorization hardening and cleaner chat agent trace spans", covering realtime payloads, public tokens and chat sessions. That is a reminder of the pattern, not a Sume feature: a public token is meant for the client, a Sume key is not.

What the changelog says

The v4.6.2 entry names three surfaces: realtime payloads, public tokens and chat sessions. The changelog line is all this post relies on; check the release notes for what exactly changed before you upgrade.

What Sume has instead of a public token

Sume has no per-end-user credential and no browser-safe key. The embed recipe puts it plainly: one Sume account, one server-side key, many of your customers. A Sume key spends your credits, so anyone holding it can run any Format you own up to your caps.

Where each credential belongs (Trigger.dev changelog and Sume docs, read 2026-10-03)
CredentialLives inSafe in a browser?
Trigger.dev public tokenClient, issued per useDesigned for it
Sume API keyYour server environmentNo
Your own session cookieBrowserYes, it is yours

Rules from the Sume docs

The Format embedding recipe lists the custody rules. They apply whether your background jobs run on Trigger.dev or anywhere else.

  • Keep the key in server environment, never in client JavaScript, a mobile bundle or a NEXT_PUBLIC_* variable.
  • Proxy the call, not the key. A pass-through endpoint that forwards the browser payload with your key attached is the same leak one hop later.
  • Run your own authorization check. Sume authenticates you, not your customer.
  • Rotate by creating a new key and retiring the old one, since scopes cannot be added to an existing key.

A server-side shape that works

Your endpoint accepts your customer's identifiers, builds the Sume request itself, and sets a spend cap and an idempotency key. The TypeScript SDK path from the recipe looks like this.

import { createSumeClient, subscribeFormatRun } from "@sume-com/sdk";

const client = createSumeClient({ apiKey: process.env.SUME_API_KEY! });

const run = await subscribeFormatRun({
  client,
  path: { handle: "acme", slug: "product-promo" },
  idempotencyKey: `order-${order.id}`,
  body: {
    input: { product_url: order.productUrl },
    generation_spend_cap_usd: 3,
  },
});

Where a task runner fits

If a Trigger.dev task calls Sume, the key is a secret in the task environment, like any other server code. Whatever the task reports back to the browser through a public token should be your own record ids and status, not Sume credentials or signed URLs. Prefer a webhook to polling for results in production, as the recipe advises.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume