Powered by Cloudflare Workers · instant push updates · 200ms pass generation worldwide
WalletWallet API
Get API Key Docs Pricing Changelog Log in

The simplest Wallet pass API.

Create a pass with one request, update every installed device with the next. No certificates. JSON in, .pkpass out. Apple and Google Wallet.

Push updates are Apple-only for now.

Free up to 1,000 passes/month, then $0.00019 per pass on Pro.

An alternative to PassKit, Pass2U,
or building on Apple's SDK.

Issue passes once, update them anytime.

Every pass gets a serial number. Call it again to update the pass or send a notification to the customer's lock screen. Communicate with users without making them download an app.

  1. Issue the pass

    POST the pass content. You get back a .pkpass and its own serial number. The customer adds it to Apple or Google Wallet.

    POST /api/pkpass
    curl -X POST https://api.walletwallet.dev/api/pkpass \
      -H "Authorization: Bearer ww_live_<key>" \
      -H "Content-Type: application/json" \
      -d '{
        "logoText": "Bayroast Coffee",
        "headerFields": [{ "label": "POINTS", "value": "1,250" }],
        "primaryFields": [{ "label": "CARD", "value": "Coffee Rewards" }]
      }' \
      -o pass.pkpass
  2. Push updates

    PUT new fields to that serial. The pass refreshes on every Apple device it's installed on, and your message shows as a lock-screen notification.

    PUT /api/pkpass/<serial>
    curl -X PUT https://api.walletwallet.dev/api/pkpass/<serial> \
      -H "Authorization: Bearer ww_live_<key>" \
      -d '{
        "headerFields": [{
          "label": "POINTS",
          "value": "1,300",
          "changeMessage": "Now at %@ points"
        }]
      }'
  3. Surface it by location

    Attach coordinates to the serial. Apple pins the pass to the lock screen when the customer is near the place you set.

    PUT /api/pkpass/<serial>
    curl -X PUT https://api.walletwallet.dev/api/pkpass/<serial> \
      -H "Authorization: Bearer ww_live_<key>" \
      -d '{
        "locations": [{
          "latitude": 40.7484,
          "longitude": -73.9857,
          "relevantText": "Free refill at our Empire State store"
        }]
      }'

No certificate to manage or APNs to setup. You only need to store the serial.

Why WalletWallet?

A unique serial per pass

Call it any time after issue to update the pass and push lock-screen notifications. One call reaches every device the customer installed it on: iPhone, iPad, Apple Watch.

Live pass updates

PUT new fields to a serial. The pass refreshes on every iPhone, iPad, and Apple Watch it installed on.

Push notifications

APNs handled automatically. A lock-screen banner shows the changeMessage you set.

Your branding

Logo, thumbnail, strip banner, foreground and background colors, custom field labels.

Lock-screen locations

Up to 10 GPS coordinates per pass. Wallet shows the pass when the user is nearby.

Edge-deployed

Hosted on Cloudflare Workers. Sub-200ms pass generation worldwide.

Preview the pass before any API call.

Tune every field, color, and image and watch the pass update. Copy the code when you're done.

Text next to the logo (top-left)

Notification title on pass updates. Defaults to your account name.

No header fields

No primary fields

No secondary fields

No back fields

Click the pin to fill a row with where you are, for testing. The real pass needs the actual place.

Wallet shows the pass on the lock screen within ~100m of a coordinate.

Pro feature — upgrade to add up to 10 lock-screen location triggers per pass.

Overrides color preset

Lock-screen and pass-update notification image. Defaults to your logo.

Wide banner image. Use secondary fields for readable text when using this option.

EXPIRES

The full API. Two endpoints.

Bearer auth, JSON in, signed .pkpass out. Click any endpoint to expand the schema.

Auth Authorization: Bearer ww_live_<your_key> Base https://api.walletwallet.dev
POST /api/pkpass

Request body

Field Type Req Description
barcodeValue string Yes Data encoded in the barcode (e.g., member ID, ticket number).
barcodeFormat string Yes One of QR PDF417 Aztec Code128.
logoText string No Text next to the logo (top-left of pass).
description string No Accessibility text (not visible). Defaults to logoText.
organizationName string No Issuer name shown as the notification title on pass updates and in the Wallet info screen. Max 64 chars. Falls back to your account default.
primaryFields array No Main content. Array of {label, value, changeMessage?}. changeMessage is the lock-screen banner template that fires when this field changes during a PUT.
secondaryFields array No Fields below primary. Array of {label, value, changeMessage?}.
headerFields array No Top-right header area. Array of {label, value, changeMessage?}.
backFields array No Back of pass. Array of {label, value, changeMessage?}.
locations array No Up to 10 geofences. {latitude, longitude, altitude?, relevantText?} per entry. Surfaces the pass on the lock screen when the device is nearby.
colorPreset string No Color theme: dark blue green red purple orange.
color string No Custom hex color (Pro). e.g., #1e40af.
logoURL string No Custom logo image (Pro). HTTPS URL or PNG data URI.
thumbnailURL string No Top-right image (Pro). HTTPS URL or PNG data URI.
stripURL string No Banner behind the primary field (Pro). Switches to store-card layout. HTTPS URL or PNG data URI.
iconURL string No Replaces the default lock-screen notification icon (Pro). Distinct from logoURL. HTTPS URL or PNG data URI.
title string No Legacy. Sets primaryFields[0].value + logoText if unset.
cardLabel string No Legacy. Sets primaryFields[0].label. Defaults to CARD.
label string No Legacy. Sets secondaryFields[0].label.
value string No Legacy. Sets secondaryFields[0].value.
expirationDays number No Pass expires after this many days. Any integer between 1 and 3650.

