Overview
Kemicard is a managed package that enables Salesforce organizations to generate Apple Wallet and Google Wallet passes directly from Salesforce records. The package integrates natively with Salesforce objects through custom metadata configuration.
1. Adding Items to Wallet (Pass Generation & Delivery)
How Kemicard Creates Passes
Kemicard generates wallet passes from Salesforce records using:
- Custom Metadata Configuration that maps a Salesforce object (e.g., Contact, custom object) to pass generation rules
- Pass Templates that define the visual design and field mappings for Apple and Google passes
- Automated or manual triggers (Flows, Apex, or manual actions) to create pass records
Configuration Setup (Admin)
Step 1: Create a Configuration Record
Navigate to: Kemicard Console → Configuration
Refer this document – Create Kemicard Configuration
Step 2: Create a Pass Template
Navigate to: Kemicard Template Builder
Refer to this document – Create New Template
End-User Steps: Adding a Pass to Wallet
From Email (Most Common):
- Salesforce creates a Contact record with required membership fields populated
- A Flow or automation generates the Kemicard pass and sends an email
- The user receives an email with “Add to Apple Wallet” and “Save to Google Wallet” buttons
- User taps the appropriate button for their device
- The pass preview opens showing:
- Card design (logo, colors, member name)
- Membership details (tier, expiry date)
- Scannable barcode/QR code
- User taps Add and the pass appears in their Wallet app
From a Salesforce Record (Portal or Community):
- User logs into a Salesforce Experience Cloud site
- User navigates to their membership or profile page
- A Kemicard Lightning component displays an “Add to Wallet” button
- User clicks the button and selects Apple or Google Wallet
- Pass is generated on-the-fly and added to their device
2. Removing and Revoking Passes
User-Initiated Removal
On Apple Wallet:
- Open Wallet app on iPhone
- Tap the Kemicard pass (e.g., “Woofy Membership”)
- Tap the **- – – ** (More) button in the top-right
- Tap Remove Pass
- Confirm deletion
On Google Wallet:
- Open Google Wallet app on Android
- Tap the Kemicard pass
- Tap the three-dot menu in the top-right
- Tap Remove pass
- Confirm deletion
Admin-Initiated Revocation (Salesforce)
Kemicard allows admins to revoke passes when a membership ends, account is closed, or pass is no longer valid.
Method 1: Change Status/Expiry on the Source Record
- Open the Contact (or source object) record in Salesforce
- Update fields that control pass validity:
- Set Membership_Status__c to “Expired” or “Cancelled”
- Change Membership_Expiration_Date__c to a past date
- Save the record
- Kemicard automatically pushes an update to the pass, marking it invalid or expired
- The pass on the user’s device shows as expired (visual indicators like grayed-out appearance or “Expired” label)
Method 2: Delete the Pass Record
- Navigate to Kemicard Passes
- Find the pass record linked to the Contact
- Delete the pass record
- The pass on the user’s device is invalidated (barcode no longer scans)
Example Scenario:
A member cancels their subscription. Admin updates the Contact record to set Status = “Lapsed” and set the expiry date. The Kemicard pass on their phone updates to show “Expired” status, and the barcode is deactivated at the scanner level via the configured Scanner Flow (Kemicard_Expired_Member_Scan_Processor).
3. Using Wallet in Daily Workflows
Check-In and Verification at Physical Locations
Scanning a Pass:
- Member arrives at a location (gym, event, store)
- Member opens their Wallet app and selects the Kemicard pass
- Staff scans the QR code or barcode using:
- Kemicard Scanner app (navigate to: Kemicard Scanner tab)
- A generic barcode scanner integrated with Salesforce
- A custom Flow or Apex class triggered by the scan
- The scanner reads the QR code (which contains the Contact Id)
- The configured Scanner Flow API Name (Kemicard_Expired_Member_Scan_Processor) executes:
- Validates the pass is active
- Checks expiry date
- Updates Salesforce records (e.g., logs attendance, increments visit count)
- Returns success or error to the scanner
Example Workflow: Gym Check-In
- Member scans Woofy Membership Pass at gym entrance
- Scanner reads Contact Id from barcode
- Flow checks if Membership_Expiration_Date__c > Today
- If valid: logs attendance on Contact, updates Last_Visit__c field, grants entry
- If expired: displays error message, denies entry
Automated Pass Issuance and Updates
Trigger-Based Issuance:
Use Salesforce Flow to automatically issue passes when certain conditions are met:
- Flow Trigger: Contact is created or updated
- Criteria: Membership_Status__c = “Active” AND Membership_Pass__c is blank
- Action: Create Kemicard Pass record
- Action: Send email with pass attachment (via configured Email Template)
Real-Time Updates:
When you update a Contact field mapped to the pass (e.g., tier, points, expiry), Kemicard pushes the change to the user’s device:
- Update Contact record: Change Membership_Tier__c from “Silver” to “Gold”
- Kemicard detects change and regenerates the pass
- User’s Wallet updates automatically (header changes from “Silver Member” to “Gold Member”)
No re-download or manual action required by the user.
Bulk Actions
Navigate to: Kemicard Console → Bulk Actions
Generate Passes in Bulk:
- Create a Salesforce Report of Contacts who need passes
- Click Generate Passes in Bulk Actions
- Upload or reference the report
- Kemicard creates pass records and sends emails for all contacts in the report
- Uses the Flow configured in Bulk Actions Flow API Name (Send_Membership_Pass)
Send Messages in Bulk:
- Select a group of pass holders
- Click Send Messages
- Compose a push notification or email message
- Kemicard delivers the message to all selected pass holders
4. Kemicard Digital Wallet — Permission Sets Guide
Overview of Kemicard Permission Sets
Kemicard provides 8 pre-configured permission sets that control access to different features of the managed package. These permission sets follow a role-based access control model, allowing admins to grant granular permissions based on user responsibilities
Kemicard Permission Sets Reference
- Kemicard Digital Pass
API Name: Kemicard_Digital_Pass
Purpose: Full access permission set for Kemicard functionality
License: (None specified)
Description: Foundation permission set for accessing core Kemicard objects and features
Typical Users:
- Admins who manage the full Kemicard implementation
- Integration users who need API access to Kemicard objects
Key Permissions:
- Access to Kemicard custom objects (Pass, Template Pass, Configuration)
- Read/Write access to Kemicard records
- System-level permissions for Kemicard operations
- Kemicard Digital Pass User ⭐ Most Common
API Name: Kemicard_Digital_Pass_User
Purpose: Enables end-user pass operations
License: (None specified)
Description: Permissions to access Kemicard Apple and Google wallet pass operations like pass send, upgrade, push notification, etc.
Typical Users:
- Customer service representatives who issue passes to members
- Marketing users who send bulk pass updates
- Community/portal users who generate their own passes
Key Permissions:
- Object Access: Read, Create, Edit on Kcard__Pass__c (Kemicard Pass object)
- Pass Operations:
- Generate new passes from records
- Send passes via email
- Update existing passes
- Push notifications to pass holders
- Upgrade pass templates
- Field-Level Security: Access to pass status, barcode, email fields
- Apex Class Access: Execute pass generation and delivery classes
- Visualforce Page Access: Access pass preview and management pages
Usage Example:
A gym front-desk staff member needs to issue a new membership pass to a walk-in customer. They have Kemicard_Digital_Pass_User assigned, which lets them create a Contact record, generate a pass, and email it to the customer—all without admin privileges.
- Kemicard Event Admin
API Name: Kemicard_Event_Admin
Purpose: Manage event-related passes and check-ins
License: (None specified)
Description: Permissions for users who manage event ticketing and attendance tracking
Typical Users:
- Event coordinators who issue event tickets
- Venue managers who track event check-ins
- Conference organizers managing attendee passes
Key Permissions:
- Object Access: Full CRUD on Kcard__Event__c and Kcard__Event_Assignment__c
Usage Example:
A conference organizer creates a “FutureMind Conference” event template , assigns it to registered Contact.,
- Kemicard Integration
API Name: Kemicard_Integration
Purpose: API and external system integration
License: (None specified)
Description: Permissions to allow Kemicard Authentication. Add Kemicard_Integration_Unpackaged Permission Set for full access.
Typical Users:
- Integration service accounts (API users)
Key Permissions:
- The integration user’s purpose is to allow the Kemicard backend service to update Salesforce records
Usage Example:
A Salesforce user initiates pass generation. Once the pass is generated from the Kemicard backend service, it connects to Salesforce as the integration user to update the Pass_c record.
Note: For full integration capabilities, also assign the unpackaged permission set Kemicard_Integration_Unpackaged (custom permission set created in your org).
- Kemicard Pass Bulk Actions
API Name: Kemicard_Pass_Bulk_Actions
Purpose: Execute bulk operations on passes
License: (None specified)
Description: Permissions to access Bulk Actions on Kemicard passes. Add Kemicard_Digital_Pass_User and Kemicard_Metadata_API_Unpackaged Permission Sets for full feature access.
Typical Users:
- Marketing managers running bulk campaigns
- Operations teams issuing passes to large member lists
- Admins performing mass pass updates or revocations
Key Permissions:
- Bulk Actions Tab Access: Access to Kemicard Console → Bulk Actions
- Flow Access: Execute Send_Membership_Pass and other bulk flows
- Report Access: Read Salesforce reports to use as bulk action sources
- Email Sending: Send bulk emails with pass attachments
Key Features:
- Generate Passes: Create passes for multiple records at once from a report
- Send Messages: Push notifications or emails to groups of pass holders
Usage Example:
A nonprofit renews 500 annual memberships and needs to reissue passes with new expiry dates. The membership manager runs a report of renewed members, navigates to Bulk Actions, clicks Generate Passes, and selects the report. Kemicard creates and emails 500 updated passes in minutes.
Dependencies: Requires Kemicard_Digital_Pass_User for base pass operations.
- Kemicard Scanner
API Name: Kemicard_Scanner
Purpose: Use Kemicard Scanner app for barcode validation
License: (None specified)
Description: Permissions to access and use the Kemicard Scanner application
Typical Users:
- Front-desk staff at gyms, events, retail locations
- Security personnel at venue entrances
- Check-in coordinators at conferences or membership facilities
Key Permissions:
- Scanner App Access: Access to Kemicard Scanner tab
- Flow Execution: Trigger scanner flows (e.g., Kemicard_Expired_Member_Scan_Processor)
- Object Read Access: Read Pass and related object records to validate scans
- Field Access: View member status, expiry dates, attendance logs
Scanner Workflow:
- User opens Kemicard Scanner app on tablet or mobile device
- Scans QR code on member’s pass (reads Contact Id from barcode)
- Scanner Flow executes:
- Validates pass is active and not expired
- Checks Membership_Expiration_Date__c > Today
- Logs attendance on Contact record
- Updates Last_Visit__c field
- Scanner displays ✅ Valid or ❌ Expired/Invalid
Usage Example:
At a gym entrance, a receptionist with Kemicard_Scanner permission scans a member’s Woofly Membership Pass . The scanner checks if the pass is valid, logs the visit, and grants entry.
- Kemicard Template Configuration
API Name: Kemicard_Template_Configuration
Purpose: Create and manage pass templates and configurations
License: (None specified)
Description: Permissions to access Kemicard Configuration and Template Builder. Add Kemicard_Metadata_API_Unpackaged Permission Sets for full feature access.
Typical Users:
- Kemicard administrators who set up new pass types
- Designers who configure pass visual appearance
- System architects who map objects to pass templates
Key Permissions:
- Configuration Access: Create/Edit records in Kemicard Configuration V2i
- Template Builder Access: Access Kemicard Template Builder tab
- Template Management: Full CRUD on Kcard__Template_Pass__c
- Custom Metadata Access: Edit Kemicard Configuration V2 custom metadata
- Object Mapping: Configure object-to-pass field mappings
Key Features:
- Create new Kemicard Configuration records (map objects like Contact, Account, custom objects to passes)
- Design pass templates using Template Builder (set colors, logos, text fields for Apple/Google Wallet)
- Configure email templates for pass delivery
- Set up scanner flows and bulk action flows
Usage Example:
An admin wants to create a new “VIP Event Pass” for a custom Event_Registration__c object. They:
- Navigate to Kemicard Console → Configuration
- Click Add New Configuration
- Use Kemicard Template Builder to design the pass appearance
- Activate the configuration
Dependencies: For full functionality, also assign Kemicard_Metadata_API_Unpackaged (custom permission set in your org).
- Kemicard User
API Name: Kemicard_User
Purpose: This is a supplemental permission set that grants access to the object from which the pass is generated. In this case, it applies to the Contact object and its associated custom fields. This permission set is not required if the Contact object or custom fields are not used in your implementation; however, a similar permission set should be created to grant access to whatever object and fields are used for Kemicard pass generation.
License: (None specified – Can be deleted/modified)
Description: Minimal permissions for access to Contact and fields used in sample implementation.
Typical Users:
- Supplemental to Kemicard Digital Pass and Kemicard Digital Pass User
Key Permissions:
- Object Read/Write Access: Access to Contact object and Membership_Template__c and Membership_Pass__c fields.
Permission Set Assignment Best Practices
Role-Based Assignment Matrix
| User Role | Recommended Permission Sets | Rationale |
|---|---|---|
| Kemicard Administrator | – Kemicard Digital Pass | Full control over configuration, templates, and operations |
| Front-Line Staff (Customer service, front desk) | – Kemicard Digital Pass User | Issue and manage passes for individual customers |
| Event Coordinator | – Kemicard Event Admin- Kemicard Scanner | Manage events and check in attendees |
| Scanner Operator (Security, check-in) | – Kemicard Scanner | Validate passes at entry points only |
| Marketing Manager | – Kemicard Digital Pass User- Kemicard Pass Bulk Actions | Send bulk pass campaigns and updates |
| Integration Service Account | – Kemicard Integration | API access |
5. Flow Documentation: Send Membership Pass
Overview
Flow Name: Send Membership Pass
API Name: Send_Membership_Pass
Flow Type: Autolaunched Flow
Status: Active
Version: V1
Purpose:
This flow automates the generation and delivery of Kemicard membership passes for Contact records. It retrieves Contact information, prepares pass data (location, barcode, email), determines the appropriate template and configuration, then calls a Kemicard Apex action to create and email the pass to the member.
Use Case:
Used as the Bulk Actions Flow in the Kemicard Configuration for Contact objects . When admins run Bulk Actions from the Kemicard Console, this flow processes multiple Contacts and issues membership passes at scale.
Trigger:
- Called from Kemicard Console → Bulk Actions → Generate Passes
- Can be invoked from Process Builder or another Flow
- Can be called via Apex or API for custom integrations
Flow Architecture
The flow follows a sequential process with conditional logic:
text
START
↓
Get Contact (Retrieve Contact record by RecordId)
↓
Set Location (Assign location variable)
↓
Set Barcode Value (Assign Contact ID as barcode value)
↓
Set Email Address (Assign Contact Email)
↓
CheckIfConfigEmpty (Decision: Does Contact have a configuration?)
├─ ConfigEmpty: Retrieve default template
│ ↓
│ GetTemplate (Get Records: Template Pass)
│ ↓
│ AssignConfiguration (Assign default config to variable)
│ ↓
└─ Has Config: Skip template lookup
↓
Set Pass Details (Assign pass metadata: barcode, email, location, config)
↓
Create and Email Membership Pass (Apex Action: Kemicard API)
↓
END
Flow Elements Breakdown
1. Start (Autolaunched Flow)
- Type: Start element
- Trigger: No trigger (autolaunched/invoked by Kemicard Bulk Actions or API)
- Input Variables:
- RecordId (Text) – ID of the Contact record to process
- Other optional inputs (configuration ID, template ID if overriding defaults)
2. Get Contact (Get Records)
- Label: Get Contact
- API Name: Get_Contact
- Element Type: Get Records
- Object: Contact
Configuration:
- Filter: Contact ID Equals {!RecordId}
- Store: Only the first record
- Fields: Automatically store all fields
- Output Variable: Get_Contact (single Contact record)
Purpose:
Retrieves the full Contact record using the RecordId passed into the flow. This provides access to all Contact fields needed for pass generation (Name, Email, Membership fields, etc.).
Error Handling:
If no Contact is found, the flow will fail gracefully (subsequent elements cannot proceed without data).
3. Set Location (Assignment)
- Label: Set Location
- API Name: Set_Location
- Element Type: Assignment
Configuration:
- Variable: varLocation (Text variable)
- Value: {!Get_Contact.MailingCity} or similar location field from Contact
Purpose:
Assigns the Contact’s location (city, state, or full address) to a flow variable. This can be displayed on the pass or used for pass grouping/filtering.
4. CheckIfConfigEmpty (Decision)
- Label: CheckIfConfigEmpty
- API Name: CheckIfConfigEmpty
- Element Type: Decision
Configuration:
- Outcome 1: ConfigEmpty
- Condition: Membership_Pass_Template__c IS NULL on Contact
- Next Element: GetTemplate (retrieve default template)
- Outcome 2: Has Config
- Condition: Membership_Pass_Template__c IS NOT NULL
- Next Element: Set Pass Details (skip template lookup)
Purpose:
Determines whether the Contact record has a template explicitly assigned via the Membership_Pass_Template__c field . If not, the flow retrieves a default template from the Template Pass object.
Business Logic:
- If Contact has a template field populated: Use that specific template (e.g., “Woofy Membership Pass” for this Contact)
- If Contact template field is empty: Use the default template for all Contacts (first template marked as default in configuration)
5. GetTemplate (Get Records) – ConfigEmpty Path
- Label: GetTemplate
- API Name: GetTemplate
- Element Type: Get Records
- Object: Kcard__Template_Pass__c (Kemicard Template)
Configuration:
- Filter: Object__c Equals “Contact” AND IsDefault__c Equals TRUE (or retrieves first active template)
- Store: Only the first record
- Output Variable: GetTemplate (single Template Pass record)
Purpose:
Retrieves the default membership pass template when the Contact doesn’t have a template explicitly assigned. This ensures all Contacts can receive a pass even if the template field is not populated.
Example:
If the “Woofy Membership Pass” template is marked as the default for Contact object, this element retrieves it.
6. AssignConfiguration (Assignment) – ConfigEmpty Path
- Label: AssignConfiguration
- API Name: AssignConfiguration
- Element Type: Assignment
Configuration:
- Variable: varTemplateId (Text variable)
- Value: {!GetTemplate.Id} (ID of the retrieved default template)
Purpose:
Assigns the default template ID to a variable so it can be passed to the Apex action. This standardizes the pass template across all Contacts when no specific template is assigned.
7. Create and Email Membership Pass (Apex Action)
- Label: Create and Email Membership Pass
- API Name: Create_and_Email_Membership_Pass
- Element Type: Apex Action (Invocable Method)
- Apex Class: Kcard.PassGenerationController (Managed package Apex class from Kemicard)
Configuration:
Input Parameters:
- contactId: {!varContactId}
- barcodeValue: {!varBarcodeValue}
- emailAddress: {!varEmailAddress}
- location: {!varLocation}
- templateId: {!varTemplateId}
- expiryDate: {!varExpiryDate}
- sendEmail: true (from Kemicard Configuration “Send Email” checkbox )
What the Apex Action Does:
- Creates a Kcard_Pass__c record:
- Links pass to the Contact via Kcard_Record__c lookup
- Stores barcode value, template reference, expiry date
- Generates Apple Wallet and Google Wallet pass files
- Stores pass URLs and metadata
- Sends Email:
- Uses the email template specified in the configuration (Woofly_Welcome_Email)
- Attaches “Add to Apple Wallet” and “Save to Google Wallet” buttons
- Sends to the Contact’s email address
- Updates Contact Record:
- Populates Membership_Pass__c field with the new pass record ID
- Updates pass status to “Active”
Output Variables:
- passId (Text) – ID of the created pass record
- success (Boolean) – Whether pass generation succeeded
- errorMessage (Text) – Error details if generation failed
Error Handling:
- If email is invalid, logs error and sets success = false
- If template is missing, throws exception
- If Kemicard API is unavailable, retries or logs failure
Flow Variables
| Variable Name | Data Type | Input/Output | Description |
| RecordId | Text | Input | Contact ID passed from Bulk Actions or API |
| varContactId | Text | Internal | Stores Contact ID for Apex action |
| varBarcodeValue | Text | Internal | Contact ID used as QR code value |
| varEmailAddress | Text | Internal | Contact Email for pass delivery |
| varLocation | Text | Internal | Contact location (city/state) |
| varTemplateId | Text | Internal | ID of template to use for pass generation |
| varExpiryDate | Date | Internal | Membership expiration date |
| passId | Text | Output | ID of created pass record |
| success | Boolean | Output | Pass generation success flag |
8. Update Contact (Update Records)
- Label: Update Contact
- API Name: Update_Contact
- Element Type: Update Records
- Object: Contact
Configuration:
- Record to Update: {!Get_Contact.Id} (the Contact retrieved at the start)
- Fields to Update:
- Membership_Pass__c = {!passId} (lookup to the newly created pass record)
Purpose:
Updates the source Contact record with a reference to the generated pass. This creates a bidirectional relationship:
- Pass record links to Contact via Kcard__Contact__c lookup
- Contact links to Pass via Membership_Pass__c lookup
Why This Matters:
- Enables quick lookups: “Show me this Contact’s pass”
- Prevents duplicate pass generation (can check if Membership_Pass__c is already populated)
- Tracks when pass was last issued
Error Handling:
- If Apex action fails and passId is null, this update may fail or store a null value
- Use fault connectors to catch update errors and log them
Error Handling and Debugging
Common Errors
1. “No Contact Found”
- Cause: Invalid RecordId passed to flow
- Resolution: Verify RecordId is a valid 18-character Contact ID
2. “Email Address is Required”
- Cause: Contact Email field is blank
- Resolution: Ensure all Contacts in bulk action have valid emails, or disable “Send Email” in configuration
3. “Template Not Found”
- Cause: No default template exists for Contact object
- Resolution: Create a default template in Kemicard Templates and mark it as default for Contact
4. “Apex Action Failed”
- Cause: Kemicard API error, invalid template configuration, or missing required fields
- Resolution: Check Debug Logs for Apex errors, verify template has all required fields (logo URL, colors, etc.)
Debugging Steps
- Enable Debug Logs:
- Setup → Debug Logs → New Debug Log
- Select User running
6. Security and Privacy Basics
How Kemicard Protects Data
Encryption:
- All pass data is transmitted via HTTPS/TLS encryption
- Wallet platforms (Apple, Google) encrypt passes at rest on the device using device-level encryption
Access Control:
- Only users with appropriate Salesforce profiles and permissions can:
- Create or edit Kemicard configurations
- Generate passes
- Revoke passes
- Access Kemicard Scanner
- Field-level security controls which Contact fields are visible on passes
Data Minimization:
- Only essential fields are mapped to passes (name, ID, expiry, tier)
- Sensitive data (SSN, payment info, full address) should never be mapped to pass fields
- Full Contact records remain in Salesforce; passes display only configured fields
- Data is only stored in Salesforce (no data is stored in Kemicard backend services)
Salesforce-Level Security
Custom Metadata Security:
- Kemicard Configuration V2 records are stored as Custom Metadata Types
- Managed package protects core fields; org can edit configuration values
- Namespace prefix: Kcard
Scanner Flow Security:
- The configured Scanner Flow (Kemicard_Expired_Member_Scan_Processor) runs with system permissions