Passmint
TemplatesDocsPricing
Log inGet started
Passmint
TemplatesDocsPricingTermsPrivacy

© 2026 Passmint. Built for indie makers.

Getting started

  • Overview
  • Quickstart

API

  • REST API reference
    • Authentication
    • Passes
    • Templates
    • Events
    • Webhooks
    • Errors
  • Webhooks
    • Event types
    • Creating a webhook
    • Payload format
    • Verifying signatures
    • Retries
  • Node.js SDK
    • Configuration
    • Passes
    • Templates
    • Webhook signatures
    • Errors
    • Idempotency

Open source

  • Passmint Package
@passmint/node

The official Node.js SDK.

Typed, tested, ESM + CJS. Idempotency, retries, and webhook signature verification — all built in.

01

Install

npm install @passmint/node
02

Initialize

import { Passmint } from "@passmint/node"

const passmint = new Passmint({
  apiKey: process.env.PASSMINT_API_KEY!,
})
03

Configuration

The constructor accepts several options to control SDK behaviour:

const passmint = new Passmint({
  apiKey: process.env.PASSMINT_API_KEY!,
  baseUrl: "https://api.passmint.com",  // default
  timeoutMs: 30_000,                     // default
  maxRetries: 3,                         // default
})
  • apiKey — required. Your secret API key.
  • baseUrl — override the API host, useful for proxies or self-hosted instances.
  • timeoutMs — per-request timeout in milliseconds.
  • maxRetries — automatic retries on network errors and 5xx responses.

You can check the environment at runtime with passmint.mode, which returns "test" or "live" based on the key prefix.

04

Passes

// Create a pass
const pass = await passmint.passes.create({
  templateId: "tmpl_xxx",
  holderEmail: "alice@example.com",
  fieldValues: { seatNumber: "A12" },
}, { idempotencyKey: "purchase_42" })

// Retrieve a single pass
const fetched = await passmint.passes.retrieve(pass.id)

// List passes with optional filters
const list = await passmint.passes.list({ limit: 100 })

// Update a pass — pushes live updates to installed passes
const updated = await passmint.passes.update(pass.id, {
  fieldValues: { seatNumber: "B7" },
  metadata: { upgraded: true },
})

// Void a pass
await passmint.passes.void(pass.id)

// Fetch pass events
const events = await passmint.passes.events(pass.id)

update() accepts fieldValues and/or metadata — at least one is required. Voided passes cannot be updated.

05

Templates

// Create a template
const tpl = await passmint.templates.create({
  name: "VIP Membership",
  type: "membership",
  appleStyle: "storeCard",
  design: { /* your design config */ },
  starterTemplateId: "starter_xxx", // optional
})

// Retrieve a template
const fetched = await passmint.templates.retrieve("tmpl_xxx")

// List all templates
const templates = await passmint.templates.list()

// Update a template
const updated = await passmint.templates.update("tmpl_xxx", {
  name: "Premium Membership",
  design: { /* updated design */ },
  archived: false,
})

// Archive a template
const result = await passmint.templates.archive("tmpl_xxx")
// { id: "tmpl_xxx", deleted: true }

The type parameter accepts "event", "membership", "coupon", "loyalty", or "generic".

The appleStyle parameter accepts "eventTicket", "generic", "storeCard", "coupon", or "boardingPass".

06

Webhook signatures

Verify webhook signatures with the SDK helper. Timing-safe compare and a tolerance window — Stripe-style.

const event = passmint.webhooks.constructEvent(
  rawBody,
  request.headers["passmint-signature"]!,
  process.env.PASSMINT_WEBHOOK_SECRET!,
  300, // tolerance in seconds (default: 300)
)
  • payload — the raw request body as a string or Buffer.
  • signature — the value of the passmint-signature header.
  • secret — your webhook signing secret.
  • toleranceSeconds — optional. Defaults to 300 seconds (5 minutes). Rejects events with timestamps outside the window.

Throws PassmintError if the signature is invalid or the timestamp is outside the tolerance window.

07

Errors

The SDK throws typed errors so you can branch cleanly:

  • PassmintError — base class for all SDK errors.
  • PassmintAPIError — non-2xx response. Includes status, type, code, and param properties.
  • PassmintAuthError — thrown on 401/403 responses (bad, expired, or revoked API key).
  • PassmintRateLimitError — includes a retryAfterSeconds property with the number of seconds to wait before retrying.
import {
  PassmintError,
  PassmintAPIError,
  PassmintAuthError,
  PassmintRateLimitError,
} from "@passmint/node"

try {
  await passmint.passes.create({ /* ... */ })
} catch (err) {
  if (err instanceof PassmintRateLimitError) {
    console.log(`Retry after ${err.retryAfterSeconds}s`)
  } else if (err instanceof PassmintAuthError) {
    console.log("Check your API key")
  } else if (err instanceof PassmintAPIError) {
    console.log(err.status, err.code, err.param)
  }
}
08

Idempotency

Both create() and update()methods auto-generate an idempotency key if you don't provide one. You can pass your own for deterministic replay:

await passmint.passes.create(
  { templateId: "tmpl_xxx", holderEmail: "alice@example.com" },
  { idempotencyKey: "purchase_42" },
)

await passmint.passes.update(
  "pass_xxx",
  { fieldValues: { seatNumber: "C3" } },
  { idempotencyKey: "upgrade_42" },
)
  • Keys are scoped per organization.
  • Keys expire after 24 hours.
  • Replayed requests return the original response without re-executing the operation.