Passmint
TemplatesIntegrationsDocsPricing
Log inGet started
Passmint

Apple and Google Wallet passes from one API. Built for people who ship.

  • GitHub
  • X
Product
  • Pass Designer
  • Developers
  • Distribution
  • Analytics
  • Templates
  • Integrations
  • Pricing
Resources
  • Free tools
  • Wallet card generator
  • pkpass validator
  • Pass anatomy
  • Live demo
  • Blog
  • Glossary
  • Compare
Developers
  • Documentation
  • API reference
  • Node SDK
  • Webhooks
  • MCP server
Company
  • Changelog
  • About
  • Contact
  • Support
  • Security
  • Terms
  • Privacy

© 2026 Passmint.

Apple Wallet & Google Wallet, one API.

Getting started

  • Overview
  • Quickstart

API

  • REST API reference
    • Authentication
    • Passes
    • Templates
    • Events
    • Webhooks
    • Errors
  • Pass images
    • Image slots
    • How images resolve
    • Stamp card example
    • Member photo example
    • Google Wallet
    • Privacy
  • Webhooks
    • Event types
    • Creating a webhook
    • Payload format
    • Verifying signatures
    • Retries
  • MCP server
    • Install
    • The endpoint
    • Other clients
    • Read-only mode
    • Tools
    • Things worth knowing
    • Example prompts
    • What it doesn't do
    • Rate limits
  • Node.js SDK
    • Configuration
    • Passes
    • Templates
    • Webhook signatures
    • Errors
    • Idempotency

Open source

  • Passmint Package
Guide

Pass images.

A pass's artwork comes from its template. When some passes need different artwork from others, such as a stamp card that shows how many stamps the holder has, give the template image variantsand point each pass at one. When one pass needs artwork of its own, such as a membership card with the member's photo, upload a pass image.

01

Image slots

Images are uploaded per slot, using Apple's names: icon, logo, strip, thumbnail, background and footer. Which slots a template can use depends on its Apple pass style. icon is required.

StyleTemplate slotsVariant and pass slots
genericicon, logo, thumbnailthumbnail
storeCardicon, logo, stripstrip
couponicon, logo, stripstrip
eventTicketicon, logo, strip, thumbnail, backgroundstrip, thumbnail, background
boardingPassicon, logo, footernone

Uploading a slot the style doesn't have returns 400 with code: "image_slot_not_allowed" and param: "slot". Send PNG, JPEG or WebP at any resolution, up to 8 MB. Passmint resizes each image to the slot's 1x and @2x sizes.

02

How a pass's images resolve

Each slot resolves on its own, top-down. The first of these layers that has the slot wins:

  1. Pass image: uploaded for this one pass with PUT /v1/passes/:id/images/:slot.
  2. Variant image: from the pass's image_variant, a named image set on the template.
  3. Template image: the template's own slot.

A layer only replaces the slots it holds. A variant with just a stripkeeps the template's icon, logo and everything else, so you upload only the image that changes. A pass image of the thumbnailkeeps the variant's strip.

Variants and pass images can hold strip, thumbnail and background, limited to the slots the style has (see the table above). icon and logoare the template's identity and never vary per pass.

Every pass object has an images map with each slot the pass renders and the layer it comes from:

"images": {
  "icon": { "source": "template" },
  "logo": { "source": "template" },
  "strip": { "source": "variant" },
  "thumbnail": { "source": "pass" }
}

A variant name is 1-32 characters of lowercase letters, digits, - and _, starting with a letter or digit. A variant exists once it holds at least one image, and it is listed in the template's image_variants.

03

Example: a stamp card

A ten-stamp loyalty card on a storeCard template. Pre-render a strip for each stamp count and upload them once, as variants 0 to 9 and reward:

for v in 0 1 2 3 4 5 6 7 8 9 reward; do
  curl -X PUT https://api.passmint.com/v1/templates/tmpl_xxx/images/strip \
    -H "Authorization: Bearer pmk_test_xxx" \
    -H "Content-Type: application/json" \
    -d "{ \"variant\": \"$v\", \"data\": \"$(base64 -i strip-$v.png)\" }"
done

Issue each card on variant 0:

