Download OpenAPI specification:Download
Welcome to Passentry
PassEntry API is an OpenAPI 3.1.0 compliant REST API with predictable URLs, JSON request bodies, standard HTTP response codes, authentication, and verbs. This documentation describes the functionality of our system available for integration with your business.
API Host https://api.passentry.com
The PassEntry API uses API keys to authenticate requests. You can view and manage your API keys in Developer tools in the PassEntry Dashboard
Your API keys carry many privileges, so be sure to keep them secure. Don't share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth.
Authentication to the API is performed with Bearer authentication. These tokens must be attached to the Authorization header of the request.
Example: "Authorization": "Bearer {API KEY}"
You must make all API calls over HTTPS. Calls that you make over plain HTTP will fail. API requests without authentication will also fail.
PassEntry API responses are generally in JSON API format, which provides a consistent standard for formatting responses in JSON, including a top-level data
object and optional included
and meta
objects.
PassEntry uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx
range indicate success. Codes in the 4xx
range indicate an error that failed given the information provided (e.g., a required parameter was omitted, syntax error, etc.). Codes in the 5xx
range indicate an error with PassEntry's servers (these are rare).
Some 4xx
errors include text that briefly explains the error reported.
What are entities?
Entities serve as subdivisions within an organization, designed to help larger clients such as aggregators or resellers manage their operations more effectively. Each entity can represent a different department or business unit within the larger organization, enabling detailed segmentation and breakdowns.
A common use case of having multiple entities is separating the passes in the Wallet (Most commonly an issue in Apple Wallet) as passes from different entities are not grouped in the Wallet.
All organisations have one entity by default. For most organisations, this is sufficient. If you would like to create additional entities, please contact PassEntry.
Example
An organisation, "PassEntry Enterprise" has 2 business units, "PassEntry Supermarket" and "PassEntry Coffee". In order to keep their information and data separate, they have 2 Entities, each with their own Pass Templates, Passes...etc
{- "data": [
- {
- "id": "0d10c850",
- "type": "entity",
- "attributes": {
- "name": "PassEntry Fitness Centre",
- "passDeeplinks": {
- "apple": "shoebox://pass/pass.com.test.test/{PASSENTRY_PASS_UUID}",
}
}
}, - {
- "id": "0d10c84f",
- "type": "entity",
- "attributes": {
- "name": "PassEntry Coffee",
- "passDeeplinks": {
- "apple": "shoebox://pass/pass.com.test.test/{PASSENTRY_PASS_UUID}",
}
}
}, - {
- "id": "0d10c84e",
- "type": "entity",
- "attributes": {
- "name": "PassEntry Supermarket",
- "passDeeplinks": {
- "apple": "shoebox://pass/pass.com.test.test/{PASSENTRY_PASS_UUID}",
}
}
}
], - "meta": {
- "totalCount": 3,
- "resultsPerPage": 25,
- "currentPage": 1,
- "totalPages": 1
}, - "links": {
- "first": null,
- "prev": null,
- "next": null,
- "last": null
}
}
{- "data": {
- "id": "37ae0eaa",
- "type": "entity",
- "attributes": {
- "name": "PassEntry Supermarket",
- "passDeeplinks": {
- "apple": "shoebox://pass/pass.com.test.test/{PASSENTRY_PASS_UUID}",
}
}
}
}
Before creating passes using the PassEntry API, it is necessary to have a pass template built. A template serves as a blueprint for your passes and includes various components such as fields, colours, images and value keys.
Create pass template
To create a pass template, you can do so directly from the Dashboard, in the Pass Templates page. Click the button 'Create Pass Template' in the top right corner (direct link: https://passentry.com/pass-templates/create).
Once created, the pass template will be shown in the Pass Templates page.
See pass templates list
All pass templates are displayed in the Pass Templates page of your Dashboard (direct link: https://passentry.com/pass-templates).
successful
Error: Unauthorized
Error: Not Found
{- "data": {
- "id": "f0af94dc3c69a80cee32c173",
- "type": "passTemplate",
- "attributes": {
- "backgroundColor": "#EFEFEF",
- "name": "Summer Sale 2023",
- "description": "Summer Sale Pass",
- "labelColor": "#FF8477",
- "textColor": "#29323A",
- "templateType": "storeCard",
- "header": {
- "header_one": {
- "id": "name",
- "label": "Name",
- "default_value": null
}, - "header_two": {
- "id": null,
- "label": null,
- "default_value": null
}, - "header_three": {
- "id": null,
- "label": null,
- "default_value": null
}
}, - "primary": {
- "primary_one": {
- "id": "attendee",
- "label": "Attendee",
- "default_value": null
}, - "primary_two": {
- "id": null,
- "label": null,
- "default_value": null
}
}, - "secondary": {
- "secOne": {
- "id": "address",
- "label": "Address",
- "default_value": null
}, - "secTwo": {
- "id": null,
- "label": null,
- "default_value": null
}, - "secThree": {
- "id": null,
- "label": null,
- "default_value": null
}
}, - "auxiliary": {
- "auxOne": {
- "id": "dob",
- "label": "DOB",
- "default_value": null
}, - "auxTwo": {
- "id": null,
- "label": null,
- "default_value": null
}, - "auxThree": {
- "id": null,
- "label": null,
- "default_value": null
}
}, - "backFields": {
- "backOne": {
- "id": "website",
- "label": "Website",
- "default_value": null
}, - "backTwo": {
- "id": null,
- "label": null,
- "default_value": null
}, - "backFive": {
- "id": null,
- "label": null,
- "default_value": null
}, - "backFour": {
- "id": null,
- "label": null,
- "default_value": null
}, - "backThree": {
- "id": null,
- "label": null,
- "default_value": null
}
}
}
}
}
{- "data": {
- "id": "506cb78e57ee",
- "type": "event",
- "attributes": {
- "name": "The Lion King Live",
- "venueName": "Lyceum Theathre",
- "startTime": "2023-09-15T11:45:00Z",
- "endTime": "2023-09-15T11:45:00Z",
- "timeZone": "UTC",
- "status": "ended"
}, - "meta": {
- "passesCount": 0
}
}
}
successful
Error: Unauthorized
Error: Unprocessable Entity
{- "event": {
- "name": "Bob Marley Live",
- "venueName": "The Lyceum Theatre",
- "startDatetime": "1975-07-17T22:30:00+01:00",
- "endDatetime": "1975-07-18T02:30:00+01:00",
- "timeZone": "Europe/London"
}
}
{- "data": {
- "id": "506cb78e57ee",
- "type": "event",
- "attributes": {
- "name": "The Lion King Live",
- "venueName": "Lyceum Theathre",
- "startTime": "2023-09-15T11:45:00Z",
- "endTime": "2023-09-15T11:45:00Z",
- "timeZone": "UTC",
- "status": "ended"
}, - "meta": {
- "passesCount": 0
}
}
}
Created
Error: Unauthorized
Error: Unprocessable Entity
{- "event": {
- "name": "Bob Marley Live",
- "venueName": "The Lyceum Theatre",
- "startDatetime": "1975-07-17T22:30:00+01:00",
- "endDatetime": "1975-07-18T02:30:00+01:00",
- "timeZone": "Europe/London"
}
}
{- "data": {
- "id": "9f1e67ca17ee",
- "type": "event",
- "attributes": {
- "name": "Bob Marley Live",
- "venueName": "The Lyceum Theatre",
- "startTime": "1975-07-17T22:30:00+01:00",
- "endTime": "1975-07-18T02:30:00+01:00",
- "timeZone": "Europe/London",
- "status": "ended"
}, - "meta": {
- "passesCount": 0
}
}
}
PassEntry supports wallet-native push notifications on both the Apple and Google Wallet.
Use notifications to deliver timely and relevant updates to your customers, such as when the time for an event has changed or that their membership is about to expire. A push notification message will appear on the lock screen and will be stored on the back of the pass as the "Latest Update".
Best practices
Google currently limits their push notifications to 3 per day per pass, if you go over this quota, the passholder will not receive a push notification on their lock screen, but it will update the "Latest Update" on the back of the pass.
Apple limits their push notifications to 10 per day and may sometimes not show push notifications if sent within a very short interval (seconds between notifications)
We suggest limiting the maximum number of notifications per day per pass to 3
When creating a pass, we return a JSON object with pass attributes and timestamps. Within this object, we include a downloadUrl
, unique to each pass, which when clicked by the end user will open a generic pass download page, a web view hosted by PassEntry on download.passentry.com
.
As at this stage, the passholder's device type is unknown, one of the purposes of this download page is to detect the user's device and deliver either an Apple Wallet pass or Google Wallet pass. When the download page is opened on a device other than an iPhone or Android phone, it will display a QR code directing the user to the same URL, in order to direct them to open the download page on a mobile device.
Using this download page enables simple distribution of passes to your customers via a generic, dynamic link. As a best practice, we suggest putting the downloadUrl
behind a button or redirecting the user to it at a desired point in their user journey.
In some cases, use of the download page is not a viable option, such as when provisioning the pass from within an app, or when wanting to directly deliver the pass from within a web page, without redirecting the user to PassEntry's download page.
In order for this to be possible, you must know the device type when creating the pass. When delivering the pass from within an app, the device type will already be known. When delivering from a web page, there are a number of scripts that can be used to detect the device type and request the correct pass source.
Here is a sample script:
// JavaScript
const getMobileOS = () => {
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
if (/android/i.test(userAgent)) {
return "Android";
} else if (/iPhone/i.test(userAgent)) {
return "iPhone";
}
return "Other";
};
// Example usage
const mobileOS = getMobileOS();
console.log(`This page is opened on: ${mobileOS}`);
Once the device is known, request and deliver the correct Pass Source.
To request the Pass Source, include the ?includePassSource
query parameter in your POST /passes/
or GET /passes/:id
request. This parameter accepts apple
or google
as options. For more details, review the API documentation for these endpoints.
If valid, the response will include the pass attributes in JSON, alongside a passSource
object. It will only return the passSource
object in the response if the selected pass is not currently active in a device.
The passSource
object will contain a key, googleDownloadUrl
, containing a unique URL, which when opened on an Android device, will prompt the user to add their pass to their Google Wallet. As the Google Wallet is linked to an individual Google Account, the user will be prompted to log in to their Google Account if they are not already logged in and to download the Google Wallet if they have not already done so.
The googleDownloadUrl
works best when placed behind Google's "Add to Google Wallet" button. Here are the brand guidelines and assets provided by Google:
Apple requires the pass source to be delivered as a file with a .pkpass
extension. The passSource
object will contain a key, appleBase64
, containing the .pkpass
file encoded in base64. Decode the base64, save it to a file with the .pkpass
extension, and deliver this to the user. When an iPhone detects a .pkpass
file, it will prompt the user to add it to their Apple Wallet. Deliver the pass when the user clicks Apple's "Add to Apple Wallet" button. Here are the brand guidelines and assets provided by Apple:
Succesful
Error: Bad Request
Error: Unauthorized
Error: Not Found
{- "notification": {
- "message": "string"
}
}
{- "data": {
- "id": "e89b1330fc391ec89656f3c664318cff8805471e",
- "type": "pass",
- "attributes": {
- "downloadUrl": "string",
- "passType": "generic",
- "deviceType": "android",
- "createdAt": "string",
- "status": "issued",
- "extId": "string",
- "groupTag": "string",
- "addedAt": "string",
- "removedAt": "string",
- "deactivatedAt": "string",
- "expiresAt": "string",
- "passTemplateUuid": "string",
- "passTemplateName": "string",
- "nfc": "string",
- "barcode": {
- "type": "qrCode",
- "value": "string",
- "displayText": true
}, - "latestMessage": "string",
- "passContent": {
- "templateKey1": "string",
- "templateKey2": "string"
}, - "passDesign": {
- "backgroundColor": "#EFEFEF",
- "labelColor": "#EFEFEF",
- "textColor": "#EFEFEF",
- "bannerImageUrl": "string",
- "logoImageUrl": "string"
}, - "locations": [
- {
- "name": "West Entrance",
- "latitude": 51.54321132456805,
- "longitude": -0.022901231803803924,
- "radius": 90,
- "message": "Welcome! Enjoy the show!",
- "address": "Mick's Garage, Queens Yard, London, England, E9 5EN, United Kingdom"
}
], - "beacons": [
- {
- "proximityUuid": "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0",
- "major": 65535,
- "minor": 8525,
- "message": "You're near my store",
- "name": "West Entrance"
}
], - "passSource": {
- "oneOf": {
- "appleBase64": "string",
- "googleDownloadUrl": "string"
}
}
}
}, - "meta": {
- "notifications": {
- "status": "delivered",
- "message": "Delivered succesfully"
}
}
}
Successful
Error: Bad Request
Error: Unauthorized
Error: Not Found
{- "pass": {
- "nfc": {
- "enabled": true
}, - "fullName": "Jane Smith",
- "qr": {
- "value": "123abcd",
- "displayText": true
}
}, - "locations": [
- {
- "name": "Venue",
- "latitude": 51.54321132456805,
- "longitude": -0.022901231803803924,
- "radius": 100,
- "message": "Welcome to the venue"
}
]
}
{- "data": {
- "id": "33b680b7a5460e6cd4646dfd2c1a8c33a6fbfa5c",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "createdAt": "2022-06-05T10:06:53Z",
- "status": "issued",
- "extId": "123",
- "passTemplateUuid": "2e2d7ee8c306e8f0223dbdc1",
- "passTemplateName": "PassEntry Ticketing",
- "nfc": "33b680b7a5460e6cd4646dfd2c1a8c33a6fbfa5c",
- "barcode": {
- "type": "qrCode",
- "value": "123abcd",
- "displayText": true
}, - "passContent": {
- "nfc": {
- "enabled": true
}, - "fullName": "Jane Smith",
- "qr": {
- "value": "123abcd",
- "displayText": true
}
}, - "locations": [
- {
- "name": "Venue",
- "latitude": 51.54321132456805,
- "longitude": -0.022901231803803924,
- "radius": 100,
- "message": "Welcome to the venue",
- "address": "Blast Analytics, 22 Upper Ground, London, England, SE1 9PD, United Kingdom"
}
]
}
}
}
perPage | integer Record limiter per page. Default is 100 |
status | string Filter passes by status |
deviceType | string Filter passes by device type |
groupTag | string Filter passes by group tag |
passTemplateUuid | string Filter passes by pass template UUID |
passTemplateName | string Filter passes by pass template name. Must be URL encoded |
eventUuid | string Filter passes by event UUID |
eventName | string Filter passes by event name. Must be URL encoded |
createdAfter | string Returns passes created after given datetime. Format is ISO 8601 |
createdBefore | string Returns passes created before given datetime. Format is ISO 8601. Can be combined with createdBefore parameter |
fields | string Returns a partial response (Sparse fieldset) per record, instead of the whole record. Set one or many comma separated record attributes |
includePassDesign | boolean If true, includes the pass design in the response |
Successful
Error: Bad Request
Error: Unauthorized
{- "data": [
- {
- "id": "237f0526-b2aa-4dd1-884b-ed49abbd7447",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "createdAt": "2022-01-08T00:00:00Z",
- "status": "issued",
- "extId": "d994dfcf8b6d0b0a3267",
- "passTemplateUuid": "2e2d7ee8c306e8f0223dbdc1",
- "passTemplateName": "PassEntry Ticketing",
- "nfc": null,
- "barcode": null,
- "passContent": {
- "fullName": "John Johnson"
}
}
}, - {
- "id": "237f0526-b2aa-4dd1-884b-ed49abbd7446",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "createdAt": "2022-01-07T00:00:00Z",
- "status": "issued",
- "extId": "d994dfcf8b6d0b0a3266",
- "passTemplateUuid": "2e2d7ee8c306e8f0223dbdc1",
- "passTemplateName": "PassEntry Ticketing",
- "nfc": null,
- "barcode": null,
- "passContent": {
- "fullName": "John Johnson"
}
}
}, - {
- "id": "237f0526-b2aa-4dd1-884b-ed49abbd7445",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "createdAt": "2022-01-06T00:00:00Z",
- "status": "issued",
- "extId": "d994dfcf8b6d0b0a3265",
- "passTemplateUuid": "2e2d7ee8c306e8f0223dbdc1",
- "passTemplateName": "PassEntry Ticketing",
- "nfc": null,
- "barcode": null,
- "passContent": {
- "fullName": "John Johnson"
}
}
}, - {
- "id": "237f0526-b2aa-4dd1-884b-ed49abbd7444",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "createdAt": "2022-01-05T00:00:00Z",
- "status": "issued",
- "extId": "d994dfcf8b6d0b0a3264",
- "passTemplateUuid": "2e2d7ee8c306e8f0223dbdc1",
- "passTemplateName": "PassEntry Ticketing",
- "nfc": null,
- "barcode": null,
- "passContent": {
- "fullName": "John Johnson"
}
}
}, - {
- "id": "237f0526-b2aa-4dd1-884b-ed49abbd7443",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "createdAt": "2022-01-04T00:00:00Z",
- "status": "issued",
- "extId": "d994dfcf8b6d0b0a3263",
- "passTemplateUuid": "2e2d7ee8c306e8f0223dbdc1",
- "passTemplateName": "PassEntry Ticketing",
- "nfc": null,
- "barcode": null,
- "passContent": {
- "fullName": "John Johnson"
}
}
}
], - "meta": {
- "totalCount": 8,
- "resultsPerPage": 5,
- "currentPage": 1,
- "totalPages": 2
}, - "links": {
- "first": null,
- "prev": null,
- "next": "/api/v1/passes?page=2&perPage=5",
- "last": "/api/v1/passes?page=2&perPage=5"
}
}
object | |||||||
message | string Push Notification message to display. If present, response will include X-Notification-Status header | ||||||
passAction | string Only available when updating the pass.
| ||||||
Array of objects (location) <= 10 Array of locations, currently only available on Apple devices, due to Android device restrictions. Maximum of 10 locations | |||||||
Array of objects (beacon) <= 10 Array of beacons, currently only available on Apple devices, due to Android device restrictions. Maximum of 10 beacons | |||||||
groupTag | string Tag used for grouping passes |
Successful
Error: Bad Request
Error: Unauthorized
Error: Not Found
{- "pass": {
- "nfc": {
- "enabled": false
}, - "fullName": "Jane Roberts"
}, - "message": "Your pass details have been updated. Click to show pass",
- "locations": [
- {
- "name": "Venue",
- "latitude": 51.54321132456805,
- "longitude": -0.022901231803803924,
- "radius": 100,
- "message": "Welcome to the venue"
}
]
}
{- "data": {
- "id": "d2ac8d95-6914-4cac-957c-2a5ccf534390",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "createdAt": "2022-01-01T00:00:00Z",
- "status": "issued",
- "extId": "b1985e420025dd92ccf2",
- "passTemplateUuid": "2e2d7ee8c306e8f0223dbdc1",
- "passTemplateName": "PassEntry Ticketing",
- "nfc": null,
- "barcode": null,
- "latestMessage": "Your pass details have been updated. Click to show pass",
- "passContent": {
- "fullName": "Jane Roberts",
- "nfc": {
- "enabled": false
}
}, - "locations": [
- {
- "name": "Venue",
- "latitude": 51.54321132456805,
- "longitude": -0.022901231803803924,
- "radius": 100,
- "message": "Welcome to the venue",
- "address": "Blast Analytics, 22 Upper Ground, London, England, SE1 9PD, United Kingdom"
}
]
}
}, - "meta": {
- "notifications": {
- "status": "notDelivered",
- "message": "Pass has not been added to the wallet"
}
}
}
includePassDesign | boolean If true, includes the pass design in the response |
includePassSource | string Used when delivering the pass directly to the passholder, without using PassEntry's download page. Choose one of Apple/Google, includes the pass source in the response. The passSource object is only included if the pass is not currently 'active' |
Successful
Error: Unauthorized
Error: Not Found
{- "data": {
- "id": "d2ac8d95-6914-4cac-957c-2a5ccf534390",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "createdAt": "2022-01-01T00:00:00Z",
- "status": "issued",
- "extId": "b1985e420025dd92ccf2",
- "passTemplateUuid": "2e2d7ee8c306e8f0223dbdc1",
- "passTemplateName": "PassEntry Ticketing",
- "nfc": null,
- "barcode": null,
- "passContent": {
- "fullName": "John Johnson"
}
}
}
}
PassEntry provides a number of RESTful endpoints for interacting and manipulating passes created under the Loyalty vertical.
This includes but is not limited to: Loyalty Cards, Gift Cards, Coupons, Memberships…
Balance: This can represent loyalty points, stamps, credit, and more in an integer type. Balance can be accumulated or used. Balance is stored in our database and represented on the pass.
POS System: handles in store sales transactions, inventory management, and reporting
Loyalty Program: This is implemented externally to PassEntry, is where the loyalty behaviour is handled and loyalty/customer data is stored. Ideally, this would be closely integrated with the POS system, in order to allow for seamless tracking of purchases and points. As a best practice, any loyalty data relevant to a pass must always be mirrored in the loyalty program.
Payment Terminal: where payment is made, can also be used to read the loyalty pass and thus identify the customer
To allow interacting with your passes using the Loyalty API, the first step is to ensure that the parent template has loyalty balance enabled. Once this is done, you must choose how you want the balance to be represented on the pass, set at the pass template level. We currently offer support for integer and decimal types.
Example: PassEntry Coffee has a loyalty program. Every £10 spent, a customer receives 1 Point
When a customer has received 5 points they are able to get £5 off on their order total
Distributing a loyalty pass
A loyalty pass is created and distributed to a customer with an ext_id
equivalent to customer in the loyalty program
The loyalty pass balance on this loyalty pass is 0
. This is represented on the loyalty pass as Points 0
and is stored on the loyalty program.
When the customer makes a purchase in store and presents their device to make payment, the reader identifies their loyalty pass and sends both the loyalty pass ext_id
and the loyalty pass balance to the POS
Accumulating balance
The POS system takes payment, and updates the loyalty pass with a balance equal to a value determined by the loyalty program, alongside an optional push notification.
In this example, the customer has spent £20, so the the balance is increased by 2 points and the customer receives Thank you for your order. You've earned 2 points!
as a push notification.
Receiving a reward
The POS system takes £10 payment and customer balance is increased by 1 point.
As the threshold of 5 points has been reached, as determined by the loyalty program, the customer is sent a push notification Congratulations! You've got £5 off on your next order!
The pass design can be updated via the /passes/
endpoint so that the £5 off
reward appears on the loyalty pass design to inform the customer of their reward
Redeeming a reward
The POS system is ready to receive payment of £8
The customer presents their device, and their loyalty pass ext_id
and balance are sent to the POS system, identifying the customer to the loyalty program
The loyalty program detects that the customer has 5 points and is thus entitled to a £5 off discount
The POS system prompts the user to redeem their £5 off!
reward via a Would you like get £5 off on this order?
prompt (Optional: rewards can be applied automatically as determined by the loyalty program)
The transaction amount on the payment terminal is updated to £3
The customer makes payment
The reward is removed from the loyalty pass alongside a You've used your £5 off discount!
push notification
Resetting the balance (Optional)
successful
Error: Unauthorized
Error: Not Found
Error: Precondition Failed
{- "data": {
- "id": "2258d9ed-05bc-47cd-be65-83b9bb5e0273",
- "type": "pass",
- "attributes": {
- "passType": "storeCard",
- "deviceType": "android",
- "createdAt": "2022-01-01T00:00:00Z",
- "status": "active",
- "extId": "4e9ab9e571bbc8ff64e7",
- "passTemplateUuid": "b7f3372d08eddd76f28926ff",
- "passTemplateName": "PassEntry Store",
- "nfc": "941c35348d16187199a6b41047f0b7862b2dcb67",
- "barcode": null,
- "passContent": {
- "description": "Template Description",
- "centralTitle": "Template Central Title",
- "fullName": "Robert Smith",
- "labelOne": "1",
- "labelTwo": "11",
- "points": "7",
- "terms": "Your use of the Google Wallet is subject to Google's terms and conditions of use, which PassEntry are not responsible for."
}
}
}, - "meta": {
- "loyalty": {
- "balance": 7
}
}
}
balance | integer If integer is positive, balance is added. If negative, balance is subtracted. Cannot be used with overrideBalance key |
overrideBalance | integer Override the balance and set it to this value. Cannot be used with balance key |
message | string Push Notification message to display. Only used if pass is active. Use alongside balance or overrideBalance keys |
successful
{- "balance": 10
}
{- "data": {
- "id": "2258d9ed-05bc-47cd-be65-83b9bb5e0273",
- "type": "pass",
- "attributes": {
- "passType": "storeCard",
- "deviceType": "android",
- "createdAt": "2022-01-01T00:00:00Z",
- "status": "active",
- "extId": "4e9ab9e571bbc8ff64e7",
- "passTemplateUuid": "b7f3372d08eddd76f28926ff",
- "passTemplateName": "PassEntry Store",
- "nfc": "941c35348d16187199a6b41047f0b7862b2dcb67",
- "barcode": null,
- "passContent": {
- "description": "Template Description",
- "centralTitle": "Template Central Title",
- "fullName": "Robert Smith",
- "labelTwo": "11",
- "points": "17",
- "terms": "Your use of the Google Wallet is subject to Google's terms and conditions of use, which PassEntry are not responsible for."
}
}
}, - "meta": {
- "loyalty": {
- "balance": 17
}
}
}
When building integrations with PassEntry, you might want your application to receive events as they occur, so that your backend systems can execute actions accordingly.
To enable webhooks, you must first register a valid HTTPS URL, and subscribe to the events you want to be notified by. To do this, please visit the Webhook section on the PassEntry dashboard.
We implement a number of security measures to guarantee any interactions between PassEntry and your system are verified and authentic.
Secret Key: When configuring your webhook endpoint, you will be provided a secret key, which PassEntry will use to sign any outbound webhooks. You must store this securely. If you believe your secret key has been compromised, you have the option to rotate your secret key. This will immediately invalidate the previous secret key and sign all subsequent webhooks with the new key
Timestamp: Each webhook payload includes a timestamp, serving as a safeguard against replay attacks.
HMAC-SHA256 Signature: Every outgoing webhook includes an HMAC signature.
The signature is included in the X-Webhook-Signature
header and is generated using the webhook payload and the shared secret key.
To verify that the webhook is authentic, you can encrypt the webhook payload using the SHA-256 encryption algorithm and your secret key.
If your generated signature matches the signature included in the X-Webhook-Signature
header, you can confirm that the webhook is authentic.
Asynchronous Delivery: Webhooks include a timestamp to reflect the actual event time.
Retry Mechanism: Failures in delivery due to network issues, SSL problems, or non-2xx HTTP responses will trigger retries. PassEntry retries delivery up to 10 times over 3 days, using exponential backoff.
Success Responses: Please ensure your endpoint returns a status code within the 200-299 range. Any code outside this range is considered an error, prompting retries.
Response Body: While optional, you may return a response body.
HTTP Status: 200
Content-Type: application/json
{
"status": "ok"
}
Webhook triggered when a pass is added to the wallet by user
object | |
Array of serializedPassObject (object) or serializedPassTapObject (object) or serializedReaderObject (object) |
Return a 200 status to indicate that the data was received successfully
{- "data": {
- "id": "018d8e07-beaa-7634-80a8-647cd33d6bb3",
- "type": "webhook",
- "attributes": {
- "timeStamp": "2022-01-01T00:00:00Z",
- "webhookType": "passInstalled"
}, - "relationships": {
- "pass": {
- "data": {
- "id": "313c3c3b950d30d7ecec486ddf9adf33b887ae29",
- "type": "pass"
}
}
}
}, - "included": [
- {
- "id": "e89b1330fc391ec89656f3c664318cff8805471e",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "deviceType": "android",
- "createdAt": "2022-01-01T00:00:00Z",
- "status": "active",
- "extId": "0811d028ddf0da42c28f",
- "addedAt": "2022-02-01T00:00:00Z",
- "removedAt": null,
- "deactivatedAt": null,
- "passTemplateUuid": "c1f632d3e693a75c376b440b",
- "passTemplateName": "Pass Template 1 3079",
- "nfc": "e89b1330fc391ec89656f3c664318cff8805471e",
- "passContent": {
- "fullName": "Jane Smith"
}, - "barcode": {
- "type": "qrCode",
- "value": "123abcd",
- "displayText": true
}
}
}
]
}
{- "status": "ok"
}
Webhook triggered when a pass is removed from the wallet by user
object | |
Array of serializedPassObject (object) or serializedPassTapObject (object) or serializedReaderObject (object) |
Return a 200 status to indicate that the data was received successfully
{- "data": {
- "id": "018d8e07-beaa-7634-80a8-647cd33d6bb3",
- "type": "webhook",
- "attributes": {
- "timeStamp": "2022-01-01T00:00:00Z",
- "webhookType": "passRemoved"
}, - "relationships": {
- "pass": {
- "data": {
- "id": "313c3c3b950d30d7ecec486ddf9adf33b887ae29",
- "type": "pass"
}
}
}
}, - "included": [
- {
- "id": "e89b1330fc391ec89656f3c664318cff8805471e",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "deviceType": "android",
- "createdAt": "2022-01-01T00:00:00Z",
- "status": "removed",
- "extId": "0811d028ddf0da42c28f",
- "addedAt": "2022-02-01T00:00:00Z",
- "removedAt": "2023-02-01T00:00:00Z",
- "deactivatedAt": null,
- "passTemplateUuid": "c1f632d3e693a75c376b440b",
- "passTemplateName": "Pass Template 1 3079",
- "nfc": "e89b1330fc391ec89656f3c664318cff8805471e",
- "passContent": {
- "fullName": "Jane Smith"
}, - "barcode": {
- "type": "qrCode",
- "value": "123abcd",
- "displayText": true
}
}
}
]
}
{- "status": "ok"
}
Webhook triggered when an NFC pass is tapped on a reader
object | |
Array of serializedPassObject (object) or serializedPassTapObject (object) or serializedReaderObject (object) |
Return a 200 status to indicate that the data was received successfully
{- "data": {
- "id": "018d8e07-beaa-7634-80a8-647cd33d6bb3",
- "type": "webhook",
- "attributes": {
- "timeStamp": "2022-01-01T00:00:00Z",
- "webhookType": "passTapped"
}, - "relationships": {
- "passTap": {
- "data": {
- "id": "857e764e-ec8d-4348-abfb-25f379983eaf",
- "type": "passTap"
}
}, - "pass": {
- "data": {
- "id": "313c3c3b950d30d7ecec486ddf9adf33b887ae29",
- "type": "pass"
}
}, - "reader": {
- "data": {
- "id": "CC202952",
- "type": "reader"
}
}
}
}, - "included": [
- {
- "id": "857e764e-ec8d-4348-abfb-25f379983eaf",
- "type": "passTap",
- "attributes": {
- "tappedAt": "2022-01-01T00:00:00Z",
- "successful": true
}
}, - {
- "id": "e89b1330fc391ec89656f3c664318cff8805471e",
- "type": "pass",
- "attributes": {
- "passType": "generic",
- "deviceType": "android",
- "createdAt": "2022-01-01T00:00:00Z",
- "status": "removed",
- "extId": "0811d028ddf0da42c28f",
- "addedAt": "2022-02-01T00:00:00Z",
- "removedAt": "2023-02-01T00:00:00Z",
- "deactivatedAt": null,
- "passTemplateUuid": "c1f632d3e693a75c376b440b",
- "passTemplateName": "Pass Template 1 3079",
- "nfc": "e89b1330fc391ec89656f3c664318cff8805471e",
- "passContent": {
- "fullName": "Jane Smith"
}, - "barcode": {
- "type": "qrCode",
- "value": "123abcd",
- "displayText": true
}
}
}, - {
- "id": "CC202952",
- "type": "reader",
- "attributes": {
- "name": "West Gate"
}
}
]
}
{- "status": "ok"
}
Readers can be used for a variety of use cases, to validate access, redeem loyalty, claim discounts, identify the user and much more.
NFC
PassEntry's passes are NFC enabled, which allow you to set an NFC 'value' behind every pass. This value defaults to the UUID of the pass, or can be set to a custom value. This NFC value is encrypted, and can only be generated by PassEntry. In order for the NFC value to be read, an NFC reader must be configured. To do this, two things are required, a pass identifier, which tells the reader which passes to request the device for when "tapped", and a private key, which allows the reader to decrypt the NFC value.
Our system supports two types of Readers: VTAP Readers and PassEntry Reader App. Both types can be configured through the Passentry Dashboard or via API requests.
Below, we provide an overview of each reader type, the configuration process, and additional setup information.
VTAP Readers come in a range of form factors, from boxed, countertop devices to embedded hardware that can be integrated in existing platforms. The NFC value can be transmitted over the internet, or over wire through USB, RS-232, RS-485, Wiegand and more.
Setting up a VTAP Reader consists of two parts:
VtapReader
PassEntry Reader is a software application available for download from the Google Play Store, MAXSTORE, and Sunmi App Store. This reader offers additional functionality and settings for scanning NFC passes, QR codes/barcodes, Mifare Classic NFC cards, and more. It can perform specific actions such as scanning taps, redeeming/adding points, and adding stamps. For more information, please contact PassEntry.
{- "data": {
- "id": "south-gate-1",
- "type": "reader",
- "attributes": {
- "name": "South Gate Reader",
- "readerType": "PassentryReader",
- "loggedIn": false,
- "qrEnabled": false,
- "mifareClassicNfcEnabled": false,
- "scanEnabled": true,
- "redeemEnabled": false,
- "addPointsEnabled": false,
- "lastSeenAt": "2020-03-13T13:00:00Z"
}
}
}
successful
Error: Unauthorized
Error: Unprocessable Entity
{- "reader": {
- "id": "south-gate-3",
- "password": "Test789!",
- "mifareClassicNfcEnabled": true,
- "scanEnabled": false,
- "redeemEnabled": true,
- "qrEnabled": true
}
}
{- "data": {
- "id": "south-gate-3",
- "type": "reader",
- "attributes": {
- "name": "South Gate Reader",
- "readerType": "PassentryReader",
- "loggedIn": false,
- "qrEnabled": true,
- "mifareClassicNfcEnabled": true,
- "scanEnabled": false,
- "redeemEnabled": true,
- "addPointsEnabled": false,
- "lastSeenAt": "2020-03-13T13:00:00Z"
}
}
}
Created
Error: Unauthorized
Error: Unprocessable Entity
{- "reader": {
- "name": "South Entrance Reader 1",
- "id": "south_entrance_01",
- "type": "VtapReader",
- "password": "string",
- "scanEnabled": true,
- "redeemEnabled": false,
- "addPointsEnabled": false,
- "mifareClassicNfcEnabled": false,
- "qrEnabled": false
}
}
{- "data": {
- "id": "east-gate-1",
- "type": "reader",
- "attributes": {
- "name": "East Gate Reader",
- "readerType": "PassentryReader",
- "loggedIn": false,
- "qrEnabled": true,
- "mifareClassicNfcEnabled": false,
- "scanEnabled": true,
- "redeemEnabled": false,
- "addPointsEnabled": false
}
}
}
Successful
Error: Unauthorized
Error: Not Found
{- "data": {
- "id": "defd0867",
- "type": "readerConfiguration",
- "attributes": {
- "nfcPrivateKey": "-----BEGIN EC PRIVATE KEY-----\n PRIVATE KEY\n -----END EC PRIVATE KEY-----",
- "googleCollectorId": "95415519",
- "applePassTypeId": "pass.com.test.test",
- "googleKeyVersion": 1,
- "readerConfigurationApiKey": "uwMGo/K/8SNxEznuFDZhe/lZLdk0ruGgikh1fGOGXh8KV1cdGU7vDzl8Dit0MEBhuF7sRhec2aCU9b1t3WiZDg=="
}
}
}
This document outlines the implementation of geofencing and iBeacon technology to enhance customer engagement through targeted notifications based on location proximity.
Currently, only Apple Wallet passes support this feature due to Google Wallet constraints.
Note: When setting 2 or more geofences in close proximity, there may be a delay in the notification appearing when moving between geofences. The device implements a cooldown period to ensure that the user has left the previous geofence before entering the next one.
iBeacons are a technology standard developed by Apple that allows mobile apps to listen for signals from beacons in the physical world and react accordingly.
The technology is based on Bluetooth Low Energy (BLE) proximity sensing, which enables a device to perform actions when in close proximity to a beacon.
PassEntry is not able to track the exact location of the user, we do not have access to the user's location data, as this never leaves the device.
Learn more about beacons here: iBeacon
If you have a large number of location you would like to enable geofence capabilities for, here's an example:
Use Case: PassEntry Coffee Chain
Configuration Example
In this example: PassEntry Coffee would configure their 200 beacons like so:
London (50 locations):
Bakery Section beacons:
uuid: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
major: 1
minor: 1
name: 'london-bakery'
Cafe Section beacons:
uuid: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
major: 1
minor: 2
name: 'london-cafe'
Dubai (30 locations):
Bakery Section beacons:
uuid: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
major: 2
minor: 1
name: 'dubai-bakery'
Cafe Section beacons:
uuid: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
major: 2
minor: 2
name: 'dubai-cafe'
Singapore (20 locations):
Bakery Section beacons:
uuid: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
major: 3
minor: 1
name: 'singapore-section'
Cafe Section beacons:
uuid: E2C56DB5-DFFB-48D2-B060-D0F5A71096E0
major: 3
minor: 2
name: 'singapore-cafe'
When building the pass via the PassEntry API, the following JSON structure would be used to define the beacons:
{
"beacons": [
{
"proximity_uuid": "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0",
"major": 1,
"minor": 1,
"message": "£10 off on cakes!",
"name": "london-bakery"
}, {
"proximity_uuid": "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0",
"major": 1,
"minor": 2,
"message": "Buy one get one free juice",
"name": "london-cafe"
}, {
"proximity_uuid": "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0",
"major": 2,
"minor": 1,
"message": "AED 20 off on cakes!",
"name": "dubai-bakery"
}, {
"proximity_uuid": "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0",
"major": 2,
"minor": 2,
"message": "Try our pumpkin spice lattes!",
"name": "dubai-cafe"
}, {
"proximity_uuid": "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0",
"major": 3,
"minor": 1,
"message": "$5 off on kuih lapis!",
"name": "singapore-bakery"
}, {
"proximity_uuid": "E2C56DB5-DFFB-48D2-B060-D0F5A71096E0",
"major": 3,
"minor": 2,
"message": "Buy one get one free teh tarik!",
"name": "singapore-cafe"
}
]
}