# PassFast Docs

> PassFast lets you generate Apple Wallet and Google Wallet passes via API.
> Design a template, call the API with dynamic data, and get a signed
> `.pkpass` file (Apple) or a save URL (Google) back.

This markdown file mirrors the public HTML docs at https://passfa.st/docs
(Getting Started, Authentication, Quick Start generate) plus pricing facts
from https://passfa.st/#pricing. The machine-readable API is
https://passfa.st/openapi.yaml — that is the only API surface.

- Site: https://passfa.st
- API host: https://api.passfa.st
- API base: https://api.passfa.st/functions/v1
- Sign up: https://passfa.st/signup
- Index for AI agents: https://passfa.st/llms.txt
- API overview (markdown): https://passfa.st/api.md
- MCP (markdown): https://passfa.st/mcp.md
- MCP (HTML): https://passfa.st/docs/mcp
- Full AI index: https://passfa.st/llms-full.txt

Last updated: 2026-09-20

## Getting Started

### How it works

1. **Create a template** — define pass style, colors, fields, and images in the Template Builder (`/dashboard/templates`).
2. **Publish the template** — lock it so passes can be generated from it.
3. **Call the API** — `POST` the template ID and dynamic data. You get back an Apple `.pkpass` binary, a Google save URL, or both.
4. **Deliver to your users** — serve the `.pkpass` to iOS/macOS, redirect to the Google save URL, or use a share link that handles both wallets.

### Authentication

PassFast uses two types of API keys. Manage them on the API Keys page after signup.

| Key type | Prefix | Use case | Scopes |
| --- | --- | --- | --- |
| Secret | `sk_live_` | Server-side only. Full API access. | All |
| Publishable | `pk_live_` | Client-side (browser). Can only generate and download passes. | `passes:create`, `passes:download` |

All requests use a Bearer token:

```
Authorization: Bearer sk_live_your_secret_key_here
```

If the organization has multiple apps, include `X-App-Id` to target a specific
app. For single-app orgs this header is optional.

### Quick Start: generate your first pass

Before you begin:

- An API key from the API Keys page
- A published template from the Templates page
- Signing credentials — during onboarding choose **managed signing** (PassFast signs for you; no certificates) or **custom signing** (your own Apple `.p12` and/or Google service account). Change this anytime in Settings.

Generate both wallets (recommended):

```
curl -X POST https://api.passfa.st/functions/v1/generate-pass \
  -H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
  -H "X-App-Id: YOUR_APP_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": "YOUR_TEMPLATE_ID",
    "serial_number": "PASS-001",
    "wallet_type": "both",
    "data": {
      "memberName": "Jane Smith",
      "memberId": "MEM-12345"
    }
  }'
```

Example JSON response (`wallet_type: "both"`):

```
{
  "apple": {
    "id": "uuid",
    "serial_number": "PASS-001",
    "wallet_type": "apple",
    "status": "active",
    "download_url": "/manage-passes/<id>/download"
  },
  "google": {
    "id": "uuid",
    "serial_number": "PASS-001",
    "wallet_type": "google",
    "status": "active",
    "save_url": "https://pay.google.com/gp/v/save/...",
    "google_object_id": "issuerId.passId"
  },
  "warnings": []
}
```

Use `wallet_type: "both"` to generate Apple and Google in one call. For
Apple-only, omit `wallet_type` (defaults to `"apple"`) and pipe to
`--output pass.pkpass`. For Google-only, set `wallet_type: "google"`.

Official TypeScript SDK (`npm install @passfast/sdk`):

```
import { PassFast } from "@passfast/sdk";

const pf = new PassFast("sk_live_YOUR_SECRET_KEY");

const { passId, pkpassData } = await pf.passes.generate({
  template_id: "YOUR_TEMPLATE_ID",
  serial_number: "PASS-001",
  data: { memberName: "Jane Smith", memberId: "MEM-12345" },
});
```

### Request body (`POST /generate-pass`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `template_id` | string | Yes | ID of a published template |
| `serial_number` | string | Yes | Unique serial number for this pass |
| `data` | object | Yes | Dynamic values matching the template's field schema |
| `wallet_type` | string | No | `"both"` (recommended), `"apple"` (default), or `"google"` |
| `external_id` | string | No | Your own identifier for cross-referencing |
| `expires_at` | string | No | ISO 8601 expiration date |
| `get_or_create` | boolean | No | Return existing active pass instead of 409 on duplicate serial (default: false) |

Scope: `passes:create`.

## Pricing

Pricing on the marketing site is https://passfa.st/#pricing (there is no
separate `/pricing` HTML page). Markdown: https://passfa.st/pricing.md

Pricing: $0.015 per active pass / month (Apple+Google = 1). First 100 generates free once. Expired passes bill until void/delete. Card required after free allowance.

- Sign up: https://passfa.st/signup

## FAQ

**Q: What is an active pass?**  
A: Any pass that is not voided or deleted. Expired passes are still active for billing until you void or delete them.

