Introduction
This article guides you through setting up and utilizing PassKit webhooks to receive instant notifications about key events related to your digital passes. Webhooks enable you to:
React Instantly: Trigger actions in your systems the moment a pass is issued, installed, uninstalled, updated or deleted.
Maintain Data Synchronization: Keep your CRM, POS, analytics dashboards, and other systems in perfect sync with PassKit data.
Enhance Customer Engagement: Send timely communications (emails, SMS) based on real-time pass activity.
Automate Workflows: Update pass records, activate coupons, and manage tickets automatically.
Gain Deeper Insights: Feed real-time data into your reporting and analytics platforms.
What are Webhooks?
Think of webhooks as real-time messengers. Instead of your applications constantly asking PassKit for updates (polling), PassKit proactively pushes data to your specified URL whenever an event occurs. This "push" method is efficient, reducing unnecessary traffic and ensuring you receive only the information you need.
Key Benefits of Using PassKit Webhooks
Real-time Updates: Stay informed about pass activity as it happens.
Automation: Automate critical workflows and reduce manual tasks.
Improved Efficiency: Minimize API polling and optimize resource usage.
Enhanced Customer Experience: Deliver personalized and timely interactions.
Supported Event Types
PassKit webhooks are triggered by the following events:
Pass Created
Request Type: HTTP POST
Event: Fired when a new pass record is created (e.g., membership card, loyalty card, coupon, ticket, etc.). Contains information about where and when the pass was issued.
Example Use Case: Update your CRM, send a welcome message, or activate a coupon/ticket in your system.
Pass Installed
Request Type: HTTP PUT
Event: Fired when a user installs a pass in their mobile wallet. Contains information about the wallet type, IP address, and installation time.
Example Use Case: Track pass installation status and wallet type in your CRM.
Pass Uninstalled
Request Type: HTTP PUT
Event: Fired when a user removes a pass from their mobile wallet. Contains information about the wallet type, IP address, and country where the pass was installed.
Example Use Case: Track pass removal and update your system accordingly.
Pass Updated
Request Type: HTTP PUT
Event: Fired when a pass record is updated in PassKit. Contains the updated pass data.
Example Use Case: Sync updated pass data with your CRM or other systems.
Pass Deleted
Request Type: HTTP DELETE
Event: Fired when a pass record is deleted from PassKit.
Example Use Case: Confirm that a pass record has been deleted from your account.
Important
Your webhook endpoint must respond with an HTTP 200 OK status code to acknowledge receipt of the notification.
Practical Use Cases and Payload Examples
Pass Created
This is a useful event to use in combination with SmartPass links. Because the first time a SmartPass link is clicked, it results in a pass record being created in the PassKit database, so you can use this even to for example:
update the pass record with the latest record data from your system.
send a welcome email / SMS to your customer containing their real pass link or welcome message.
store the unique PassKit ID or URL against your customer record in a CRM or POS.
'activate' or provision a coupon SKU in your POS or coupon software.
'activate' or set a ticket as 'issued' in your ticketing system.
Payload example:
{
"event": "PASS_EVENT_RECORD_CREATED",
"pass": {
"id": "5u5EO18473CDVG0Vw0VgPV",
"classId": "24hmYozRggBJTtPt0Y2e3X",
"protocol": 100,
"personDetails": {
"displayName": "Patrick Kosterman",
"emailAddress": "patrick@passkit.com"
},
"metadata": {
"utm": {},
"issueIpAddress": "92.237.10.176",
"issueAt": {
"seconds": 1608644518,
"nanos": 743534000
}
},
"recordData": {
"design.pointsType": "int",
"members.member.externalId": "ABC123",
"members.member.points": "10.000000",
"members.member.secondaryPoints": "0.000000",
"members.member.status": "ACTIVE",
"members.member.tierPoints": "0",
"members.program.id": "24hmYozRggBJTtPt0Y2e3X",
"members.program.name": "CodeREADR Points \u0026 Tier Demo",
"members.tier.id": "bronze",
"members.tier.name": "Bronze",
"person.displayName": "Patrick Kosterman",
"person.emailAddress": "patrick@passkit.com",
"universal.issued": "2020-12-22T13:41:58Z",
"universal.optOut": "no",
"universal.status": "PASS_ISSUED"
}
}
}
Pass Installed
This is a useful event if you are tracking the pass 'status' in your own CRM or system and want to know which of your customers have installed the pass in wallet, when and in which wallet.
Payload example:
{
"event": "PASS_EVENT_INSTALLED",
"pass": {
"id": "5u5EO18473CDVG0Vw0VgPV",
"classId": "24hmYozRggBJTtPt0Y2e3X",
"protocol": 100,
"personDetails": {
"displayName": "Patrick Kosterman",
"emailAddress": "patrick@passkit.com"
},
"metadata": {
"status": 1,
"lifecycleEvents": [1, 2],
"utm": {},
"altId": "5u5EO18473CDVG0Vw0VgPV",
"issueIpAddress": "92.237.10.176",
"installIpAddress": "92.237.10.176",
"renderLocation": {
"country": "GB",
"city": "Islington",
"state": "England",
"latitude": 51.536,
"longitude": -0.0925
},
"renderIpAddress": "92.237.10.176",
"installUserAgent": "PassKitCore/1.0 CFNetwork/1206 Darwin/20.1.0",
"renderUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15",
"installDeviceAttributes": [1, 512],
"renderDeviceAttributes": [4, 128, 1024],
"issueAt": {
"seconds": 1608644518,
"nanos": 743534000
},
"renderedAt": {
"seconds": 1608644536,
"nanos": 416327000
},
"firstInstalledAt": {
"seconds": 1608644748,
"nanos": 43410000
},
"lastInstalledAt": {
"seconds": 1608644748,
"nanos": 43410000
}
},
"recordData": {
"design.pointsType": "int",
"members.member.externalId": "ABC123",
"members.member.points": "10.000000",
"members.member.secondaryPoints": "0.000000",
"members.member.status": "ACTIVE",
"members.member.tierPoints": "0",
"members.program.id": "24hmYozRggBJTtPt0Y2e3X",
"members.program.name": "CodeREADR Points \u0026 Tier Demo",
"members.tier.id": "bronze",
"members.tier.name": "Bronze",
"person.displayName": "Patrick Kosterman",
"person.emailAddress": "patrick@passkit.com",
"universal.issued": "2020-12-22T13:41:58Z",
"universal.optOut": "no",
"universal.status": "PASS_INSTALLED"
}
}
}
Pass Uninstalled
This is a useful event if you are tracking the pass 'status' in your own CRM or system and want to know which of your customers have removed the pass from their wallet.
Payload example:
{
"event": "PASS_EVENT_RECORD_UPDATED",
"pass": {
"id": "5u5EO18473CDVG0Vw0VgPV",
"classId": "24hmYozRggBJTtPt0Y2e3X",
"protocol": 100,
"personDetails": {
"displayName": "Patrick Kosterman",
"emailAddress": "patrick@passkit.com"
},
"metadata": {
"status": 2,
"lifecycleEvents": [1, 2, 1024],
"utm": {},
"altId": "5u5EO18473CDVG0Vw0VgPV",
"issueIpAddress": "92.237.10.176",
"installIpAddress": "92.237.10.176",
"renderLocation": {
"country": "GB",
"city": "Islington",
"state": "England",
"latitude": 51.536,
"longitude": -0.0925
},
"renderIpAddress": "92.237.10.176",
"installUserAgent": "PassKitCore/1.0 CFNetwork/1206 Darwin/20.1.0",
"renderUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15",
"installDeviceAttributes": [1, 512],
"renderDeviceAttributes": [4, 128, 1024],
"issueAt": {
"seconds": 1608644518,
"nanos": 743534000
},
"renderedAt": {
"seconds": 1608644536,
"nanos": 416327000
},
"firstInstalledAt": {
"seconds": 1608644748,
"nanos": 43410000
},
"lastInstalledAt": {
"seconds": 1608644748,
"nanos": 43410000
},
"firstUninstalledAt": {
"seconds": 1608645679,
"nanos": 83822000
},
"lastUninstalledAt": {
"seconds": 1608645679,
"nanos": 83822000
}
},
"recordData": {
"design.pointsType": "int",
"members.member.externalId": "ABC123",
"members.member.id": "5u5EO18473CDVG0Vw0VgPV",
"members.member.points": "100.000000",
"members.member.secondaryPoints": "0.000000",
"members.member.status": "ENROLLED",
"members.member.tierPoints": "0",
"members.program.id": "24hmYozRggBJTtPt0Y2e3X",
"members.program.name": "CodeREADR Points \u0026 Tier Demo",
"members.tier.id": "bronze",
"members.tier.name": "Bronze",
"person.displayName": "Patrick Kosterman",
"person.emailAddress": "patrick@passkit.com",
"universal.issued": "2020-12-22T13:41:58Z",
"universal.optOut": "no",
"universal.status": "PASS_UNINSTALLED"
}
}
}
Pass Updated
This is a useful event if you want a PassKit to deliver information when a pass record is modified. For example you might use the PassReader app to check-in a member, or change the tier of a person, or manually add points when you scan their pass. And you want this information to automatically propagate to your booking software or CRM.
Payload example:
{
"event": "PASS_EVENT_RECORD_UPDATED",
"pass": {
"id": "5u5EO18473CDVG0Vw0VgPV",
"classId": "24hmYozRggBJTtPt0Y2e3X",
"protocol": 100,
"personDetails": {
"displayName": "Patrick Kosterman",
"emailAddress": "patrick@passkit.com"
},
"metadata": {
"status": 1,
"lifecycleEvents": [1, 2],
"utm": {},
"altId": "5u5EO18473CDVG0Vw0VgPV",
"issueIpAddress": "92.237.10.176",
"installIpAddress": "92.237.10.176",
"renderLocation": {
"country": "GB",
"city": "Islington",
"state": "England",
"latitude": 51.536,
"longitude": -0.0925
},
"renderIpAddress": "92.237.10.176",
"installUserAgent": "PassKitCore/1.0 CFNetwork/1206 Darwin/20.1.0",
"renderUserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Safari/605.1.15",
"installDeviceAttributes": [1, 512],
"renderDeviceAttributes": [4, 128, 1024],
"issueAt": {
"seconds": 1608644518,
"nanos": 743534000
},
"renderedAt": {
"seconds": 1608644536,
"nanos": 416327000
},
"firstInstalledAt": {
"seconds": 1608644748,
"nanos": 43410000
},
"lastInstalledAt": {
"seconds": 1608644748,
"nanos": 43410000
}
},
"recordData": {
"design.pointsType": "int",
"members.member.externalId": "ABC123",
"members.member.id": "5u5EO18473CDVG0Vw0VgPV",
"members.member.points": "100.000000",
"members.member.secondaryPoints": "0.000000",
"members.member.status": "ENROLLED",
"members.member.tierPoints": "0",
"members.program.id": "24hmYozRggBJTtPt0Y2e3X",
"members.program.name": "CodeREADR Points \u0026 Tier Demo",
"members.tier.id": "bronze",
"members.tier.name": "Bronze",
"person.displayName": "Patrick Kosterman",
"person.emailAddress": "patrick@passkit.com",
"universal.issued": "2020-12-22T13:41:58Z",
"universal.optOut": "no",
"universal.status": "PASS_INSTALLED"
}
}
}
Setup up Webhooks
Using PassKit's UI
Webhooks are setup on a project level. It is supported to setup multiple webhooks to different endpoints for different events. The settings can be found under "Your Project" >> "Settings" >> "Integrations" >> "Webhooks":
Using the API
Endpoint for configuring webhooks is:
POST OR PUT https://api.pub1.passkit.io/integrations/sink
Payload example (for POST and PUT):
{
// Webhook id required at PUT call.
"id": "6MAyTmvzoJuV3tsRmHFM8U",
// Member program id or Coupon campaign id.
"classId": "3wiJKeMm5wD6ZrFqjuX4rL",
// Please set MEMBERSHIP or SINGLE_USE_COUPON.
"protocol": "SINGLE_USE_COUPON",
// Available passEventId are PASS_EVENT_RECORD_CREATED, PASS_EVENT_INSTALLED, PASS_EVENT_RECORD_UPDATED, PASS_EVENT_UNINSTALLED, PASS_EVENT_INVALIDATED, PASS_EVENT_RECORD_DELETED
"passEventId": ["PASS_EVENT_RECORD_CREATED"],
"status": "INTEGRATION_ACTIVE",
"configType": "WEBHOOK",
// Please set the destination URL with stringify JSON
"configuration": " {\"targetUrl\":\"https://yourwebhookurl/y4rsldy5\"}"
}
To get, update or delete Membership webhook:
GET or DELETE https://api.pub1.passkit.io/integrations/sink/MEMBERSHIP/{webhook_id}
To get, update or delete Coupon webhook:
GET or DELETE https://api.pub1.passkit.io/integrations/sink/SINGLE_USE_COUPON/{webhook_id}
Webhook Request Body Details
Main Structure
{
// The webhook event type, one of the below:
// PASS_EVENT_RECORD_CREATED
// PASS_EVENT_INSTALLED
// PASS_EVENT_RECORD_UPDATED
// PASS_EVENT_RECORD_UPDATED
"event": "PASS_EVENT_RECORD_UPDATED",
// The pass record details
"pass": {
// The unique 22 character PassKit ID.
"id": "5u5EO18473CDVG0Vw0VgPV",
// The id of the project which the pass belongs to.
"classId": "24hmYozRggBJTtPt0Y2e3X",
// The protocol, which signifies the project type.
// For a list of possible ENUM values see below.
"protocol": 100,
// PII data of the pass holder. Full object details can be found in our member -or coupon documentation in the 'person' object:
// https://docs.passkit.io/protocols/member/#operation/Members_enrolMember
"personDetails": {
"displayName": "Patrick Kosterman",
"emailAddress": "patrick@passkit.com"
...
},
// All the system generated pass meta data. Full object details can be found in our member -or coupon documentation in the 'metaData' object:
// For a list of possible ENUM values in this object see below.
"metaData": {
"status": 1,
"lifecycleEvents": [1, 2],
"utm": {},
"altId": "5u5EO18473CDVG0Vw0VgPV",
"issueIpAddress": "92.237.10.176"
...
}
// Holds protocol specific data for the pass record (e.g. tier points for Membership protocol, flight number for flight protocol)
"recordData": {
"members.member.externalId": "ABC123",
"members.member.id": "5u5EO18473CDVG0Vw0VgPV",
"members.member.points": "100.000000"
...
}
}
}
Pass Meta Data ENUM Values
PassProtocol
enum PassProtocol {
// Flights protocol: https://docs.passkit.io/protocols/boarding/
FLIGHT_PROTOCOL = 3;
// Generic Membership protocol: https://docs.passkit.io/protocols/member/
MEMBERSHIP = 100;
// Single Use Coupon protocol: https://docs.passkit.io/protocols/coupon/
SINGLE_USE_COUPON = 101;
// Event Ticket protocol: https://docs.passkit.io/protocols/event/
EVENT_TICKETING = 102;
// Values 1000 onwards are for proprietary protocols
}
Status
// Status is the best determined status of the pass.
enum Status {
// Pass has been issued.
PASS_ISSUED = 0;
// Pass has been installed in a wallet.
PASS_INSTALLED = 1;
// Pass has been uninstalled (possibly deleted) from a wallet.
PASS_UNINSTALLED = 2;
// Pass has been invalidated.
PASS_INVALIDATED = 3;
}
LifeCycleEvents
// Statuses of the pass. A pass will collect multiple statuses as it passes through its lifecycle.
enum LifecycleEvents {
NO_STATUS = 0;
// Pass has been created and presented to the user to install.
RENDERED = 0x1;
// Pass has been installed in at least one Apple device.
INSTALLED_APPLE = 0x2;
// Pass has been installed in at least one Google Pay account.
INSTALLED_GOOGLE = 0x4;
// Pass has been installed in at least one Android wallet app.
INSTALLED_ANDROID_OTHER = 0x8;
// Pass has been uninstalled from at least one Apple device.
UNINSTALLED_APPLE = 0x400;
// Pass has been uninstalled from at least one Google Pay account.
UNINSTALLED_GOOGLE = 0x800;
// Pass has been uninstalled from at least one Android wallet app.
UNINSTALLED_ANDROID_OTHER = 0x1000;
// An Apple pass bundle has been created.
APPLE_PASS_CREATED = 0x2000;
// A Google Pay record has been created.
GOOGLE_PAY_RECORD_CREATED = 0x4000;
// Invalidation request sent to pass.
INVALIDATE_REQUESTED = 0x40000;
// Pass has been invalidated.
INVALIDATE_CONFIRMED = 0x80000;
}
DeviceAttributes:
enum DeviceAttributes {
NoAttributes = 0;
Ios = 0x1;
Android = 0x2;
SupportWallet = 0x4;
WalletScanner = 0x8;
WalletDaemon = 0x10;
WalletPasses = 0x20;
Windows = 0x40;
OSX = 0x80;
Linux = 0x100;
Mobile = 0x200;
Desktop = 0x400;
Tablet = 0x800;
UnsupportedIos = 0x1000;
}
Security
If you need to whitelist our IP addresses, or need other security measures in place, please contact us about your use-case, and one of our solution engineers will contact you asap to discuss your needs.
Troubleshooting Tips
Verify that your webhook URL is accessible and correctly configured.
Check your server logs for errors.
Ensure your endpoint responds with an HTTP 200 OK status code.
Use a tool like postman or curl to test your webhook endpoint.