Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

passkit-generator

alexandercerutti147.6kMIT3.4.0TypeScript support: included

The easiest way to generate custom Apple Wallet passes in Node.js

Apple, Passkit, Wallet, Pass

readme



<picture> <source media="(prefers-color-scheme: dark)" srcset="https://github.com/alexandercerutti/passkit-generator/raw/master/assets/logo-dark.svg?sanitize=true" width="600" > Passkit-generator logo for light mode </picture>

Simple Node.js interface to generate customized Apple Wallet Passes for iOS and WatchOS.


Financial Contributors on Open Collective


Architecture

This library was created with a specific architecture in mind: application and model (as preprocessed entity), to split as much as possible static objects (such as logo, background, icon, etc.) from dynamic ones (translations, barcodes, serialNumber, ...), while keeping an eye on the different possible execution contexts.

Pass creation and population might not fully happen in runtime. This library allows to create a pass from scratch, specify a folder model (template) or specify a set of buffers. In the last two cases, both should contain all the objects needed (static medias) and structure to make a pass work.

Whenever adding files, through scratch, template or buffer, these will be read and pushed as they are in the resulting .zip file, while dynamic data will be patched (pass.json with props) or generated in runtime (manifest.json, signature and translation files).

Installation

$ npm install passkit-generator --save

API Documentation

This package comes with an API Documentation Reference, available in wiki, that makes available a series of methods to create and customize passes.


Looking for the previous major version?

Check the v2 tag. That tag is kept for reference only.


Coming from the previous major version?

Look at the Migration Guide.


Integrating Apple Wallet Web services?

Give a look at another library I made: Passkit Webservice Toolkit and its integrations!


Getting Started

Model

Assuming that you don't have a model yet, the first thing you'll have to do, is creating one. A model contains all the basic pass data that compose the Pass identity. These data can be files (icon, thumbnails, ...), or pieces of information to be written in pass.json (Pass type identifier, Team Identifier, colors, ...) and whatever you know that likely won't be customized on runtime.

When starting from zero, the best suggested solution is to use a Template (folder) to start with, as it will allow an easier access to all the files and data. Nothing will prevent you using a buffer model or creating a pass from scratch, but they are meant for an advanced usage or different contexts (e.g. running a cloud function might require a scratch model for faster startup, without storing the model in a "data bucket").

Let's suppose you have a file model.zip stored somewhere: you unzip it in runtime and then get the access to its files as buffers. Those buffers should be available for the rest of your application run-time and you shouldn't be in need to read them every time you are going to create a pass.

To maintain a pass model available during the run-time, a PKPass instance can be created from whatever source, and then used as a template through PKPass.from.

Using the .pass extension is a best practice, showing that the directory is a pass package. (Build your first pass - Apple Developer Portal).

Following to this best practice, the package is set to require each folder-model to have a .pass extension.

If omitted in the configuration (as in Usage Example below), it will be forcefully added, possibly resulting in a folder reading error, if your model folder doesn't have it.


Model creation can be performed both manually or with the auxiliary of a web tool I developed, Passkit Visual Designer, which will let you design your model through a neat user interface. It will output a .zip file that you can decompress and use as source.


You can follow Create the Directory and add Files for the Pass at Apple Developer to build a correct pass model. The icon is required in order to make the pass work. Omitting an icon resolution, might make a pass work on a device (e.g. Mac) but not on another (e.g. iPhone). Manifest.json and signature will be automatically ignored from the model and generated in runtime.

You can also create .lproj folders (e.g. en.lproj or it.lproj) containing localized media. To include a folder or translate texts inside the pass, please refer to Localizing Passes in the wiki API documentation.

To include a file that belongs to an .lproj folder in buffers, you'll just have to name a key like en.lproj/thumbnail.png.

Pass.json

Create a pass.json by taking example from examples folder models or the one provided by Apple for the first tutorial and fill it with the basic informations, that are teamIdentifier, passTypeIdentifier and all the other basic keys like pass type. Please refer to Pass interface documentation on Apple Developers.

{
    "formatVersion": 1,
    "passTypeIdentifier": "pass.<bundle id>",
    "teamIdentifier": "<your team identifier>",
    "organizationName": "<your organization name>",
    "description": "A localizable description of your pass. To do so, put here a placeholder.",
    "boardingPass": {}
}

