PassMeThat API

Issue, update, and void Apple Wallet and Google Wallet passes from your own systems. Updates push live to installed passes — no re-issuing.

Authentication

Create an API key on your dashboard's API & Webhooks page (Growth plan or higher) and send it as a Bearer token. Keys are shown once and can be revoked at any time.

curl https://passmethat.com/api/v1/templates \
  -H "Authorization: Bearer pmt_live_..."

Rate limit: 120 requests/minute per key. Exceeding it returns 429 with a Retry-After header.

Endpoints

GET/api/v1/templatesList templates + their placeholder fields
GET/api/v1/passesList passes (?page=, ?status=active|voided)
POST/api/v1/passesIssue a pass from a published template
GET/api/v1/passes/{serial}Get one pass
PATCH/api/v1/passes/{serial}Merge data fields + push live updates
DELETE/api/v1/passes/{serial}Void a pass

Issue a pass

data keys fill the {placeholders} used in your template design (list them via /api/v1/templates). The response contains a hosted claim page your customer opens to add the pass on either platform.

curl -X POST https://passmethat.com/api/v1/passes \
  -H "Authorization: Bearer pmt_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": 12,
    "data": { "name": "Alex Rivera", "points": "100", "tier": "Gold" }
  }'

# 201 →
{
  "serial":    "PMT4B0E40182988",
  "claimUrl":  "https://passmethat.com/p/ba5e3e827eca",
  "appleUrl":  "https://passmethat.com/api/passes/PMT4B0E40182988/apple",
  "googleUrl": "https://passmethat.com/api/passes/PMT4B0E40182988/google"
}

Update a pass (live)

PATCH merges the fields you send into the pass. Installed copies refresh automatically — Apple via push notification, Google via the Wallet API. The response reports the push result.

curl -X PATCH https://passmethat.com/api/v1/passes/PMT4B0E40182988 \
  -H "Authorization: Bearer pmt_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "data": { "points": "250" } }'

# 200 →
{
  "serial": "PMT4B0E40182988",
  "status": "active",
  "data":   { "name": "Alex Rivera", "points": "250", "tier": "Gold" },
  "push":   { "apple": "pushed 1/1", "google": "patched" },
  ...
}

Webhooks

Register HTTPS endpoints on the dashboard to receive events: pass.issued, pass.updated, pass.voided, pass.installed, pass.uninstalled. Each delivery is signed — verify it with your webhook's secret:

// Node.js signature verification
const crypto = require("crypto");

function verify(rawBody, signatureHeader, secret) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader), Buffer.from(expected));
}

// Delivery shape
{
  "id": "evt_1a2b3c4d",
  "event": "pass.installed",
  "createdAt": "2026-07-02T20:15:00.000Z",
  "data": { "serial": "PMT4B0E40182988", "platform": "apple" }
}

Errors

401 — missing or invalid API key

402 — trial ended, no active subscription

403 — plan doesn't include this feature (e.g. API on Starter) or limit reached

404 — pass or template not found (or belongs to another organization)

429 — rate limit exceeded; retry after the Retry-After seconds

All errors return JSON: { "error": "human-readable message" }