Passport
All documentation

Node SDK

Start with the account-backed connection check. The download includes the compiled Node ESM SDK, type declarations and a runnable diagnostic. It requires Node.js 24+ but no registry access or dependency install.

Download and run

Download Node starter · Download SHA-256 manifest

Extract the archive, open passport-node-starter, and copy the non-secret environment settings from Dashboard → Set up. Set the key-file path and run:

export PASSPORT_PRIVATE_KEY_FILE='/absolute/path/agent.private.pem'
npm run check

The other required variables are PASSPORT_URL, PASSPORT_ORGANIZATION_ID, PASSPORT_AGENT_ID, and PASSPORT_PROJECT_ID. Setup fills them in. The URL must be the configured issuer origin, not an arbitrary preview alias. Local development must configure discovery and setup for the same local origin.

For secret-managed runtimes, the starter also accepts PASSPORT_AGENT_PRIVATE_KEY (PEM or base64 PEM) when no file path is supplied. Never put that secret in a prompt, committed configuration, or pasted commands.

The check signs exactly this request:

{
  action: "tool",
  parameters: {
    server: "passport-onboarding",
    tool: "connection_check",
    arguments: {},
    amount: 1
  },
  source: "local-dev"
}

The starter requires a denied / POLICY_DENIED response with a correctly bound signed receipt. It fetches the configured issuer's discovery without following redirects, checks its origin and decision-signing key, and verifies the receipt against the complete request. An allowed or pending response is an error here, not success. No execution request is sent.

Use the SDK in your application

The package is not published to npm. From your own application's directory, install the extracted local package:

npm install /absolute/path/passport-node-starter/packages/sdk

Then construct a client in the trusted runtime, not in browser or model code:

import { readFile } from "node:fs/promises";
import { PassportClient } from "@passport-ai/sdk";

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`${name} is required`);
  return value;
}

const passport = PassportClient.connect({
  baseUrl: required("PASSPORT_URL"),
  organizationId: required("PASSPORT_ORGANIZATION_ID"),
  agentId: required("PASSPORT_AGENT_ID"),
  projectId: required("PASSPORT_PROJECT_ID"),
  privateKey: await readFile(required("PASSPORT_PRIVATE_KEY_FILE"), "utf8"),
  source: "server",
});

For a KMS/HSM, use new PassportClient({ ...options, signer }) with a custom Signer that signs canonical bytes. The runtime must validate proposed actions before signing; possession of a key alone is not proof of safe code.

Authorization is not execution

passport.authorize({ action, parameters }) signs and submits a request. Its result uses status and reasonCode, not a boolean:

  • denied: stop. A receipt is evidence of denial, never execution permission.
  • pending: wait for a human through waitForDecision(result). Timeout or network failure must stop the action.
  • allowed: the action still needs the appropriate guarded executor.

Protocol/authentication errors throw PassportError; recorded denials resolve normally. Keep authorizationToken secret. It is a scoped bearer token for status and execution, not a model-facing explanation.

For configured Vercel and HTTP integrations, execute(result) invokes Passport's relay and its live checks. For custom tools or payments, implement a trusted enforcement point with fresh permission checks and replay protection; do not execute merely because verifyReceipt returns true.

The SDK exports receipt and credential signature helpers. They do not infer a trusted issuer or prove live revocation status. Pin the intended issuer, bind all expected request details, and consult verification. The starter implements stronger, diagnostic-specific checks on top of these helpers.

Requests default to five minutes of validity; the protocol maximum is fifteen. Approval and execution windows are separate.

When the check fails

Check the issuer URL, IDs, key file and diagnostic configuration. A lost or rotated key requires the current private key. A missing receipt, unexpected decision, issuer mismatch or invalid signature must be investigated, not ignored. Recheck the setup panel and prepare a new isolated check if the old grant or deny policy has changed. Do not convert that deny policy into an allow.