Open dashboardwalletap.com

Work with templates

List, read, create, change, duplicate and delete templates over the API, and upload the images they use.

Web

Most templates are designed in the dashboard, where you can see the pass as you build it. The API does the same work from code — useful when you set up the same card for many locations, or keep a design under version control. Everything you change here shows in the dashboard designer, and the other way round.

Paid plans

Before you start#

  • A key with the template scopes for what you do. Manage passes and Read only keys can list and read templates; creating, changing and deleting needs Full access or a key with templates.create, templates.edit or templates.delete. See Scopes.
  • To design in the dashboard instead, see Create a template.

List templates#

GEThttps://api.walletap.com/templates
Shell
curl "https://api.walletap.com/templates?limit=50" \
  -H "X-API-Key: $WALLETAP_API_KEY"
JSON
{
  "object": "list",
  "data": [
    { "object": "template", "id": "tmpl_123", "name": "Coffee Card", "type": "loyalty", … },
    { "object": "template", "id": "tmpl_789", "name": "Harbour Points", "type": "loyalty", … }
  ],
  "has_more": false,
  "next_cursor": null,
  "total_count": 6,
  "url": "/templates"
}

Templates come newest first, 15 per page unless you set limit (up to 100). While has_more is true, request the next page with starting_after set to next_cursor.

Read a template#

GEThttps://api.walletap.com/templates/{id}
Shell
curl https://api.walletap.com/templates/tmpl_123 \
  -H "X-API-Key: $WALLETAP_API_KEY"
FieldWhat it is
id, name, typeThe template's identity and pass type
passThe design, as a JSON string: colours, images, barcode and fields
enrollFormThe sign-up form, as a JSON string
passPageThe pass page's design, as a JSON string
created, updatedEpoch milliseconds

Parse pass to read the design. Its header, rows and linkRows hold the fields on the pass, and each field's id is the key you use for its value when you issue a pass.

Create a template#

POSThttps://api.walletap.com/templates

Only name and type are required. Walletap starts from its default design for the type and applies whatever you send in pass on top.

Shell
curl -X POST https://api.walletap.com/templates \
  -H "X-API-Key: $WALLETAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Northside Membership",
    "type": "generic",
    "pass": {
      "backgroundColor": "#1B2A3A",
      "logo": { "fileId": "file_0123456789abcdef0123456789abcdef" },
      "header": { "id": "memberName", "label": "Member" },
      "rows": [
        [
          { "id": "plan", "label": "Plan" },
          {},
          { "id": "validUntilDate", "label": "Valid until" }
        ]
      ],
      "barcodeType": "qrcode"
    }
  }'

The response is the new template, with status 201. Walletap then sets up its Apple Wallet and Google Wallet identities in the background.

Types#
typeIn the dashboard
genericGeneric — membership and ID cards
loyaltyLoyalty — points and stamp cards
giftCardGift — carries a remaining balance
eventTicketEvent — a date, venue and seat
offerCoupon / Offer — a headline discount

Generic and loyalty templates start with a sign-up form asking for name, email and phone. See Sign-up page.

The design#

Common keys inside pass:

KeyNotes
backgroundColorHex colour. Text and label colours follow it automatically
textColor, labelColorUsed when adjustTextColor is false
logo, icon, hero, strip, thumbnail, backgroundImages. See Upload images
headerThe headline field
rowsFront fields: a list of rows, each up to three fields. Use {} for an empty column
linkRowsFields on the back of the pass, one per line
barcodefalse hides the barcode. true by default
barcodeTypeqrcode, code128, pdf417 or azteccode; code39, codabar, ean13 and itf show on iPhones from iOS 27 and fall back to Code 128 before that
useStampCollection, stampCountTurn a loyalty card into a stamp card with this many stamps

A field needs only an id and a label. When the id is one of the type's own fields, such as accountName on a loyalty card, it is bound to that field; any other id becomes a field of your own, filled from customFields when you issue a pass. Leave out id and Walletap derives one from the label, so "label": "Member number" gets the ID memberNumber.

See Fields and Barcodes and NFC for what each part does on the pass.

Stamp cards#

On a loyalty template, "useStampCollection": true with a stampCount makes a stamp card. Walletap supplies a default stamp image and banner; to use your own, upload them with the template_stamp and template_hero purposes and reference both as stamp and hero.

Change a template#

PATCHhttps://api.walletap.com/templates/{id}

Send only what changes:

Shell
curl -X PATCH https://api.walletap.com/templates/tmpl_123 \
  -H "X-API-Key: $WALLETAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "pass": { "backgroundColor": "#3B2418" } }'

Objects inside pass merge key by key, so the request above changes the colour and nothing else. Lists — rows and linkRows — are replaced whole, so send the complete list when you change one field in it. locations is replaced whole too, and an empty list clears it.

