> ## Documentation Index
> Fetch the complete documentation index at: https://tapace.lk/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js quickstart

> Use a test API key and an existing template to issue a wallet pass, share its delivery URL, and update its values from a Node.js application.

Use the TapAce Node.js SDK to issue a pass from a template you designed in the dashboard, then return its delivery link to the holder. Run this example in your server application.

## Prepare a template and key

Install the SDK using the current [installation instructions](https://tapace.lk/docs/sdk/node/overview.md). Follow the [API quickstart](https://tapace.lk/docs/quickstart.md) to create a test API key and design a dedicated test template. For this example, use a template with a per-pass field named `memberName`. Supply any other fields listed in its `requiredFields` and any required per-pass actions listed in `requiredActions`.

Set `TAPACE_API_KEY`, `TAPACE_TEMPLATE_ID` and `REGISTRATION_ID` in your server environment. Use a registration ID already saved by your application. Reuse it only when retrying this same pass issuance, with the same request details.

## Issue and deliver

```typescript theme={null}
import { TapAce, idempotencyKey } from "@tapace/node";

const apiKey = process.env.TAPACE_API_KEY;
const templateId = process.env.TAPACE_TEMPLATE_ID;
const registrationId = process.env.REGISTRATION_ID;
if (!apiKey || !templateId || !registrationId) {
  throw new Error("Set TAPACE_API_KEY, TAPACE_TEMPLATE_ID and REGISTRATION_ID");
}

const tapace = new TapAce({ apiKey });
const account = await tapace.me.retrieve();
if (account.environment !== "test") throw new Error("Use a test API key for this quickstart");
const template = await tapace.templates.retrieve(templateId);
console.log("Required fields:", template.requiredFields);

const pass = await tapace.passes.create(
  {
    templateId,
    externalId: registrationId,
    holder: { name: "Nimal Perera", email: "nimal@example.com" },
    fieldValues: { memberName: "Nimal Perera" },
  },
  { idempotencyKey: idempotencyKey("membership-pass", registrationId) },
);

console.log(pass.id);
console.log(pass.distributionUrl);
```

The SDK converts `holder.name` and `holder.email` into the API's `holderName` and `holderEmail`. You can also supply those flat properties directly; a supplied nested value takes precedence.

Save the returned pass ID in your database. Send `distributionUrl` to the holder through your own email, SMS or application flow. Issuing a pass does not add it to their phone automatically. See [Deliver passes](https://tapace.lk/docs/guides/deliver-passes.md).

For your own wallet buttons, use `pass.appleDownloadUrl` or `pass.googleSaveUrl`. Either may be `null`; the hosted distribution page is a fallback.

## Update the same pass

Continue in the same script, after issuance:

```typescript theme={null}
const result = await tapace.passes.update(
  pass.id,
  { fieldValues: { memberName: "Nimal P." }, notificationMode: "silent" },
  { idempotencyKey: idempotencyKey("membership-name-update", registrationId, 1) },
);

console.log(result.pass.id);
if (result.update) {
  console.log(result.update.id, result.update.delivery);
}
```

The final key part identifies this particular change. Use a new saved operation ID or revision for a different update; keep the key and body unchanged for a retry.

A successful response confirms the API operation, not delivery to every wallet. If `result.update` is present, inspect it later with `tapace.passes.retrieveUpdate(pass.id, result.update.id)`. See [Update passes](https://tapace.lk/docs/guides/update-passes.md).

## Check the installed pass

Open the delivery URL in Safari on an iPhone and add the pass to Apple Wallet. After updating it, confirm the new value on the same installed pass. A silent update changes the pass without a notification banner; absence of an alert is expected.

Read `pass.presence.apple?.activeDevices` or subscribe to [wallet lifecycle webhooks](https://tapace.lk/docs/sdk/node/webhooks.md) to observe installations. API acceptance, an installed pass and a visible wallet change are separate checks. On Apple, a `delivered` status means the update signal was sent successfully; it does not prove the phone has fetched and displayed the new pass.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.