Certificates

The third step is about the developer and WWDR certificates. I suggest you to create a certificate-dedicated folder inside your working directory (e.g. ./certs) to contain everything concerning the certificates.

This is a standard procedure: you would have to do it also without using this library. We'll use OpenSSL to complete our work (or to do it entirely, if only on terminal), so be sure to have it installed.

Follow the FULL GUIDE in wiki to get all the files you need to proceed.


Usage Examples

Importing:

/** CommonJS **/
const { PKPass } = require("passkit-generator");

/** ESM **/
import { PKPass } from "passkit-generator";

Folder Model

try {
    /** Each, but last, can be either a string or a Buffer. See API Documentation for more */
    const { wwdr, signerCert, signerKey, signerKeyPassphrase } = getCertificatesContentsSomehow();

    const pass = await PKPass.from({
        /**
         * Note: .pass extension is enforced when reading a
         * model from FS, even if not specified here below
         */
        model: "./passModels/myFirstModel.pass",
        certificates: {
            wwdr,
            signerCert,
            signerKey,
            signerKeyPassphrase
        },
    }, {
        // keys to be added or overridden
        serialNumber: "AAGH44625236dddaffbda"
    });

    // Adding some settings to be written inside pass.json
    pass.localize("en", { ... });
    pass.setBarcodes("36478105430"); // Random value

    // Generate the stream .pkpass file stream
    const stream = pass.getAsStream();
    doSomethingWithTheStream(stream);

    // or

    const buffer = pass.getAsBuffer();
    doSomethingWithTheBuffer(buffer);
} catch (err) {
    doSomethingWithTheError(err);
}

Buffer Model

try {
    /** Each, but last, can be either a string or a Buffer. See API Documentation for more */
    const { wwdr, signerCert, signerKey, signerKeyPassphrase } = getCertificatesContentsSomehow();

    const pass = new PKPass({
        "thumbnail.png": Buffer.from([ ... ]),
        "icon.png": Buffer.from([ ... ]),
        "pass.json": Buffer.from([ ... ]),
        "it.lproj/pass.strings": Buffer.from([ ... ])
    },
    {
        wwdr,
        signerCert,
        signerKey,
        signerKeyPassphrase,
    },
    {
        // keys to be added or overridden
        serialNumber: "AAGH44625236dddaffbda",
    });

    // Adding some settings to be written inside pass.json
    pass.localize("en", { ... });
    pass.setBarcodes("36478105430"); // Random value

    // Generate the stream .pkpass file stream
    const stream = pass.getAsStream();
    doSomethingWithTheStream(stream);

    // or

    const buffer = pass.getAsBuffer();
    doSomethingWithTheBuffer(buffer);
} catch (err) {
    doSomethingWithTheError(err);
}

For more complex usage examples, please refer to examples folder.


Other

If you used this package in any of your projects, feel free to open a topic in issues to tell me and include a project description or link (for companies). 😊 You'll make me feel like my time hasn't been wasted, even if it had not anyway because I learnt and keep learning a lot of things by creating this.

The idea to develop this package, was born during the Apple Developer Academy 17/18, in Naples, Italy, driven by the need to create an iOS app component regarding passes generation for events.

A big thanks to all the people and friends in the Apple Developer Academy (and not) that pushed me and helped me into realizing something like this and a big thanks to the ones that helped me to make technical choices and to all the contributors.

Any contribution, is welcome. Made with ❤️ in Italy.


Contributors

A big thanks to all the people that contributed to improve this package. Any contribution is welcome. Do you have an idea to make this improve or something to say? Open a topic in the issues and we'll discuss together! Thank you ❤️ Also a big big big big thank you to all the financial contributors, which help me maintain the development of this package ❤️!

Code Contributors

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

changelog

Changelog

