Documentation Index: Fetch llms.txt first to discover every published page. This page is also available as Markdown at /node-sdk-download-tokens.md.
Verified · 8/11/2026

Signed Download Tokens

Generate short-lived, HMAC-signed tokens that scope a download URL to one email's raw MIME bytes or attachment bundle, and verify them before serving the content.

Signed download tokens let you mint a short-lived, HMAC-signed token that scopes access to one email's raw bytes or attachment bundle, so you can hand out a fetchable link without exposing your webhook secret. Use them when a browser or downstream service needs to retrieve that content later from a route you serve.

Both helpers are exported from the webhook subpath of @primitivedotdev/sdk, the SDK entry point that also carries signature verification:

import {
  generateDownloadToken,
  verifyDownloadToken,
} from "@primitivedotdev/sdk/webhook";
Note

generateDownloadToken takes a GenerateDownloadTokenOptions object and verifyDownloadToken takes VerifyDownloadTokenOptions and returns a VerifyDownloadTokenResult. All three types are exported alongside the functions, so your editor shows the exact required fields; the SDK is the authoritative reference for them.

import type {
  GenerateDownloadTokenOptions,
  VerifyDownloadTokenOptions,
  VerifyDownloadTokenResult,
} from "@primitivedotdev/sdk/webhook";
Tip

Checking whether an inbound email's raw content arrived inline or must be fetched from Primitive's own download URL is a different job. See Parsing Raw Email (.eml) for isRawIncluded and decodeRawEmail. Download tokens are for URLs you mint and serve yourself.

Mint and verify a token#

Generate the token in the code that already holds the email and the secret, then verify it in the route that serves the bytes.

  1. 1

    Generate the token where you have the email and the secret#

    // server-side: any module that already has the inbound email in hand
    import { generateDownloadToken } from "@primitivedotdev/sdk/webhook";
    
    const token = generateDownloadToken({
      emailId: email.id,
      secret: process.env.PRIMITIVE_WEBHOOK_SECRET!,
    });
    

    Fill in the remaining fields from GenerateDownloadTokenOptions; your editor lists them and marks which are required.

  2. 2

    Embed the token in a URL your own route serves#

    const downloadUrl = `https://yourapp.example.com/downloads/${email.id}?token=${token}`;
    

    Hand this URL to whatever needs the content later. The token, not the path, is what gates access.

  3. 3

    Verify before serving any bytes#

    // app/downloads/[emailId]/route.ts (Next.js route handler)
    import { verifyDownloadToken } from "@primitivedotdev/sdk/webhook";
    
    export const runtime = "nodejs";
    
    export async function GET(
      req: Request,
      { params }: { params: { emailId: string } },
    ) {
      const token = new URL(req.url).searchParams.get("token") ?? "";
    
      const result = verifyDownloadToken({
        token,
        emailId: params.emailId,
        secret: process.env.PRIMITIVE_WEBHOOK_SECRET!,
      });
    
      // Inspect `result` (a VerifyDownloadTokenResult) and reject before you
      // read anything off disk or call Primitive's download endpoint.
      // ... stream the raw bytes or attachment bundle here ...
    }
    
Warning

Verify on every request. Do not cache a "verified once" flag for a token past its lifetime, and do not skip the email-id check to serve a multi-email download page. A token is scoped to a single email; mint one per email.

Tip

Both functions take the secret directly, so they work outside a receive() call, for example in a standalone download route that never sees the original inbound webhook request. Use the same PRIMITIVE_WEBHOOK_SECRET you use for webhook signature verification.

Next steps#

Was this page helpful?

© Primitive SDKs

Powered by Browzer