Creating passes over the API

The patterns that matter when you issue passes from your own systems - field ids, tags, listing and paginating, updating, pushing a message, and voiding.

Updated 7/26/2026

This is the main integration point: something happens in your system - a purchase, a booking, a signup - and a pass should exist.

Creating

curl -X POST "https://api-prod.getpocketpass.com/api/v1/passes?passTemplate=TEMPLATE_ID&extId=order-8891" \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "passContent": {
      "customerName": { "value": "Jane Doe" },
      "seat": { "value": "Row F, 12" }
    },
    "groupTags": ["spring-season"],
    "expiresAt": "2026-09-01T18:00:00Z"
  }'

passTemplate is required and goes in the query string. extId is optional but you should almost always set it - see External IDs and idempotency.

Field ids, not labels

The keys in passContent are the template's field ids. They're generated from the labels when a template is first saved and then frozen, so they don't always match what the label says now.

Get them from the template:

curl https://api-prod.getpocketpass.com/api/v1/pass-templates/TEMPLATE_ID \
  -H "Authorization: Bearer pk_live_..."

An id you send that isn't on the template is ignored rather than rejected, which makes a typo silently produce a pass with a missing value.

Don't hardcode field ids from memory. Read them from the template once at startup, or keep them in configuration that a human has checked against the API response. A typo here fails quietly, which is the worst way for it to fail.

Omitting a value is not the same as sending an empty one

Leave a field out of passContent and the pass uses the template's default. Send { "value": "" } and the pass shows nothing.

Usually you want the first. Only send an explicit empty string when you genuinely mean "blank, overriding the default".

Tags

groupTags is what makes a pass targetable later. Set them at creation from whatever your system already knows - the plan, the region, the cohort, the campaign that brought them in.

{ "groupTags": ["annual", "manchester", "referral"] }

Tags are normalised - lowercased, spaces to hyphens. See Tags and bulk actions.

Reading a pass back

By our id or by yours - both work on the same route:

curl https://api-prod.getpocketpass.com/api/v1/passes/order-8891 \
  -H "Authorization: Bearer pk_live_..."

Listing

curl "https://api-prod.getpocketpass.com/api/v1/passes?page=1&perPage=100&status=active&groupTag=vip" \
  -H "Authorization: Bearer pk_live_..."

Filters: passTemplate, groupTag, status. Paging: page and perPage (max 200, default 50).

The total is in the X-Total-Count response header, not the body - read it from there to work out how many pages to fetch.

Updating

curl -X PATCH https://api-prod.getpocketpass.com/api/v1/passes/order-8891 \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "passContent": { "seat": { "value": "Row A, 4" } } }'

The pass in the customer's wallet updates by itself.

You can also PATCH with "passAction": "deactivate" or "reactivate" to turn a pass off and on. See Pass statuses.

Pushing a message while you update

Include a message in a PATCH and the update is pushed with a notification, so the change is announced rather than silent:

-d '{
  "passContent": { "seat": { "value": "Row A, 4" } },
  "message": "You have been upgraded to Row A, seat 4."
}'

The response carries an X-Notification-Status header telling you whether it was delivered.

To send a message without changing anything:

curl -X POST https://api-prod.getpocketpass.com/api/v1/passes/order-8891/notification \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "title": "Gate change", "message": "Your entrance is now Gate 3." }'

That's for one pass. To message many, use a notification campaign.

Voiding

curl -X DELETE https://api-prod.getpocketpass.com/api/v1/passes/order-8891 \
  -H "Authorization: Bearer pk_live_..."

DELETE does not delete. It voids the pass - the record stays and the copy in the wallet is marked void. It cannot be undone.

If you want something reversible, PATCH with "passAction": "deactivate" instead.

Templates over the API

You can create and update templates programmatically too, via /api/v1/pass-templates. Most teams design in the builder and only read templates over the API - programmatic creation earns its keep when you're provisioning many similar accounts.

Where to go next

More in Developers