Passmint
TemplatesDocsPricing
Log inGet started
Passmint
TemplatesDocsPricingTermsPrivacy

© 2026 Passmint. Built for indie makers.

Getting started

  • Overview
  • Quickstart

API

  • REST API reference
    • Authentication
    • Passes
    • Templates
    • Events
    • Webhooks
    • Errors
  • Webhooks
    • Event types
    • Creating a webhook
    • Payload format
    • Verifying signatures
    • Retries
  • Node.js SDK
    • Configuration
    • Passes
    • Templates
    • Webhook signatures
    • Errors
    • Idempotency

Open source

  • Passmint Package
REST API · v1

API reference.

Base URL: https://api.passmint.com

01

Authentication

Pass your API key as a Bearer token in the Authorization header. Test keys use the pmk_test_ prefix and live keys use pmk_live_. The mode (test or live) is determined by the key prefix.

Authorization: Bearer pmk_test_xxx
02

Idempotency

Send an Idempotency-Key header on POST and PATCH requests to safely retry without duplicating side effects. Replays within 24 hours return the cached response. Reusing a key with a different request body returns 409.

Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7
03

Response format

Single objects include an object field identifying the type. List endpoints wrap results in a standard envelope.

// Single object
{
  "object": "pass",
  "id": "pass_xxx",
  ...
}

// List
{
  "object": "list",
  "data": [...],
  "has_more": false
}
04

Errors

Errors return a consistent JSON envelope with a type, optional code, human-readable message, and the offending param when applicable.

{
  "error": {
    "type": "invalid_request_error",
    "code": null,
    "message": "template_id is required",
    "param": "template_id"
  }
}
TypeStatusDescription
authentication_error401Invalid or missing API key
invalid_request_error400Malformed or invalid request body
not_found_error404Resource does not exist
billing_error402Account billing issue
idempotency_error409Idempotency key reused with different body
api_error500Internal server error
05

Passes

Passes are the core resource — each represents a single wallet pass issued from a template.

POST/v1/passes

Issue a pass

Create a new pass from a template. Supports idempotency.

template_idstringRequired. The template to issue from.
holder_emailstringEmail address of the pass holder.
holder_namestringFull name of the pass holder.
field_valuesRecord<string, string>Key-value pairs for template fields.
metadataRecord<string, unknown>Arbitrary metadata to attach to the pass.
curl https://api.passmint.com/v1/passes \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "template_id": "tmpl_xxx",
    "holder_email": "alice@example.com",
    "holder_name": "Alice Johnson",
    "field_values": { "seatNumber": "A12" },
    "metadata": { "order_id": "ord_123" }
  }'
{
  "object": "pass",
  "id": "pass_xxx",
  "short_id": "abc123",
  "template_id": "tmpl_xxx",
  "serial_number": "...",
  "mode": "test",
  "holder_email": "alice@example.com",
  "holder_name": "Alice Johnson",
  "field_values": { "seatNumber": "A12" },
  "voided": false,
  "voided_at": null,
  "metadata": { "order_id": "ord_123" },
  "created_via_api": true,
  "url": "https://passmint.com/p/abc123",
  "download_url": "https://passmint.com/p/abc123/download",
  "created_at": "2026-04-16T12:00:00Z"
}
GET/v1/passes

List passes

Returns a paginated list of passes.

template_idstringFilter by template.
holder_emailstringFilter by holder email.
limitintegerNumber of results (default 50, max 100).
curl "https://api.passmint.com/v1/passes?template_id=tmpl_xxx&limit=10" \
  -H "Authorization: Bearer pmk_test_xxx"
{
  "object": "list",
  "data": [{ "object": "pass", "id": "pass_xxx", ... }],
  "has_more": false
}
GET/v1/passes/:id

Retrieve a pass

Returns a single pass by ID.

curl https://api.passmint.com/v1/passes/pass_xxx \
  -H "Authorization: Bearer pmk_test_xxx"
PATCH/v1/passes/:id

Update a pass

Update the field values or metadata on a pass. At least one of field_values or metadata is required. Cannot update voided passes (returns 400). Live updates are pushed to installed passes automatically. Supports idempotency.

field_valuesRecord<string, string>Updated field values.
metadataRecord<string, unknown>Updated metadata.
curl -X PATCH https://api.passmint.com/v1/passes/pass_xxx \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ "field_values": { "seatNumber": "B7" } }'
DELETE/v1/passes/:id

Void a pass

Voids a pass. The pass is not deleted — it is returned with voided: true and a voided_at timestamp.