3.4.0 (28 May 2025)

  • Added support to undocumented feature stripColor (PR #245)

3.3.0 (11 Jan 2025)

  • Added support to the missing iOS 18 changes (useAutomaticColor, footerBackgroundColor, suppressHeaderDarkening, auxiliaryStoreIdentifiers, eventStartDateInfo, venueOpenDate);
  • Added support to relevantDate property in relevantDates, along with startDate and endDate, in pass.json;
  • Added new method setRelevantDates;
  • Improved details on (root).relevantDate deprecation since iOS 18;
  • Improved comments and markers on SemanticTags with iOS version;
  • Added support to double compilation ESM + CJS: both are now shipped;
  • Updated examples. This update brings also them to run on ESM;
  • Made easier to run examples and install their dependency by converting repo to be a pnpm workspace;

3.2.0 (29 Oct 2024)

  • Added support to iOS 18 changes (refer to issue #205 for all the changes);
  • Added support to hex colors for foregroundColor, backgroundColor, labelColor as well as new iOS 18 color properties;
  • Added new example models for iOS 18 changes;
  • Added inline source maps in files;
  • Fixed Field.timeStyle typescript type;
  • Changed all node imports to use node: prefix;
  • Changes do-not-zip usage make use of explict node:buffer import;

3.1.11 (15 Aug 2023)

  • Fixed beacons major validation to be more relaxed (PR #158);

3.1.10 (09 Aug 2023)

  • Fixed dates processing by converting them to UTC (PR #155);

3.1.9 (03 Apr 2023)

  • Fixed transitType which wasn't being imported when a boardingPass was getting read (PR #138)
  • Improved types for property in Field type (PR #139)

3.1.8 (26 Mar 2023)

  • Fixed Typescript type for Semantics.WifiAccess (PR #136)

3.1.7 (14 Nov 2022)

  • Fixed generation of EventTicket with row fields (PR #118)

3.1.6 (29 Mar 2022)

  • Optimizations for localizationEntries, PKPass.pack, localize and regexes;
  • Dependencies Update;

3.1.5 (22 Feb 2022)

  • Fixed FieldsArray order when pushing or unshifting fields in headerFields, primaryFields, secondaryFields, auxiliaryFields and backFields (PR #104)

3.1.4 (07 Feb 2022)

  • Fixed Schema validation for browser-like contexts like Cloudflare Workers (PR #100);

  • Added examples for Cloudflare Workers;


3.1.3 (16 Jan 2022)

  • Updated dependencies to remove dependabot alerts (like, node-forge to v1.2.1);
  • Updated tests;

3.1.2 (30 Dec 2021 (Happy new year!))

  • This release fixes some issues when running under Windows and adds new tests.
  • Thanks to PR #99 by d34db4b3.

3.1.1 (25 Dec 2021 (Merry Christmas!))

  • This release fixes some issues with typescript strict mode (as much as we were able to fix without starting ho-ho-ho-ing due to madness 🤪).

3.1.0 (11 Dec 2021)

  • Made PKPass.from Template certificates to be optional;
  • Changed constructor buffers and certificates to be optional;
  • Added constructor check on certificates to avoid error if pass is created through PKPass.from but without certificates;
  • Added constructor checks for buffers with a warning being fired if the passed parameter is not an object;

3.0.0 / 3.0.1 (31 Oct 2021)

  • Passkit-generator has been completely refactored and re-conceptualized. Follow Migration Guide v2 to v3 to see the differences between the two versions

2.0.8 (25 Aug 2021)

  • Added support for optional NFC key requiresAuthentication;
  • Added support for semantics as a global overridable property;
  • Renamed files to conform to Apple naming in documentation;
  • Added documentation links in files;

2.0.7 (21 Jun 2021)

  • Fixed wrong Schemas keys (ignoresTimeZone and dataDetectorTypes);
  • Added more SemanticsTagTypes
  • Refactored Error system;
  • Refactored Schemas;
  • Updated Dependencies;
  • Removed unnecessary ways to perfom ways in refactoring;

2.0.6 (09 Feb 2021)

  • Improved building phase;
  • Improved tests;
  • Updated dependencies (like node-forge and node-fetch, which had critical vulnerability);
  • Added prettier for formatting;
  • Generic improvements to code;
  • Removed moment.js for an internal generation of the date (without timezone support);

2.0.5 (06 Sep 2020)

  • Replaced deprecated dependencies @hapi/joi with Sideway's joi;
  • Generic dependencies update;
  • Generic code improvements (vscode-autofixes included);
  • Bumped minimum Node.JS supported version to 10 (moved from util.promisify approach to fs.promises);

2.0.4 (14 Dec 19)

  • Typescript strict configuration fixes;
  • Improved specifications;

2.0.3 (06 Dec 19)

  • Dependencies Updates;
  • More improvements;

2.0.2

  • Unlocked some other prohibited (until now) fields that were not editable due to design choice ( organizationName, passTypeIdentifier, teamIdentifier, appLaunchURL, associatedStoreIdentifiers);
  • Small improvements;

2.0.1

  • Typescript version update;
  • Update to webServiceURL schema regex and allowed all characters for authenticationToken;

2.0.0

This version brings lot of improvements and breaking changes. Please refer to the Migration Guide for the most important changes.


1.6.8

  • Added optional row attribute for auxiliaryFields

1.6.6

  • Fixed problem with fieldsArray: fields were being added even if the keys check was failing

1.6.5

  • Added support for logoText in supportedOptions (issues #21, #28)
  • Fixed nfc methods which was accepting and registering an array instead of an object
  • Adding support for native Dates (#32)
  • Fixing passes parallel generation (#31)

1.6.4

  • Added windows path slash parsing

1.6.3

  • Moved some utility functions to a separate file
  • Removed rgbValues as a variable for a direct approact
  • Renamed _validateType in _hasValidType
  • Fixed barcode legacy bug
  • Added NO_PASS_TYPE as message
  • Moved passExtractor function to class scope instead of generate()'s
  • Moved to async/await approach for generate()

1.6.0

  • Improved unique fields management;
  • Changed debug message for discarded fields;
  • Renamed uniqueKeys to fieldsKeys
  • Added BRC_BW_FORMAT_UNSUPPORTED to not let PKBarcodeFormatCode128 to be used as backward barcode format
  • Added support for row field in auxiliaryFields
  • Added support to semantics keys to fields in schema

1.5.9

  • Removed check for changeMessage as per issue topic #15
  • Added pass.strings file concatenation with translations if it already exists in specific folder;
  • Small changes to messages;

1.5.8

  • Now checking both static list and remote list before raising the error for missing files
  • (thank you, Artsiom Aliakseyenka);
  • Renamed __barcodeAutogen to barcodesFromUncompleteData and moved it outside of Pass class;
  • Renamed __barcodeAutocomplete to Symbol/barcodesFillMissing;
  • Renamed __barcodeChooseBackward to Symbol/barcodesSetBackward;
  • Removed context binding when passing above methods with alises after using .barcode();
  • Edited BRC_ATC_MISSING_DATA message

1.5.7

  • Moved tests to spec folder with jasmine configuration
  • Fixed barcodes validation problem
  • Re-engineered FieldContainer (now FieldsArray) to extend successfully array with its methods.

1.5.6

  • Updated documentation
  • Added content-certificates support;
  • Fixed problem with supported options
  • Added description to be available for override (thank you, Artsiom Aliakseyenka);

1.5.5

  • Schema: changed webServiceURL Regex and authenticationToken binding to this one
  • Schema: removed filter function for getValidated to return empty object in case of error;
  • Added OVV_KEYS_BADFORMAT message to throw in case of error;

1.5.4

  • Added .npmignore to exclude examples upload
  • Replaced findIndex for find to get directly the pass type.
  • Added function assignLength to wrap new objects with length property.
  • Converted schemas arrow functions to functions and added descriptive comments.
  • Added noop function instead creating new empty functions.

1.5.3

  • Bugfix: when overrides is not passed as option, the pass does not get generated.

1.5.2

  • Added schema support for sharingProhibited (not documented in ppfr)

1.5.1

  • Updated declaration file
  • Fixed problem in error message resolving on multiple %s;
  • Added debug messages in messages.js;
  • Added more comments;
  • Moved literal debug messages to messages.js;
  • Edited formatMessage (was formatError) to check also among debugMessages

1.5.0

  • Moved _parseCertificates outside of pass and renamed it in readCertificates;
  • Changed readCertificates to return object containing name:parsed-pem;
  • Added readCertificates and this.Certificates merging before model reading;

1.4.2

  • Minor changes to READMEs and core.
  • Updated documentation

1.4.1

  • Fix model initialization validation
  • Improved README
  • Added logo in assets and README
  • Added updates for OpenSSL for Windows in termal steps for cers generation
  • Updated dependencies minimum version

1.4.0

  • Added working example for load
  • Fix typos for non-mac guide
  • Removed express from dev dependencies;
  • Added .load type definition
  • Added .load to documentation;
  • Added .load function to fetch pictures from the web and implemented fetching function inside logic flow