**Q: Do expired passes cost money?**  
A: Yes, until you void or delete them. PassFast does not auto-remove expired passes from billing.

**Q: What is the free 100?**  
A: Your first 100 pass generates are free. That allowance is used at create time and is not refilled if you void a pass.

**Q: When do I need a card?**  
A: After you’ve used your 100 free generates, you must add a payment method before creating more passes. You’re then billed $0.015 per active pass each month.

**Q: Why was I charged for an expired pass?**  
A: Expiration does not stop billing. Void or delete the pass to stop charges from the next period.

## API Reference

Base: `https://api.passfa.st/functions/v1`

Full OpenAPI 3 spec (source of truth for paths, bodies, and errors):
https://passfa.st/openapi.yaml

HTML API Reference (generated from that spec): https://passfa.st/docs
(section “API Reference”).

### Auth reminder

```
Authorization: Bearer sk_live_...   # or pk_live_... where scopes allow
X-App-Id: YOUR_APP_ID               # required when the org has multiple apps
```

Member-management endpoints use a Supabase JWT instead of API keys.

## MCP

MCP clients (Cursor / Claude / ChatGPT / Codex / Grok) can call the same
key-auth API. Paste `sk_live_…` once in the client config — no OAuth.
This server accepts only a secret key (`pk_live_` is rejected).

- Endpoint: https://passfa.st/mcp (Streamable HTTP; alias `/api/mcp`)
- Install: https://passfa.st/docs/mcp and https://passfa.st/mcp.md
- Tool names = OpenAPI `operationId`s (`generatePass`, `listTemplates`, …)

```
Authorization: Bearer sk_live_YOUR_SECRET_KEY
X-App-Id: YOUR_APP_ID
```

Member/invite tools (`listMembers`, `inviteMember`, `acceptInvitation`,
`updateMemberRole`, `removeMember`, `listInvitations`, `revokeInvitation`)
are **out of scope for key-auth MCP v1** (they need a user JWT).

### Passes

| Method | Path | Summary |
| --- | --- | --- |
| POST | `/generate-pass` | Generate Apple, Google, or both |
| GET | `/manage-passes` | List passes |
| GET | `/manage-passes/{id}` | Get a pass |
| PATCH | `/manage-passes/{id}` | Update a pass (triggers wallet push) |
| GET | `/manage-passes/{id}/download` | Download Apple `.pkpass` |
| POST | `/manage-passes/{id}/void` | Void a pass |
| GET | `/manage-passes/serial/{serial_number}` | Get by serial |
| PATCH | `/manage-passes/serial/{serial_number}` | Update by serial |
| GET | `/manage-passes/serial/{serial_number}/download` | Download by serial |
| POST | `/manage-passes/serial/{serial_number}/void` | Void by serial |

### Templates

| Method | Path | Summary |
| --- | --- | --- |
| GET | `/manage-templates` | List templates |
| POST | `/manage-templates` | Create a template |
| GET | `/manage-templates/{id}` | Get a template |
| PATCH | `/manage-templates/{id}` | Update a template |
| DELETE | `/manage-templates/{id}` | Delete a template |
| POST | `/manage-templates/{id}/publish` | Publish a template |

### Images, certificates, org, keys, sharing

| Method | Path | Summary |
| --- | --- | --- |
| GET\|POST | `/manage-images` | List or upload images |
| GET\|POST | `/manage-certs` | List or upload Apple certs |
| POST | `/manage-certs/p12` | Upload a `.p12` bundle |
| GET\|POST | `/manage-certs/google` | List or upload Google credentials |
| GET\|PATCH | `/manage-org` | Organization settings / webhooks |
| GET\|POST | `/manage-keys` | List or create API keys |
| POST | `/share-pass/create` | Create a public share token |
| GET | `/share-pass/{token}` | Public share metadata (no auth) |
| GET | `/share-pass/{token}/download` | Public Apple `.pkpass` download |

Other operations (image usage, cert tests, members/invites, webhook events)
are documented in https://passfa.st/openapi.yaml.

## HTML docs sections (JS app)

The page at https://passfa.st/docs also includes Core Concepts, Setup &
Configuration, Backend Integration, Web Integration, Pass Distribution,
Working with Images, Webhooks, MCP Server, Error Reference, and Changelog.
Those sections are not duplicated here; use the HTML docs or the OpenAPI spec.

## Links

- Product: https://passfa.st/
- Pricing (HTML): https://passfa.st/#pricing
- Pricing (markdown): https://passfa.st/pricing.md
- Sign up: https://passfa.st/signup
- API overview (markdown): https://passfa.st/api.md
- OpenAPI: https://passfa.st/openapi.yaml
- MCP: https://passfa.st/docs/mcp
- MCP markdown: https://passfa.st/mcp.md
- Full AI index: https://passfa.st/llms-full.txt
- Privacy: https://passfa.st/privacy
- Terms: https://passfa.st/terms