curl -X DELETE https://api.passmint.com/v1/passes/pass_xxx \
  -H "Authorization: Bearer pmk_test_xxx"
{
  "object": "pass",
  "id": "pass_xxx",
  "voided": true,
  "voided_at": "2026-04-16T14:30:00Z",
  ...
}

Pass object

idstringUnique identifier (pass_xxx).
objectstringAlways "pass".
short_idstringShort URL slug.
template_idstringParent template (tmpl_xxx).
serial_numberstringUnique serial number for the pass.
modestring"test" or "live".
holder_emailstring | nullEmail of the pass holder.
holder_namestring | nullName of the pass holder.
field_valuesobjectKey-value pairs for template fields.
voidedbooleanWhether the pass has been voided.
voided_atstring | nullISO 8601 timestamp of when the pass was voided.
metadataobjectArbitrary metadata attached to the pass.
created_via_apibooleanWhether the pass was created via the API.
urlstringPublic URL for the pass landing page.
download_urlstringDirect download URL for the .pkpass file.
created_atstringISO 8601 creation timestamp.
06

Templates

Templates define the design and structure of your passes. Every pass is issued from a template.

POST/v1/templates

Create a template

Create a new pass template. Supports idempotency.

namestringRequired. Display name for the template.
typestringRequired. One of: event, membership, coupon, loyalty, generic.
apple_stylestringRequired. One of: eventTicket, generic, storeCard, coupon, boardingPass.
designobjectRequired. Design configuration for the template.
curl https://api.passmint.com/v1/templates \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "name": "VIP Concert Pass",
    "type": "event",
    "apple_style": "eventTicket",
    "design": { ... }
  }'
{
  "object": "template",
  "id": "tmpl_xxx",
  "name": "VIP Concert Pass",
  "type": "event",
  "apple_style": "eventTicket",
  "design": { ... },
  "archived": false,
  "created_at": "2026-04-16T12:00:00Z",
  "updated_at": "2026-04-16T12:00:00Z"
}
GET/v1/templates

List templates

Returns a list of non-archived templates.

limitintegerNumber of results (default 50, max 100).
curl "https://api.passmint.com/v1/templates?limit=10" \
  -H "Authorization: Bearer pmk_test_xxx"
GET/v1/templates/:id

Retrieve a template

Returns a single template by ID, including archived templates.

curl https://api.passmint.com/v1/templates/tmpl_xxx \
  -H "Authorization: Bearer pmk_test_xxx"
PATCH/v1/templates/:id

Update a template

Update a template's name, design, or archived status. All fields are optional.

namestringUpdated display name.
designobjectUpdated design configuration.
archivedbooleanSet to true to archive the template.
curl -X PATCH https://api.passmint.com/v1/templates/tmpl_xxx \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Updated Template Name" }'
DELETE/v1/templates/:id

Archive a template

Archives a template. Existing passes remain valid but no new passes can be issued from an archived template.

curl -X DELETE https://api.passmint.com/v1/templates/tmpl_xxx \
  -H "Authorization: Bearer pmk_test_xxx"
{
  "id": "tmpl_xxx",
  "deleted": true
}

Template object

idstringUnique identifier (tmpl_xxx).
objectstringAlways "template".
namestringDisplay name.
typestringOne of: event, membership, coupon, loyalty, generic.
apple_stylestringOne of: eventTicket, generic, storeCard, coupon, boardingPass.
designobjectDesign configuration.
archivedbooleanWhether the template is archived.
created_atstringISO 8601 creation timestamp.
updated_atstringISO 8601 last update timestamp.
07

Events

Events track the lifecycle of passes — from creation through installation and removal.

GET/v1/events

List recent events

Returns recent events across all passes.

limitintegerNumber of results (default 100, max 200).
curl "https://api.passmint.com/v1/events?limit=50" \
  -H "Authorization: Bearer pmk_test_xxx"
GET/v1/passes/:id/events

List events for a pass

Returns events for a specific pass.

limitintegerNumber of results (default 100, max 200).
curl "https://api.passmint.com/v1/passes/pass_xxx/events?limit=20" \
  -H "Authorization: Bearer pmk_test_xxx"
{
  "object": "list",
  "data": [
    {
      "object": "pass_event",
      "id": "evt_xxx",
      "pass_id": "pass_xxx",
      "type": "installed",
      "metadata": {},
      "created_at": "2026-04-16T13:00:00Z"
    }
  ],
  "has_more": false
}

PassEvent object

