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
/api/v1/templatesList templates + their placeholder fields/api/v1/passesList passes (?page=, ?status=active|voided)/api/v1/passesIssue a pass from a published template/api/v1/passes/{serial}Get one pass/api/v1/passes/{serial}Merge data fields + push live updates/api/v1/passes/{serial}Void a passIssue 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" }