curl https://api.passmint.com/v1/passes \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "template_id": "tmpl_xxx", "image_variant": "0" }'

With each stamp, move the pass to the next variant. Changing image_variantis an update like any other. The pass is re-signed and pushed to the holder's wallet with its new strip. Changing only the variant is a valid update.

curl -X PATCH https://api.passmint.com/v1/passes/pass_xxx \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "image_variant": "4", "field_values": { "stamps": "4" } }'

Send "image_variant": nullto return a pass to the template's own images. Naming a variant the template doesn't have returns 400 with code: "unknown_image_variant".

In the dashboard, the designer's Images section has a Variantspanel for adding variants and previewing the pass with each one. A pass's page lets you switch its variant.

04

Example: a member photo

A membership card on a generictemplate, with each member's photo as the thumbnail. Issue the pass first, then upload the photo for it. A pass can't be created with images; they are always a second call.

curl -X PUT https://api.passmint.com/v1/passes/pass_xxx/images/thumbnail \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -d "{ \"data\": \"$(base64 -i ada.jpg)\" }"

The response is the pass, with images.thumbnail.source now "pass". The pass is re-signed and pushed to the holder's wallet, as for any update. Upload again to replace the photo. Images are never accepted in PATCH /v1/passes/:id.

To remove it, so the slot falls back to the variant or template:

curl -X DELETE https://api.passmint.com/v1/passes/pass_xxx/images/thumbnail \
  -H "Authorization: Bearer pmk_test_xxx"

A slot the style doesn't allow for pass images returns 400 with code: "image_slot_not_allowed". Uploading to a voided pass returns 409; deleting still works (see privacy, below). If Google Wallet could not be updated, the request succeeds and the response's warningssays why. In the dashboard, a pass's Images tab uploads, replaces and removes its images and shows where each slot comes from.

05

Google Wallet

Google Wallet passes are built from the same images. Google keeps shared images on the template's classand per-pass images on each pass's object. Class images only ever come from the template, so one holder's variant or photo never shows on anyone else's pass.

ImageLoyalty, offer, event ticket, transitGeneric
logo (template)Class logo, shared by every pass of the templateObject logo (Google's generic class has no images)
strip (template)Class hero image; each pass shows it unless it has its ownObject hero image
strip (variant or pass)That pass's object hero, over the class heroObject hero image
thumbnail (pass)An image module on the pass details (id pass-thumbnail)Object logo: the round image at the top, in place of the template logo
background, footer, icon; a template or variant thumbnailNot shown (Apple Wallet only)Not shown (Apple Wallet only)

Google has no thumbnail. On a generic pass, a pass thumbnailbecomes the round logo at the top of the card. The other types have no per-pass logo, so it is shown as an image module in the pass details instead. Removing a pass or variant image clears it from the pass's object, and the class image shows again.

06

Changing and removing images

  • Replacing a template or variant image doesn't touch issued passes. They pick it up the next time they are issued or updated.
  • Remove a variant's slot with DELETE /v1/templates/:id/images/:slot?variant=…. A variant with no images left drops out of image_variants. Passes still set to it show the template's images.
  • Uploading or removing a pass image re-signs and pushes the pass straight away.
  • A pass's variant and pass image changes are recorded in its activity. The pass in every webhook and GET /v1/events payload carries its current image_variant.
  • Images stay on voided passes, which still display. A voided pass can't get new images, but its own images can still be deleted, which erases them.
07

Pass images and privacy

A pass image can be personal data, like a member's photo. Google Wallet loads images from a public URL, so Passmint gives each pass's images an address built from a random token, never from the pass's id, short id or serial number. The token changes every time a pass image is uploaded or removed. After a removal the old address stops working at once; after an upload, as soon as the pass has been updated to the new one.

DELETE /v1/passes/:id/images/:slotis how to erase a pass image. It deletes the stored image and its public copy straight away, even if Google Wallet can't be reached, and updates the pass in the holder's wallet. It works on voided passes too (the image is erased; the voided pass isn't re-signed). The API and dashboard never return the public address. Upload requests are not kept in your API request logs.

Up next:
Template image endpoints →Pass image endpoints →Webhooks →