### Start Polling for Install Status Source: https://walletwallet.dev/docs Initiates polling for installation status at a fast interval (3 seconds) or slow interval (15 seconds) based on whether the device is live. ```javascript startPolling() { if (!this._showGenerate) return; if (this.installPollHandle) return; const tick = async () => { await this.pollInstallStatus(); // Once live, stop. Otherwise re-arm at fast (3s) or slow (15s). if (this.mode === 'live') return; const slow = Date.now() > this.installPollFastUntil; this.installPollHandle = setTimeout(tick, slow ? 15000 : 3000); }; this.installPollHandle = setTimeout(tick, 3000); } ``` -------------------------------- ### PKPASS File Structure Example Source: https://walletwallet.dev/llms-full.txt An example of the directory structure within a PKPASS archive after unzipping. This illustrates the required and optional files. ```plaintext MyPass.pkpass/ ├── pass.json # All pass data, fields, colors, barcode, metadata ├── manifest.json # SHA-1 hash of every other file (integrity check) ├── signature # PKCS#7 detached signature over manifest.json ├── icon.png # Required. Shown in iOS notifications + search (29×29 pt) ├── icon@2x.png # Retina variant (58×58 px) ├── logo.png # Top-left of pass face (up to 160×50 pt) ├── logo@2x.png ├── strip.png # Optional. Wide banner behind primary fields (375×98–144 pt) ├── strip@2x.png ├── thumbnail.png # Optional. Small image, top-right of pass face (90×90 pt) ├── thumbnail@2x.png └── en.lproj/ # Optional. Localization folder └── pass.strings ``` -------------------------------- ### Calculate Install Count Source: https://walletwallet.dev/docs Calculates the total number of installs, including Apple devices and Google saves. ```javascript get installCount() { return this.devices.length + (this.googleInstalled === 'saved' ? 1 : 0); } ``` -------------------------------- ### Poll Install Status Source: https://walletwallet.dev/docs Fetches the installation status of devices. It updates the device list and installation mode based on the response. Stops polling if the device is live. ```javascript pollInstallStatus() { try { const r = await fetch(this.apiUrl + '/install-status/' + this.serial); if (!r.ok) { if (r.status === 404 || r.status === 403) { this.startOver(); return; } } const data = await r.json(); this.devices = data.devices || []; this.googleInstalled = data.googleInstalled || null; if (this.installCount > 0 && this.mode === 'pending-install') { this.mode = 'live'; this.stopPolling(); } } catch {} } ``` -------------------------------- ### Get Pass Install State Source: https://walletwallet.dev/llms-full.txt Retrieves the current installation state of a specific pass, reflecting events received from Google Wallet webhooks. ```APIDOC ## GET /api/passes/{serial} ### Description This endpoint retrieves the current installation state of a specific pass, which is updated based on events received from the `/webhooks/google-wallet` endpoint. ### Method GET ### Endpoint /api/passes/{serial} ### Parameters #### Path Parameters - **serial** (string) - Required - The unique serial number of the pass. ### Response #### Success Response (200) - **Install State** (object/string) - Information about whether the pass is saved or removed. (Specific fields not detailed in source). ``` -------------------------------- ### Create Access Pass with Go Source: https://walletwallet.dev/docs This Go example shows how to create an access pass. It marshals the request body to JSON and writes the decoded pass data to a file. ```go package main import ( "bytes" "encoding/base64" "encoding/json" "net/http" "os" ) func main() { body, _ := json.Marshal(map[string]interface{}{ "barcodeValue": "PASS-999", "barcodeFormat": "QR", "logoText": "Access Pass", }) req, _ := http.NewRequest("POST", "https://api.walletwallet.dev/api/passes", bytes.NewBuffer(body)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer ww_live_") resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() var data map[string]string json.NewDecoder(resp.Body).Decode(&data) // data["serialNumber"], data["googleSaveUrl"] pkpass, _ := base64.StdEncoding.DecodeString(data["applePass"]) os.WriteFile("access.pkpass", pkpass, 0644) } ``` -------------------------------- ### Create Membership Pass with Ruby Source: https://walletwallet.dev/docs This Ruby example demonstrates creating a membership pass. It makes an HTTP POST request and decodes the base64-encoded pass data. ```ruby require 'net/http' require 'json' require 'uri' require 'base64' uri = URI('https://api.walletwallet.dev/api/passes') http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri) request['Content-Type'] = 'application/json' request['Authorization'] = 'Bearer ww_live_' request.body = { barcodeValue: 'MEMBER-001', barcodeFormat: 'QR', logoText: 'Gym Membership', primaryFields: [{ label: 'MEMBER', value: 'Premium' }] }.to_json response = http.request(request) data = JSON.parse(response.body) # data['serialNumber'], data['googleSaveUrl'] File.binwrite('membership.pkpass', Base64.decode64(data['applePass'])) ``` -------------------------------- ### Install Pass Source: https://www.walletwallet.dev/llms.txt Initiates the process of adding a pass to Google Wallet. This endpoint returns a URL that, when opened on an Android device, will add the pass. ```APIDOC ## POST /api/passes ### Description Initiates the process of adding a pass to Google Wallet. This endpoint returns a URL that, when opened on an Android device, will add the pass. ### Method POST ### Endpoint /api/passes ### Request Body This endpoint does not explicitly define a request body in the source, but it is implied that pass data is sent to create the pass. ### Response #### Success Response (200) - **googleSaveUrl** (string) - A URL that can be used to save the pass to Google Wallet on an Android device. #### Response Example { "googleSaveUrl": "https://pay.google.com/gp/v/save/" } ``` -------------------------------- ### Create Loyalty Card (All Options) Source: https://walletwallet.dev/docs This cURL example demonstrates creating a loyalty card with all available options, including primary, secondary, and header fields, color presets, and expiration. Replace 'ww_live_' with your API key. ```cURL curl -X POST https://api.walletwallet.dev/api/passes \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ww_live_" \ -d '{ "barcodeValue": "LOYALTY-98765", "barcodeFormat": "QR", "logoText": "Bayroast Coffee", "description": "Loyalty card for Bayroast Coffee", "primaryFields": [{"label": "CARD", "value": "Coffee Rewards"}], "secondaryFields": [{"label": "TIER", "value": "Gold Status"}], "headerFields": [{"label": "BALANCE", "value": "$25.00"}], "colorPreset": "green", "expirationDays": 365 }' ``` -------------------------------- ### Stop Polling for Install Status Source: https://walletwallet.dev/docs Clears any pending timeouts for polling the installation status. ```javascript stopPolling() { if (this.installPollHandle) { clearTimeout(this.installPollHandle); this.installPollHandle = null; } } ``` -------------------------------- ### Refresh Installs Status Source: https://walletwallet.dev/docs Manually triggers a refresh of the pass installation status. Includes a minimum visible duration for the refresh action to provide user feedback. ```javascript async refreshInstalls() { if (this.refreshing) return; this.refreshing = true; const started = Date.now(); try { await this.pollInstallStatus(); } finally { const elapsed = Date.now() - started; if (elapsed < 500) await new Promise((r) => setTimeout(r, 500 - elapsed)); this.refreshing = false; } } ``` -------------------------------- ### Share a Pass Source: https://www.walletwallet.dev/llms.txt Every created pass has a hosted install page. The POST /api/passes endpoint returns its URL as shareUrl. This URL can be shared with users via email, SMS, or chat, and it automatically detects the visitor's device to provide the appropriate wallet installation option (Apple Wallet, Google Wallet, or QR code for desktop). ```APIDOC ## POST /api/passes ### Description Creates a new pass and returns a shareable URL for its hosted install page. ### Method POST ### Endpoint /api/passes ### Request Body - **title** (string) - Required - The title of the pass. - **primaryFields** (object) - Optional - Primary fields to display on the pass. - **logoText** (string) - Optional - Text to display as the logo. - **barcodeValue** (string) - Required - The value of the barcode. - **barcodeFormat** (string) - Required - The format of the barcode (e.g., QR, PDF417, Aztec, Code128). - **color** (string) - Optional - The color of the pass (available on Pro plan). - **expirationDays** (integer) - Optional - The number of days until the pass expires (1-3650). - **locations** (array) - Optional - Locations associated with the pass. - **latitude** (number) - Required - Latitude of the location (-90 to 90). - **longitude** (number) - Required - Longitude of the location. - **logoURL** (string) - Optional - URL for the pass logo (must use HTTPS). ### Response #### Success Response (200) - **shareUrl** (string) - The URL to the hosted install page for the pass. #### Response Example { "shareUrl": "https://api.walletwallet.dev/p/" } ``` -------------------------------- ### Minimal Pass Creation Request Source: https://www.walletwallet.dev/llms.txt This example demonstrates the minimum required fields to create a pass using a cURL request. It includes barcode data and logo text. ```bash curl -X POST https://api.walletwallet.dev/api/passes \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ww_live_" \ -d '{ "barcodeValue": "MEMBER-12345", "barcodeFormat": "QR", "logoText": "Membership Card" }' # Returns JSON: { "serialNumber": "...", "googleSaveUrl": "https://pay.google.com/gp/v/save/...", "applePass": "", "shareUrl": "https://api.walletwallet.dev/p/..." } ``` -------------------------------- ### API Usage Response Source: https://www.walletwallet.dev/llms.txt Example JSON response for the API usage endpoint, showing usage counts, limits, and reset dates. ```json { "count": 150, "limit": 1000, "remaining": 850, "resetDate": "2026-06-01", "plan": "free" } ``` -------------------------------- ### Get API Usage Statistics Source: https://www.walletwallet.dev/llms.txt Retrieve the current month's API usage statistics for your authenticated key. Ensure you replace `` with your actual API key. ```bash curl https://api.walletwallet.dev/api/auth/usage \ -H "Authorization: Bearer ww_live_" ``` -------------------------------- ### Update Pass Request Example Source: https://walletwallet.dev/llms-full.txt This cURL command demonstrates how to update an issued pass, specifically changing a points balance and setting a message that will appear on the lock screen. ```bash curl -X PUT https://api.walletwallet.dev/api/passes/8f4c3a2e-ùi \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ww_live_" \ -d '{ "barcodeValue": "LOYALTY-98765", "barcodeFormat": "QR", "logoText": "Bayroast Coffee", "primaryFields": [{"label": "CARD", "value": "Coffee Rewards"}], "secondaryFields": [ { "label": "POINTS", "value": "500", "changeMessage": "You earned %@ points" } ], "colorPreset": "dark" }' ``` -------------------------------- ### Location Trigger Configuration Source: https://walletwallet.dev/llms-full.txt Example JSON structure for configuring location triggers in Apple Wallet passes. Up to 10 locations can be specified per pass. ```json { "locations": [ { "latitude": 37.331741, "longitude": -122.030333, "relevantText": "Welcome to Apple Park" } ] } ``` -------------------------------- ### Start Over and Reset State Source: https://walletwallet.dev/docs Resets the component to its initial state, stopping polling, clearing local storage, and resetting various properties. ```javascript startOver() { this.stopPolling(); if (this.apiKey) localStorage.removeItem('ww_demo_session::' + this.apiKey); this.confirmingStartOver = false; this.serial = null; this.devices = []; this.googleInstalled = null; this.mode = 'create'; this.previewTab = 'preview'; this.messageText = ''; this.showMessageInput = false; this.lastPutStatus = null; this.notifValue = ' '; this.error = ''; } ``` -------------------------------- ### Google Wallet Install-State Callback Source: https://www.walletwallet.dev/llms.txt Receives signed save and remove events from Google Wallet. The state of the pass (saved or removed) is updated and can be retrieved via the GET /api/passes/{serial} endpoint. ```APIDOC ## POST /webhooks/google-wallet ### Description Receives signed save and remove events from Google Wallet. The state of the pass (saved or removed) is updated and can be retrieved via the GET /api/passes/{serial} endpoint. ### Method POST ### Endpoint /webhooks/google-wallet ### Request Body Google's signed save/remove events. The exact structure is not detailed in the source. ### Response #### Success Response Indicates successful receipt and processing of the webhook event. ``` -------------------------------- ### Generate Pass via Fetch API Source: https://walletwallet.dev/docs Programmatically generates a new pass using the Fetch API. Handles success and error responses, and initiates polling for installation status. ```javascript async generate() { this.error = ''; this.success = false; this.generating = true; this.lastPutStatus = null; const body = JSON.parse(this.requestBody); try { // Unified endpoint: /api/passes returns JSON for both wallets by // default ({ serialNumber, googleSaveUrl, applePass }), vs the // Apple-only binary from /api/pkpass. const r = await fetch(this.apiUrl + '/api/passes', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + this.apiKey, }, body: JSON.stringify(body), }); if (!r.ok) { const err = await r.json().catch(() => ({})); this.error = err.error || ('Error ' + r.status); this.generating = false; return; } const created = await r.json(); const serial = created.serialNumber; this.googleSaveUrl = created.googleSaveUrl || null; // The pass is persisted (POST /api/passes wrote the serial + canonical // body), so it installs straight from the hosted /p/ page — both // wallets, a permanent link, no R2 round-trip. Drop into the install view // and render the /p/ QR. if (this._showGenerate && serial) { this.serial = serial; this.devices = []; this.googleInstalled = null; this.mode = 'pending-install'; this.previewTab = 'share'; this.saveSession(); this.installPollFastUntil = Date.now() + 90000; this.startPolling(); this.$nextTick(() => { this.renderQR(); if (window.lucide) window.lucide.createIcons(); }); } this.success = true; setTimeout(() => { this.success = false; }, 3000); } catch (e) { this.error = 'Network error'; } finally { this.generating = false; } } ``` -------------------------------- ### Initialize Component and Load Session Source: https://walletwallet.dev/docs Initializes the component, sets up visibility change listeners for polling, and attempts to resume a saved session. ```javascript async init() { if (!this._showGenerate) return; this.isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); try { const v = localStorage.getItem('ww_notif_info_expanded'); if (v === '1') this.notifInfoExpanded = true; else if (v === '0') this.notifInfoExpanded = false; } catch {} // Pause polling when tab is hidden, resume when visible. document.addEventListener('visibilitychange', () => { if (document.hidden) { this.stopPolling(); } else if (this.mode === 'pending-install' && this.serial) { this.startPolling(); } }); // Resume saved session if recent and the pass still exists. if (!this.apiKey) return; let saved = null; try { saved = JSON.parse(localStorage.getItem('ww_demo_session::' + this.apiKey) || 'null'); } catch {} if (!saved || !saved.serial) return; this.serial = saved.serial; if (typeof saved.notifValue === 'string') this.notifValue = saved.notifValue; // Probe install status; if 403/404, startOver clears it. await this.pollInstallStatus(); if (this.serial) { this.mode = this.installCount > 0 ? 'live' : 'pending-install'; this.previewTab = 'share'; // Render the QR for any generated pass, installed or not — the // hosted /p/ page is shareable forever, so it must survive // re-init once a device has connected (mode === 'live'). this.$nextTick(() => this.renderQR()); if (this.mode === 'pending-install') { this.installPollFastUntil = Date.now() + 30000; this.startPolling(); } } } ``` -------------------------------- ### Legacy Create Pass Source: https://walletwallet.dev/llms-full.txt Creates a new pass and returns the `.pkpass` binary directly, along with relevant headers. ```APIDOC ## POST /api/pkpass ### Description Creates a new pass and returns the `.pkpass` binary directly, along with relevant headers. ### Method POST ### Endpoint /api/pkpass ### Parameters #### Request Body - **organizationName** (string) - Required - The name of the organization issuing the pass. - **expirationDays** (integer) - Optional - The number of days until the pass expires. - **sharingProhibited** (boolean) - Optional - Whether sharing of the pass is prohibited. - **locations** (array) - Optional - A list of locations associated with the pass. - **colorPreset** (string) - Optional - A preset color for the pass. - **fields** (array) - Optional - An array of fields to display on the pass. - **changeMessage** (string) - Optional - A message to display when the pass is updated. - **color** (string) - Optional - Pro plan only. The color of the pass. - **logoURL** (string) - Optional - Pro plan only. The URL for the logo. - **thumbnailURL** (string) - Optional - Pro plan only. The URL for the thumbnail image. - **stripURL** (string) - Optional - Pro plan only. The URL for the strip image. - **iconURL** (string) - Optional - Pro plan only. The URL for the icon image. ### Response #### Success Response (200) - **X-Serial-Number** (string) - The serial number of the created pass. - **X-Google-Save-Url** (string) - The URL to save the pass to Google Wallet. - **X-Pass-Url** (string) - The URL for the Apple Pass. (The response body is the binary `.pkpass` file.) ``` -------------------------------- ### Poll Install Status Source: https://walletwallet.dev/docs Periodically polls the API to check the installation status of a pass. Resets if the pass is not found or access is denied, indicating a potential session issue. ```javascript async pollInstallStatus() { if (!this._showGenerate || !this.serial) return; try { const r = await fetch(this.apiUrl + '/api/passes/' + this.serial, { headers: { 'Authorization': 'Bearer ' + this.apiKey }, }); if (r.status === 404 || r.status === 403) { // Session expired / pass no longer ours — reset. return; } } ``` -------------------------------- ### Get Usage Source: https://walletwallet.dev/llms-full.txt Retrieves the current month's pass usage counter. ```APIDOC ## GET /api/auth/usage ### Description Retrieves the current month's pass usage counter. ### Method GET ### Endpoint /api/auth/usage ### Response #### Success Response (200) - **usage** (integer) - The number of passes used this month. #### Response Example ```json { "usage": 500 } ``` ``` -------------------------------- ### Initialize PostHog Analytics Source: https://walletwallet.dev/docs Initializes the PostHog analytics service with the provided API key and host. This is essential for tracking user activity and events. ```javascript !(function (t, e) { var o, n, p, r; e.__SV || (window.posthog && window.posthog.__loaded) || ((window.posthog = e), (e._i = []), (e.init = function (i, s, a) { function g(t, e) { var o = e.split("."); 2 == o.length && ((t = t[o[0]]),(e = o[1])),(t[e] = function () { t.push([e].concat(Array.prototype.slice.call(arguments, 0,))); }); } ((p = t.createElement("script")).type = "text/javascript"), (p.crossorigin = "anonymous"), (p.async = !0), (p.src = s.api_host.replace(".i.posthog.com", "-assets.i.posthog.com")) + "/static/array.js"), (r = t.getElementsByTagName("script")[0]).parentNode.insertBefore(p, r); var u = e; void 0 !== a ? (u = e[a] = []) : (a = "posthog"), (u.people = u.people || []), (u.toString = function (t) { var e = "posthog"; return ("posthog" !== a && (e += "." + a)), t || (e += " (stub)"), e; }), (u.people.toString = function () { return u.toString(1) + ".people (stub)"; }), (o = "rn sn init kn Qr wn Cn yn capture calculateEventProperties Rn register register_once register_for_session unregister unregister_for_session An getFeatureFlag getFeatureFlagPayload getFeatureFlagResult isFeatureEnabled reloadFeatureFlags updateFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSurveysLoaded onSessionId getSurveys getActiveMatchingSurveys renderSurvey displaySurvey cancelPendingSurvey canRenderSurvey canRenderSurveyAsync Fn identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset setIdentity clearIdentity get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException addExceptionStep captureLog startExceptionAutocapture stopExceptionAutocapture loadToolbar get_property getSessionProperty On En createPersonProfile setInternalOrTestUser Ln gn $n opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing get_explicit_consent_status is_capturing clear_opt_in_out_capturing In debug Kr Pn getPageViewId captureTraceFeedback captureTraceMetric vn".split(" ")), (n = 0); n < o.length; n++) g(u, o[n]); e._i.push([i, s, a]); }), (e.__SV = 1)); })(document, window.posthog || []); posthog.init("phc_TuRDld3L1ont04loMATucg4ADOXcAncHFoQku0179aS", { api_host: "https://b.walletwallet.dev", ui_host: "https://eu.posthog.com", defaults: "2026-05-30", person_profiles: "always", }); ``` -------------------------------- ### GET /api/auth/usage Source: https://www.walletwallet.dev/llms.txt Retrieves the current month's usage counter for the authenticated user. ```APIDOC ## GET /api/auth/usage ### Description Retrieves the current month's usage counter for the authenticated user. ### Method GET ### Endpoint /api/auth/usage ### Response #### Success Response (200) - **usage** (integer) - The current month's pass usage count. ``` -------------------------------- ### Get Shareable URL Source: https://walletwallet.dev/docs Constructs a shareable URL for the pass using its serial number and API URL. ```javascript get shareUrl() { return this.serial ? (this.apiUrl + '/p/' + this.serial) : ''; } ``` -------------------------------- ### Create Membership Card (Minimal) Source: https://walletwallet.dev/docs Use this cURL command to create a basic membership card with a barcode and logo text. Ensure you replace 'ww_live_' with your actual API key. ```cURL curl -X POST https://api.walletwallet.dev/api/passes \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ww_live_" \ -d '{ "barcodeValue": "MEMBER-12345", "barcodeFormat": "QR", "logoText": "Membership Card" }' ``` -------------------------------- ### POST /api/pkpass Source: https://www.walletwallet.dev/llms.txt Creates a new pass and returns the `.pkpass` binary directly, along with relevant headers. ```APIDOC ## POST /api/pkpass ### Description Creates a new pass and returns the `.pkpass` binary directly, along with relevant headers. ### Method POST ### Endpoint /api/pkpass ### Parameters #### Request Body (Same as POST /api/passes) ### Response #### Success Response (200) - **X-Serial-Number** (string) - The unique serial number of the pass. - **X-Google-Save-Url** (string) - The URL to save the pass to Google Wallet. - **X-Pass-Url** (string) - The URL for the pass. - **Binary** - The `.pkpass` binary content. ``` -------------------------------- ### Update Issued Pass with cURL Source: https://www.walletwallet.dev/llms.txt Example of updating an issued pass using cURL, including a change message that will appear on the lock screen. ```bash curl -X PUT https://api.walletwallet.dev/api/passes/8f4c3a2e-... -H "Content-Type: application/json" -H "Authorization: Bearer ww_live_" -d '{ "barcodeValue": "LOYALTY-98765", "barcodeFormat": "QR", "logoText": "Bayroast Coffee", "primaryFields": [{"label": "CARD", "value": "Coffee Rewards"}], "secondaryFields": [ { "label": "POINTS", "value": "500", "changeMessage": "You earned %@ points" } ], "colorPreset": "dark" }' ``` -------------------------------- ### Create Pass with Pro Branding Source: https://walletwallet.dev/llms-full.txt Create a pass using custom hex colors and brand assets like logos and icons. This allows for a more personalized appearance. ```bash curl -X POST https://api.walletwallet.dev/api/passes \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ww_live_" \ -d '{ "barcodeValue": "VIP-001", "barcodeFormat": "QR", "logoText": "VIP Access", "primaryFields": [{"label": "PASS", "value": "VIP Access"}], "color": "#8B4513", "logoURL": "https://example.com/logo.png", "iconURL": "https://example.com/icon.png", "thumbnailURL": "https://example.com/member-photo.png" }' ``` -------------------------------- ### Update Pass Source: https://walletwallet.dev/docs Updates a previously issued pass. Devices with the pass installed will receive an update notification. Requires authentication and ownership of the serial number. ```APIDOC ## PUT /api/passes/ ### Description Updates a previously-issued pass. Devices that have it installed receive an Apple Push Notification within seconds; Wallet refreshes the pass in place with a lock-screen banner. Requires authentication and ownership of the serial. ### Method PUT ### Endpoint /api/passes/ ### Headers - **Content-Type**: application/json - **Authorization**: Bearer ww_live_ ### Request Body Same shape as `POST /api/passes`. Send the full pass specification. The server replaces the stored body, recomputes a content hash, and fans out push notifications to registered devices. * The URL path's `` identifies the pass — do not include `serialNumber` in the body. * `authenticationToken` is server-owned and immutable once issued; including it in the body returns 400. * To surface a custom lock-screen banner on update, add `changeMessage` on the field whose value is changing (e.g. `"You earned %@ points"`). iOS substitutes `%@` with the new value. * An identical body returns `{ unchanged: true }` with no push and no quota impact — safe to retry. ### Response #### Success Response (200) - `{ "unchanged": true }` if the body is identical to the stored pass. #### Error Responses - **400** Validation error — missing or invalid fields, or invalid `authenticationToken`. - **401** Invalid or missing API key. - **403** Pass not found or not owned by the authenticated user. - **429** Monthly rate limit exceeded. ``` -------------------------------- ### Create a Pass (POST) Source: https://walletwallet.dev/docs Use this endpoint to create a new pass. It returns URLs for adding to Google Wallet and a base64 encoded Apple Wallet pass. Ensure your API key is correctly formatted. ```javascript const response = await fetch('https://api.walletwallet.dev/api/passes', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ww_live_' }, body: JSON.stringify({ barcodeValue: 'TICKET-789', barcodeFormat: 'QR', logoText: 'Event Ticket', primaryFields: [{ label: 'EVENT', value: 'Concert' }], secondaryFields: [{ label: 'Seat', value: 'A-23' }] }) }); if (!response.ok) { const error = await response.json(); throw new Error(error.error); } // One JSON response covers both wallets const { serialNumber, googleSaveUrl, applePass } = await response.json(); // googleSaveUrl -> "Add to Google Wallet" link. applePass -> base64 .pkpass. // Browser: trigger the Apple Wallet download const bytes = Uint8Array.from(atob(applePass), c => c.charCodeAt(0)); const url = URL.createObjectURL(new Blob([bytes], { type: 'application/vnd.apple.pkpass' })); const a = document.createElement('a'); a.href = url; a.download = 'ticket.pkpass'; a.click(); // Node.js: save to file // const fs = require('fs'); // fs.writeFileSync('ticket.pkpass', Buffer.from(applePass, 'base64')); ``` -------------------------------- ### Get Usage Statistics Source: https://walletwallet.dev/llms-full.txt Retrieves the current month's usage statistics for the authenticated API key, including counts, limits, and plan details. ```APIDOC ## GET /api/auth/usage ### Description Returns the current month's stats for the authenticated key. ### Method GET ### Endpoint /api/auth/usage ### Parameters #### Query Parameters None #### Request Body None ### Request Example ```bash curl https://api.walletwallet.dev/api/auth/usage \ -H "Authorization: Bearer ww_live_" ``` ### Response #### Success Response (200) - **count** (integer) - The number of passes created this month. - **limit** (integer) - The total limit for passes this month. - **remaining** (integer) - The number of passes remaining for this month. - **resetDate** (string) - The date when the usage stats reset (UTC). - **plan** (string) - The current plan ('free' or 'pro'). #### Response Example ```json { "count": 150, "limit": 1000, "remaining": 850, "resetDate": "2026-06-01", "plan": "free" } ``` ``` -------------------------------- ### Create VIP Access Pass (Custom Color & Logo) Source: https://walletwallet.dev/docs Use this cURL command to create a VIP access pass with custom color and a logo URL. Remember to replace 'ww_live_' with your actual API key. ```cURL curl -X POST https://api.walletwallet.dev/api/passes \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ww_live_" \ -d '{ "barcodeValue": "VIP-001", "barcodeFormat": "QR", "logoText": "VIP Access", "primaryFields": [{"label": "PASS", "value": "VIP Access"}], "color": "#8B4513", "logoURL": "https://example.com/logo.png" }' ``` -------------------------------- ### Create Pass Source: https://walletwallet.dev/llms-full.txt Creates a new digital pass and returns the signed .pkpass file. It also provides a Google Wallet save URL and the server-generated serial number. ```APIDOC ## POST /api/passes, create a pass ### Description Creates a new digital pass and returns the signed `.pkpass` file. The response includes custom headers for content type, content disposition, serial number, and a Google Save URL. ### Method POST ### Endpoint `/api/passes` ### Parameters #### Request Body - **pass.json** (object) - Required - The JSON payload representing the pass details. This should conform to the Apple Wallet pass specification. ### Request Example ```json { "pass.json": { "description": "Sample Pass", "logoText": "Sample Company", "foregroundColor": "#ffffff", "backgroundColor": "#000000", "organizationName": "Sample Company", "passTypeIdentifier": "pass.com.sample.app", "serialNumber": "server-generated-uuid", "teamIdentifier": "sample-team-id", "webServiceURL": "https://example.com/passes/", "authenticationToken": "server-generated-token", "generic": { "headerFields": [ { "key": "title", "label": "Sample Title", "value": "Sample Value" } ] } } } ``` ### Response #### Success Response (200) - **application/vnd.apple.pkpass** - The signed `.pkpass` file. - **Content-Type**: `application/vnd.apple.pkpass` - **Content-Disposition**: `attachment; filename=".pkpass"` - **X-Serial-Number**: `` - The server-generated serial number for the pass. - **X-Google-Save-Url**: `https://pay.google.com/gp/v/save/` - The URL to save the pass to Google Wallet. #### Response Example (Binary .pkpass file content) ### Error Handling - **400**: Validation error. - **401**: Bad or missing API key. - **403**: Serial belongs to another key. - **404**: Unknown serial or route. - **405**: Wrong HTTP method. - **429**: Monthly limit hit. - **500**: Server error. ``` -------------------------------- ### Create Pass and Save Apple Pass in Python Source: https://walletwallet.dev/llms-full.txt Create a pass using the `requests` library in Python and save the base64 encoded Apple Pass data to a file. Handles potential User-Agent blocking by Cloudflare. ```python import requests import base64 r = requests.post( 'https://api.walletwallet.dev/api/passes', headers={ 'Content-Type': 'application/json', 'Authorization': 'Bearer ww_live_', }, json={ 'barcodeValue': 'ORDER-456', 'barcodeFormat': 'Code128', 'logoText': 'Order Pickup', 'primaryFields': [{'label': 'ORDER', 'value': 'Pickup'}], 'secondaryFields': [{'label': 'Order #', 'value': '456'}], }, ) r.raise_for_status() data = r.json() # { serialNumber, googleSaveUrl, applePass, shareUrl } serial = data['serialNumber'] with open('order.pkpass', 'wb') as f: f.write(base64.b64decode(data['applePass'])) ``` -------------------------------- ### Create Order Pass with Python Source: https://walletwallet.dev/docs Use this snippet to create an order pass. It sends a POST request to the API and saves the generated pass to a file. ```python import requests, base64 response = requests.post( 'https://api.walletwallet.dev/api/passes', headers={ 'Content-Type': 'application/json', 'Authorization': 'Bearer ww_live_' }, json={ 'barcodeValue': 'ORDER-456', 'barcodeFormat': 'Code128', 'logoText': 'Order Pickup', 'primaryFields': [{'label': 'ORDER', 'value': 'Pickup'}], 'secondaryFields': [{'label': 'Order #', 'value': '456'}] } ) response.raise_for_status() data = response.json() # data['serialNumber'], data['googleSaveUrl'] (Add to Google Wallet link) with open('order.pkpass', 'wb') as f: f.write(base64.b64decode(data['applePass'])) ``` -------------------------------- ### Rate Limit Exceeded Error Response Source: https://www.walletwallet.dev/llms.txt Example JSON response when the API rate limit is exceeded. Includes error details, reset date, and a descriptive message. ```json { "error": "Rate limit exceeded", "resetDate": "2026-06-01", "message": "Monthly limit reached. Resets on 2026-06-01" } ``` -------------------------------- ### POST /api/passes Source: https://www.walletwallet.dev/llms.txt Creates a new digital pass and returns the signed .pkpass file. It also provides headers for saving to Apple Wallet and Google Wallet. ```APIDOC ## POST /api/passes, create a pass ### Description Creates a new digital pass and returns the signed `.pkpass` file. The response includes headers for saving to Apple Wallet and Google Wallet, along with the serial number. ### Method POST ### Endpoint `/api/passes` ### Request Body - **field1** (type) - Required/Optional - Description ### Response #### Success Response (200) - **Content-Type**: `application/vnd.apple.pkpass` - **Content-Disposition**: `attachment; filename=".pkpass"` - **X-Serial-Number**: `` - The server-generated serial number for the pass. - **X-Google-Save-Url**: `https://pay.google.com/gp/v/save/` - The Save to Google Wallet link. #### Response Example (Binary .pkpass file content) ### Error Handling - `400` validation - `401` bad/missing key - `403` serial belongs to another key - `404` unknown serial or unknown route - `405` wrong method - `429` monthly limit hit - `500` server error ``` -------------------------------- ### Pass Color Configuration Source: https://walletwallet.dev/llms-full.txt Defines the background, foreground, and label colors for a pass using RGB values. Ensure sufficient contrast between background and foreground for readability. ```json { "backgroundColor": "rgb(30, 64, 175)", "foregroundColor": "rgb(255, 255, 255)", "labelColor": "rgb(191, 219, 254)" } ``` -------------------------------- ### Get Google Pass Save URL Source: https://walletwallet.dev/llms-full.txt Retrieves a public redirect URL for saving a specific pass to Google Wallet. This is useful for creating 'Add to Google Wallet' buttons. ```APIDOC ## GET /api/passes/{serial}/google ### Description This endpoint provides a public 302 redirect to the Google Wallet save URL for a given pass serial number. It is intended to be used for creating "Add to Google Wallet" buttons. ### Method GET ### Endpoint /api/passes/{serial}/google ### Parameters #### Path Parameters - **serial** (string) - Required - The unique serial number of the pass. ### Response #### Success Response (302) - **Location** (string) - Redirects to the `googleSaveUrl`. #### Response Example (Redirects to a URL like: https://pay.google.com/gp/v/save/) ``` -------------------------------- ### Get API Usage Statistics Source: https://www.walletwallet.dev/llms.txt Retrieves the current month's API usage statistics for the authenticated key, including usage count, limit, remaining quota, and reset date. ```APIDOC ## GET /api/auth/usage ### Description Returns the current month's statistics for the authenticated API key. ### Method GET ### Endpoint /api/auth/usage ### Parameters #### Query Parameters None #### Request Body None ### Request Example ```bash curl https://api.walletwallet.dev/api/auth/usage \ -H "Authorization: Bearer ww_live_" ``` ### Response #### Success Response (200) - **count** (integer) - The number of API calls made this month. - **limit** (integer) - The total API call limit for the month. - **remaining** (integer) - The number of remaining API calls for the month. - **resetDate** (string) - The date when the usage resets (first of the next month, UTC). - **plan** (string) - The current subscription plan ('free' or 'pro'). #### Response Example { "count": 150, "limit": 1000, "remaining": 850, "resetDate": "2026-06-01", "plan": "free" } ```