Saving a template refreshes the Apple Wallet passes already issued from it. In Google Wallet, template-wide parts change straight away, and each pass's own parts, such as its colour, change the next time that pass is updated. The response is the updated template.

Duplicate a template#

POSThttps://api.walletap.com/templates/{id}/duplicate
Shell
curl -X POST https://api.walletap.com/templates/tmpl_123/duplicate \
  -H "X-API-Key: $WALLETAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Coffee Card — Marina" }'

The copy gets the source's design and settings under the new name (up to 200 characters), with its own copies of the images and its own wallet identities. Members, passes and campaigns stay with the original. The response is the new template, with status 201. This call needs both templates.create and templates.duplicate.

Delete a template#

DELETEhttps://api.walletap.com/templates/{id}
Shell
curl -X DELETE https://api.walletap.com/templates/tmpl_321 \
  -H "X-API-Key: $WALLETAP_API_KEY"

A template with no passes is deleted and the call answers 204. A template that has issued passes answers 409 with "code": "template_has_passes" and the number in passCount, and nothing is deleted.

Warning

Deleting a template that has issued passes breaks every one of them: every pass is voided, so scanners refuse it, and it can no longer be updated or issued again, though holders keep the card in their wallet. Only if that is what you want, repeat the request with ?force=true. To stop issuing a card while keeping its passes working, leave the template in place.

Upload images#

POSThttps://api.walletap.com/files

Upload an image, then reference it from a template's design by its file ID.

Shell
curl -X POST https://api.walletap.com/files \
  -H "X-API-Key: $WALLETAP_API_KEY" \
  -F "file=@northside-logo.png" \
  -F "purpose=template_logo"

Or let Walletap fetch it from a public URL:

Shell
curl -X POST https://api.walletap.com/files \
  -H "X-API-Key: $WALLETAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://northside.example/logo.png", "purpose": "template_logo" }'
JSON
{
  "id": "file_0123456789abcdef0123456789abcdef",
  "object": "file",
  "url": "https://…/original.png",
  "purpose": "template_logo",
  "mime_type": "image/png",
  "size": 48213,
  "width": 1200,
  "height": 375,
  "variants": { "1x": "https://…", "2x": "https://…", "3x": "https://…" },
  "template_id": null,
  "source_url": null,
  "created": 1760180400000
}

Then use it in pass, in any image slot:

JSON
{ "pass": { "logo": { "fileId": "file_0123456789abcdef0123456789abcdef" } } }

Walletap replaces the reference with the image's URLs when it saves the template.

Purposes#

With a purpose, Walletap resizes the image for that slot and returns each size in variants. Without one, the original is stored as it is.

purposeSlotSize at 1x
template_logologo160 × 50
template_iconicon29 × 29
template_herohero1032 × 336, one size
template_stripstrip320 × 123
template_thumbnailthumbnail90 × 90
template_backgroundbackground180 × 220
template_stampstamp120 × 120

Send PNG, JPEG or WebP; SVG, AVIF, HEIC, GIF, TIFF and ICO are converted to PNG. Files can be up to 10 MiB. A URL is fetched for at most 10 seconds, and only from a public address. Add templateId to file the image under a template.

See Artwork for what each slot is and which pass types show it.

Logos on a solid background#

When you upload with template_logo and the logo sits on a solid background, Walletap also makes a copy with the background removed. If the cut-out is clean, the response is that transparent copy; the original is always kept. The response's logo object lists the forms that exist, with their IDs.

To pick a form yourself, ask for it by the file's ID:

Shell
curl -X POST https://api.walletap.com/files/file_0123456789abcdef0123456789abcdef/logo \
  -H "X-API-Key: $WALLETAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "treatment": "onecolor", "color": "#FFFFFF" }'

treatment is original, transparent or onecolor, which also needs a #RRGGBB color. The response is the file to put in pass.logo.

Read and delete files#

GET /files/{id} returns a file's details. DELETE /files/{id} deletes it and answers 204. A template that still shows a deleted image loses it, so remove the image from the design first.

If something goes wrong#

400 "Unsupported barcodeType…" — use one of the values in The design.

400 "Stamp collection (useStampCollection: true) requires both 'stamp' and 'hero' images…" — a stamp card needs both images. Upload them and reference them, or leave both out on a loyalty template to get the defaults.

400 "Invalid file id", 404 "File … not found" or 403 "File … does not belong to this account" — the fileId is mistyped, deleted, or from another account.

402 with "code": "upgrade_required" — the account's plan does not cover another template (feature: "templates"), this type of card (feature: "templateType") or this many places in locations (feature: "geofences").

403 with "code": "access_badge_not_creatable_here" — access badges are created in the dashboard. See Access badges.

404 "Resource not found" — the template does not exist or belongs to another account.

409 with "code": "template_has_passes" — see Delete a template.

413 "File exceeds 10 MiB limit" — make the image smaller.

504 "Upstream timeout…" — the image URL did not answer within 10 seconds. Upload the file instead.

Next steps#