Response

  • 200 Returns application/vnd.apple.pkpass binary with an X-Serial-Number header.
  • 400 Invalid request body or missing required fields.
  • 401 Invalid or missing API key.
  • 429 Rate limit exceeded.
  • 500 Server error.

Example

curl -X POST https://api.walletwallet.dev/api/pkpass \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ww_live_<your_key>" \
  -d '{
    "barcodeValue": "MEMBER-12345",
    "barcodeFormat": "QR",
    "logoText": "Bayroast Coffee",
    "primaryFields": [{"label": "CARD", "value": "Coffee Rewards"}],
    "colorPreset": "green"
  }' \
  -o pass.pkpass
Full POST reference →
PUT /api/pkpass/<serial>

Request body

Same shape as POST. Send only the fields you want to change — everything else carries over from the existing pass. Identical bodies are no-ops: no APNs push, no quota cost. Setting changeMessage on a field that changed sets the lock-screen banner text.

Response

  • 200 Returns the new .pkpass binary. Triggers an APNs wake to every installed device.
  • 204 Identical body — no push, no quota cost.
  • 401 Invalid or missing API key.
  • 404 Serial not found.
  • 429 Rate limit exceeded.

Example

curl -X PUT https://api.walletwallet.dev/api/pkpass/<serial> \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ww_live_<your_key>" \
  -d '{
    "headerFields": [{
      "label": "POINTS",
      "value": "1,300",
      "changeMessage": "Now at %@ points"
    }]
  }'
Full PUT reference →

Coding with Codex, Claude, or another agent? Point it at /llms.txt for tight, up-to-date docs.

Flat pricing. No per-pass fees, no per-device fees.

For reference, PassKit charges $1,300/month for the same pass lifecycle features.

Free

Testing & side projects

$0 /month
  • 1,000 passes/month
  • Limited branding
  • Signed .pkpass delivery
Start free
30-day Pro trial

Pro

Production apps

$19 /month
  • 100,000 passes/month
  • Live updates & push notifications
  • Lock-screen location triggers
  • Logo, thumbnail, strip, icon
  • Priority email support
Start 30-day trial

Bring your own cert

Sign with your Apple Developer ID

Custom
  • Sign with your Apple certificate
  • Managed APNs on dedicated, low-latency workers
  • Volume pricing past 100k passes/month
  • SLA & dedicated technical support
  • Custom contract, DPA & onboarding
Schedule a call

I built WalletWallet because I needed Wallet passes for one of my apps, and the options were a $40/month dashboard or a week waiting on Apple for a signing certificate. Now it's one API call, signed with our cert, $19 flat. My email is on every page. I read all of it.

Alen, founder

Cool things you can build.

  • WalletWallet For agencies

    Run an agency? Sell a lightweight CRM to your small business clients.

    Build a white-label notification CRM on our API. Your agency clients pay you per customer they reach. We charge you $19 flat, no matter how many customers move through it.

  • WalletWallet For event organizers

    Host events? Make the badge update itself.

    Hand every attendee a pass that lives next to their physical badge. Push session changes, room swaps, and tomorrow’s agenda straight to their lock screen.

  • ShopifyWoo For store owners

    Running a small store? Skip the app build.

    Drop a pass into every order confirmation. Ping customers on the lock screen for restocks, drops, and order updates. No app install.

  • WalletWallet For B2B SaaS

    Building a B2B SaaS? Ship Wallet passes for every client.

    Your clients are businesses with their own customers to reach. Integrate WalletWallet once and the Wallet pass feature ships across every account on your platform. We don’t bill per client.

Build passes from the tools you already use

  • SumUp
  • Shopify
  • Woo
  • n8n
  • Zapier

Frequently asked questions

What's in the 30-day Pro trial?

Every new account starts on Pro for 30 days: all features, all image slots, lifecycle updates, unlimited passes. After that, keep Pro at $19/month or stay free under 1,000 passes/month. No card up front, no auto-charge.

Does this work with Google Wallet too?

The signed .pkpass file we return opens directly in Google Wallet on Android, so one API call lands a pass in both wallets. Live updates and push notifications are Apple-only. Google Wallet doesn't honor webServiceURL.

Can I update a pass after it's been added to someone's wallet?

Yes. Every pass gets a unique serial, returned in the X-Serial-Number response header and embedded inside the .pkpass file. PUT a new body to /api/pkpass/<serial> and the pass refreshes on every iPhone, iPad, or Apple Watch the customer added it to. Identical bodies don't trigger a push and don't count against your quota.

How do I send the pass to my customers?

The API response is the signed .pkpass binary. Forward it however you already reach your user: email attachment, "Add to Wallet" button on a confirmation page, SMS link, or in-app download. Apple Wallet picks it up automatically when opened on iPhone. Google Wallet does the same on Android.

Issue your first pass in five minutes.

Free under 1,000 passes a month. $19 flat above that, with 30 days of Pro on every new account.

curl -X POST https://api.walletwallet.dev/api/pkpass …