idstringUnique identifier (evt_xxx).
objectstringAlways "pass_event".
pass_idstringThe pass this event belongs to.
typestringEvent type (see below).
metadataobjectAdditional event data.
created_atstringISO 8601 timestamp.

Event types

TypeDescription
createdPass was created.
url_viewedPass landing page was viewed.
downloadedPass file was downloaded.
installedPass was added to a wallet.
updatedPass fields or metadata were updated.
removedPass was removed from a wallet.
voidedPass was voided.
08

Webhooks

Webhooks deliver real-time event notifications to your server. Passmint signs every payload so you can verify authenticity.

POST/v1/webhooks

Create a webhook

Register a new webhook endpoint. The response includes the secret field — this is the only time the secret is returned. Store it securely. Supports idempotency.

urlstringRequired. The URL to deliver events to.
eventsstring[]Required. Non-empty array of event types to subscribe to.
descriptionstringOptional description for the webhook.
enabledbooleanWhether the webhook is active (default true).

Valid event types: pass.created, pass.updated, pass.url_viewed, pass.downloaded, pass.installed, pass.removed, pass.voided, or * for all events.

curl https://api.passmint.com/v1/webhooks \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/passmint",
    "events": ["pass.created", "pass.installed"],
    "description": "Production webhook"
  }'
{
  "object": "webhook",
  "id": "whk_xxx",
  "url": "https://example.com/webhooks/passmint",
  "events": ["pass.created", "pass.installed"],
  "description": "Production webhook",
  "enabled": true,
  "secret": "whsec_xxx",
  "created_at": "2026-04-16T12:00:00Z"
}
GET/v1/webhooks

List webhooks

Returns all webhooks for your account.

curl https://api.passmint.com/v1/webhooks \
  -H "Authorization: Bearer pmk_test_xxx"
GET/v1/webhooks/:id

Retrieve a webhook

Returns a single webhook by ID. The secret field is not included in retrieval responses.

curl https://api.passmint.com/v1/webhooks/whk_xxx \
  -H "Authorization: Bearer pmk_test_xxx"
PATCH/v1/webhooks/:id

Update a webhook

Update a webhook's URL, subscribed events, description, or enabled status. All fields are optional.

urlstringUpdated delivery URL.
eventsstring[]Updated event subscriptions.
descriptionstringUpdated description.
enabledbooleanEnable or disable the webhook.
curl -X PATCH https://api.passmint.com/v1/webhooks/whk_xxx \
  -H "Authorization: Bearer pmk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "events": ["*"], "description": "All events" }'
DELETE/v1/webhooks/:id

Delete a webhook

Permanently deletes a webhook and its delivery history. This is a hard delete and cannot be undone.

curl -X DELETE https://api.passmint.com/v1/webhooks/whk_xxx \
  -H "Authorization: Bearer pmk_test_xxx"
{
  "id": "whk_xxx",
  "deleted": true
}
GET/v1/webhooks/:id/deliveries

List recent deliveries

Returns the last 100 delivery attempts for a webhook.

curl https://api.passmint.com/v1/webhooks/whk_xxx/deliveries \
  -H "Authorization: Bearer pmk_test_xxx"
{
  "object": "list",
  "data": [
    {
      "object": "webhook_delivery",
      "id": "whd_xxx",
      "webhook_id": "whk_xxx",
      "event_type": "pass.created",
      "status": "delivered",
      "attempts": 1,
      "last_attempt_at": "2026-04-16T12:01:00Z",
      "next_attempt_at": null,
      "response_status": 200,
      "response_body": "ok",
      "created_at": "2026-04-16T12:00:00Z"
    }
  ],
  "has_more": false
}

Webhook object

idstringUnique identifier (whk_xxx).
objectstringAlways "webhook".
urlstringDelivery URL.
eventsstring[]Subscribed event types.
descriptionstring | nullOptional description.
enabledbooleanWhether the webhook is active.
created_atstringISO 8601 creation timestamp.

WebhookDelivery object

idstringUnique identifier (whd_xxx).
objectstringAlways "webhook_delivery".
webhook_idstringParent webhook (whk_xxx).
event_typestringThe event type that triggered delivery.
statusstringOne of: pending, delivered, failed, dead.
attemptsintegerNumber of delivery attempts.
last_attempt_atstring | nullISO 8601 timestamp of last attempt.
next_attempt_atstring | nullISO 8601 timestamp of next retry.
response_statusinteger | nullHTTP status from your server.
response_bodystring | nullResponse body from your server.
created_atstringISO 8601 creation timestamp.