{"openapi":"3.1.0","info":{"title":"Passmint API","version":"1.0.0","description":"Issue and manage Apple Wallet and Google Wallet passes. All endpoints are authenticated with a secret API key."},"servers":[{"url":"https://api.passmint.com"}],"components":{"securitySchemes":{"scannerToken":{"type":"http","scheme":"bearer","description":"A scanner device token, obtained from POST /v1/scanners/pair."},"bearerAuth":{"type":"http","scheme":"bearer","description":"Your Passmint secret API key, e.g. `pmk_live_…` or `pmk_test_…`. Test keys never touch live data."}},"schemas":{"CreateTemplateBody":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string","enum":["event","membership","coupon","loyalty","generic"]},"apple_style":{"type":"string","enum":["generic","eventTicket","boardingPass","coupon","storeCard"]},"design":{"type":"object","properties":{"description":{"type":["string","null"]},"logoText":{"type":["string","null"]},"foregroundColor":{"type":"string","pattern":"^(rgb\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*\\)|#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)$"},"backgroundColor":{"type":"string","pattern":"^(rgb\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*\\)|#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)$"},"labelColor":{"type":"string","pattern":"^(rgb\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*\\)|#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)$"},"logoImageKey":{"type":["string","null"],"description":"Storage key from an image upload. Leave null to keep none."},"iconImageKey":{"type":["string","null"],"description":"Storage key from an image upload. Leave null to keep none."},"stripImageKey":{"type":["string","null"],"description":"Storage key from an image upload. Leave null to keep none."},"thumbnailImageKey":{"type":["string","null"],"description":"Storage key from an image upload. Leave null to keep none."},"headerFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"primaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"secondaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"auxiliaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"backFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"barcodeFormat":{"type":["string","null"],"enum":["PKBarcodeFormatQR","PKBarcodeFormatPDF417","PKBarcodeFormatAztec","PKBarcodeFormatCode128",null]},"barcodeMessageTemplate":{"type":["string","null"],"description":"What the barcode encodes. Use '{{serialNumber}}' — scanning looks passes up by serial number, and it is unique per pass. '{{fieldValues.<key>}}' inserts a field value. No other placeholders exist."},"issuerName":{"type":["string","null"],"maxLength":64,"description":"The issuer shown on the pass and in its notifications (Apple organizationName; Google issuer/program name unless logoText is set). Defaults to your organization's name."},"locations":{"type":["array","null"],"items":{"type":"object","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitude":{"type":"number"},"relevantText":{"type":"string","maxLength":256,"description":"Lock-screen text Apple Wallet shows near this location."}},"required":["latitude","longitude"]},"maxItems":10,"description":"Up to 10 places the pass is relevant near. Apple Wallet suggests the pass on the lock screen there; Google Wallet stores them on the pass."},"relevantDate":{"type":["string","null"],"pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})$","description":"ISO 8601 with offset. Apple Wallet surfaces the pass around this time. Apple only."},"google":{"type":["object","null"],"properties":{"loyaltyPoints":{"type":["object","null"],"properties":{"fieldKey":{"type":"string","maxLength":48,"pattern":"^[A-Za-z0-9_]+$","description":"Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text."},"label":{"type":"string","minLength":1,"maxLength":64,"description":"Shown next to the balance in Google Wallet, e.g. 'Stamps'."}},"required":["fieldKey","label"]},"secondaryLoyaltyPoints":{"type":["object","null"],"properties":{"fieldKey":{"type":"string","maxLength":48,"pattern":"^[A-Za-z0-9_]+$","description":"Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text."},"label":{"type":"string","minLength":1,"maxLength":64,"description":"Shown next to the balance in Google Wallet, e.g. 'Stamps'."}},"required":["fieldKey","label"]},"accountNameFieldKey":{"type":["string","null"],"maxLength":48,"pattern":"^[A-Za-z0-9_]+$","description":"Key of a field whose value is the card holder's name in Google Wallet. Omit to keep showing the description there, as cards always have."}},"description":"Google Wallet only, storeCard templates only: show template fields as the loyalty card's native balance and holder name. Apple Wallet is unaffected."}},"required":["foregroundColor","backgroundColor","labelColor"]},"platforms":{"type":"array","items":{"type":"string","enum":["apple","google"]}},"starter_template_id":{"type":"string"},"require_download_link":{"type":"boolean"},"redemption_policy":{"$ref":"#/components/schemas/RedemptionPolicyInput"}},"required":["name","type","apple_style","design"]},"RedemptionPolicyInput":{"type":"object","properties":{"mode":{"type":"string","enum":["single_use","reusable","count"]},"max_uses":{"type":"integer","minimum":1,"description":"Required when mode is count."}},"required":["mode"]},"UpdateTemplateBody":{"type":"object","properties":{"name":{"type":"string"},"design":{"type":"object","properties":{"description":{"type":["string","null"]},"logoText":{"type":["string","null"]},"foregroundColor":{"type":"string","pattern":"^(rgb\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*\\)|#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)$"},"backgroundColor":{"type":"string","pattern":"^(rgb\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*\\)|#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)$"},"labelColor":{"type":"string","pattern":"^(rgb\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*\\)|#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)$"},"logoImageKey":{"type":["string","null"],"description":"Storage key from an image upload. Leave null to keep none."},"iconImageKey":{"type":["string","null"],"description":"Storage key from an image upload. Leave null to keep none."},"stripImageKey":{"type":["string","null"],"description":"Storage key from an image upload. Leave null to keep none."},"thumbnailImageKey":{"type":["string","null"],"description":"Storage key from an image upload. Leave null to keep none."},"headerFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"primaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"secondaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"auxiliaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"backFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string","description":"Stable identifier for this field — the key you pass in field_values when issuing or updating a pass. Letters, numbers and underscores; unique across the design."},"label":{"type":["string","null"]},"defaultValue":{"type":["string","null"]},"textAlignment":{"type":["string","null"],"enum":["left","center","right","natural",null]},"required":{},"changeMessage":{"type":["string","null"],"description":"Apple Wallet lock-screen notification for this field, e.g. 'Your seat is now %@'. Must contain %@, which is replaced by the new value. This is the only way an update becomes visible to the holder."}},"required":["key"]}},"barcodeFormat":{"type":["string","null"],"enum":["PKBarcodeFormatQR","PKBarcodeFormatPDF417","PKBarcodeFormatAztec","PKBarcodeFormatCode128",null]},"barcodeMessageTemplate":{"type":["string","null"],"description":"What the barcode encodes. Use '{{serialNumber}}' — scanning looks passes up by serial number, and it is unique per pass. '{{fieldValues.<key>}}' inserts a field value. No other placeholders exist."},"issuerName":{"type":["string","null"],"maxLength":64,"description":"The issuer shown on the pass and in its notifications (Apple organizationName; Google issuer/program name unless logoText is set). Defaults to your organization's name."},"locations":{"type":["array","null"],"items":{"type":"object","properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"altitude":{"type":"number"},"relevantText":{"type":"string","maxLength":256,"description":"Lock-screen text Apple Wallet shows near this location."}},"required":["latitude","longitude"]},"maxItems":10,"description":"Up to 10 places the pass is relevant near. Apple Wallet suggests the pass on the lock screen there; Google Wallet stores them on the pass."},"relevantDate":{"type":["string","null"],"pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})$","description":"ISO 8601 with offset. Apple Wallet surfaces the pass around this time. Apple only."},"google":{"type":["object","null"],"properties":{"loyaltyPoints":{"type":["object","null"],"properties":{"fieldKey":{"type":"string","maxLength":48,"pattern":"^[A-Za-z0-9_]+$","description":"Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text."},"label":{"type":"string","minLength":1,"maxLength":64,"description":"Shown next to the balance in Google Wallet, e.g. 'Stamps'."}},"required":["fieldKey","label"]},"secondaryLoyaltyPoints":{"type":["object","null"],"properties":{"fieldKey":{"type":"string","maxLength":48,"pattern":"^[A-Za-z0-9_]+$","description":"Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text."},"label":{"type":"string","minLength":1,"maxLength":64,"description":"Shown next to the balance in Google Wallet, e.g. 'Stamps'."}},"required":["fieldKey","label"]},"accountNameFieldKey":{"type":["string","null"],"maxLength":48,"pattern":"^[A-Za-z0-9_]+$","description":"Key of a field whose value is the card holder's name in Google Wallet. Omit to keep showing the description there, as cards always have."}},"description":"Google Wallet only, storeCard templates only: show template fields as the loyalty card's native balance and holder name. Apple Wallet is unaffected."}},"required":["foregroundColor","backgroundColor","labelColor"]},"archived":{"type":"boolean"},"platforms":{"type":"array","items":{"type":"string","enum":["apple","google"]}},"certificate_set_id":{"type":["string","null"]},"google_issuer_id":{"type":["string","null"]},"require_download_link":{"type":"boolean"},"redemption_policy":{"$ref":"#/components/schemas/RedemptionPolicyInput"}}},"CreateWebhookBody":{"type":"object","properties":{"url":{"type":"string","description":"The HTTPS URL events are POSTed to.","example":"https://example.com/hooks/passmint"},"events":{"type":"array","items":{"type":"string"},"description":"Required, non-empty. Event types to deliver, or `*` for all pass events (template.republished must be subscribed by name).","example":["pass.redeemed"]},"description":{"type":["string","null"]},"enabled":{"type":"boolean","description":"Defaults to true."}},"required":["url","events"]},"UpdateWebhookBody":{"type":"object","properties":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"},"description":"Event types to deliver (for example `pass.redeemed`), or `*` for all pass events (template.republished must be subscribed by name).","example":["pass.redeemed"]},"description":{"type":["string","null"]},"enabled":{"type":"boolean"}}},"BackfillBody":{"type":"object","properties":{"since":{"type":"string","description":"ISO 8601 start of the window. Required.","example":"2026-10-01T00:00:00Z"},"until":{"type":"string","description":"ISO 8601 end of the window. Defaults to now. The window is capped in length."}},"required":["since"]},"PassIssuedEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.issued"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"}},"required":["pass"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"EventPassSnapshot":{"type":"object","properties":{"id":{"type":"string"},"short_id":{"type":"string"},"template_id":{"type":"string"},"organization_id":{"type":"string"},"serial_number":{"type":"string"},"holder":{"type":"object","properties":{"email_hash":{"type":["string","null"]},"name_present":{"type":"boolean"}},"required":["email_hash","name_present"]},"voided":{"type":"boolean"},"image_variant":{"type":["string","null"],"description":"The template image variant the pass renders with, or null for the template's own images."},"url":{"type":"string"},"download_url":{"type":["string","null"]},"google_wallet_url":{"type":["string","null"]}},"required":["id","short_id","template_id","organization_id","serial_number","holder","voided","image_variant","url","download_url","google_wallet_url"]},"PassAddIntentEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.add_intent"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"}},"required":["pass"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"PassAddedToWalletEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.added_to_wallet"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"}},"required":["pass"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"PassUpdatePushedEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.update_pushed"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"}},"required":["pass"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"PassUpdateDeliveredEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.update_delivered"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"}},"required":["pass"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"PassUpdateFailedEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.update_failed"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"},"delivery_failure":{"$ref":"#/components/schemas/EventDeliveryFailure"}},"required":["pass","delivery_failure"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"EventDeliveryFailure":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"reason":{"type":["string","null"]},"failed":{"type":["number","null"]},"devices":{"type":["number","null"]},"context":{"type":["string","null"],"enum":["update","void",null]}},"required":["platform","reason","failed","devices","context"],"description":"`data.object.delivery_failure`, present on `pass.update_failed`."},"PassRemovedEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.removed"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"}},"required":["pass"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"PassVoidedEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.voided"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"}},"required":["pass"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"PassRedeemedEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.redeemed"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"},"redemption":{"$ref":"#/components/schemas/EventRedemption"}},"required":["pass","redemption"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"EventRedemption":{"type":"object","properties":{"id":{"type":["string","null"]},"scanner_device_id":{"type":["string","null"]},"scans_used":{"type":["number","null"]},"policy_mode":{"type":["string","null"]}},"required":["id","scanner_device_id","scans_used","policy_mode"],"description":"`data.object.redemption`, present on `pass.redeemed`."},"TemplateRepublishedEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["template.republished"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"template_republish":{"$ref":"#/components/schemas/TemplateRepublish"}},"required":["template_republish"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"TemplateRepublish":{"type":"object","properties":{"object":{"type":"string","enum":["template_republish"]},"id":{"type":"string"},"template_id":{"type":"string"},"livemode":{"type":"boolean"},"status":{"type":"string","enum":["queued","running","completed"]},"google":{"type":"object","properties":{"status":{"type":"string","enum":["pending","synced","failed","skipped"],"description":"The Google Wallet class sync: one write that carries the issuer name, colour, logo and hero to every Google holder. `skipped`: no pass on this template has a Google object."},"error":{"type":["string","null"]},"objects":{"type":"object","properties":{"total":{"type":"integer"},"done":{"type":"integer"},"failed":{"type":"integer"}},"required":["total","done","failed"],"description":"Per-pass Google object updates. Zero when the change only touched the class (name, logo, hero)."}},"required":["status","error","objects"]},"apple":{"type":"object","properties":{"total":{"type":"integer"},"done":{"type":"integer"},"failed":{"type":"integer"}},"required":["total","done","failed"],"description":"Apple passes re-signed and pushed: those with an installed device, plus never-installed ones when the artwork changed."},"created_at":{"type":"string"},"completed_at":{"type":["string","null"]}},"required":["object","id","template_id","livemode","status","google","apple","created_at","completed_at"]},"ScannerPairing":{"type":"object","properties":{"object":{"type":"string","enum":["scanner_pairing"]},"token":{"type":"string"},"device":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"mode":{"type":"string","enum":["test","live"]},"template_id":{"type":["string","null"]}},"required":["id","name","mode","template_id"]},"setup":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"allow_override":{"type":"boolean"}},"required":["id","name","allow_override"]},"template_name":{"type":["string","null"]},"policy":{"type":["object","null"],"properties":{"mode":{"type":"string","enum":["single_use","reusable","count"]},"maxUses":{"type":"integer"}},"required":["mode"],"description":"The template's redemption policy when the scanner is scoped to one."}},"required":["object","token","device","setup","template_name","policy"]},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","enum":["authentication_error","authorization_error","invalid_request_error","not_found_error","rate_limit_error","idempotency_error","api_error","billing_error"]},"code":{"type":"string","description":"A stable, machine-readable code when the error has a specific cause. Not exhaustive: treat unknown codes as the generic error for the `type`. Codes include `api_key_expired` (401, the key's expiry has passed), `insufficient_scope` (403, the key's scopes do not allow this route), `invalid_limit` (400, `limit` is negative, fractional or non-numeric; 0 is valid and a limit over the maximum is clamped), `invalid_cursor` (400, `starting_after` is not an id on this list), `republish_in_progress` (429, too many template republishes running), `republish_unavailable` (503, try again shortly) and `plan_limit_exceeded` (402).","examples":["api_key_expired","insufficient_scope","invalid_limit","invalid_cursor"]},"message":{"type":"string"},"param":{"type":"string"}},"required":["type","message"]}},"required":["error"]},"ScanCodeRequest":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":512}},"required":["code"]},"ScanResult":{"type":"object","properties":{"object":{"type":"string","enum":["scan"]},"decision":{"type":"string","enum":["accepted","rejected"]},"reason":{"type":["string","null"],"enum":["already_redeemed","count_exhausted","voided","not_found","out_of_scope","wrong_mode","ambiguous","override",null],"description":"Why a scan was rejected, or `override` on an accepted scan an operator forced through. Null on a normal accept, and on an uploaded offline rejection the server would have accepted."},"client_scan_id":{"type":["string","null"]},"pass":{"type":["object","null"],"properties":{"id":{"type":"string"},"holder_name":{"type":["string","null"]},"template_name":{"type":"string"}},"required":["id","holder_name","template_name"]},"policy":{"type":["object","null"],"properties":{"mode":{"type":"string","enum":["single_use","reusable","count"]},"maxUses":{"type":"integer"}},"required":["mode"]},"scans_used":{"type":["integer","null"],"description":"Same as `redeemed_count`; kept for older scanner clients."},"redeemed_count":{"type":["integer","null"]},"max_uses":{"type":["integer","null"]},"first_redeemed_at":{"type":["string","null"]},"last_redemption":{"type":["object","null"],"properties":{"scanned_at":{"type":"string"},"device_name":{"type":["string","null"]}},"required":["scanned_at","device_name"],"description":"The pass's most recent accepted scan before this one."},"stats":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["checked_in"]},"checked_in":{"type":"integer"},"total":{"type":"integer"}},"required":["kind","checked_in","total"]},{"type":"object","properties":{"kind":{"type":"string","enum":["scans_today"]},"scans_today":{"type":"integer"}},"required":["kind","scans_today"]},{"type":"null"}]}},"required":["object","decision","reason","client_scan_id","pass","policy","scans_used","redeemed_count","max_uses","first_redeemed_at","last_redemption","stats"]},"ScanRequest":{"type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":512},"client_scan_id":{"type":["string","null"],"minLength":1,"maxLength":64,"description":"Client-generated id for this scan. A retry with the same id returns the original decision without counting again."},"override":{"type":["boolean","null"],"description":"Accept the scan past the pass's redemption policy. Honoured only when the device's setup allows overrides; a voided pass is never admitted."},"tz":{"type":["string","null"],"minLength":1,"maxLength":64,"description":"IANA time zone for the day boundary of `stats`."}},"required":["code"]},"ScannerDevice":{"type":"object","properties":{"object":{"type":"string","enum":["scanner_device"]},"id":{"type":"string"},"name":{"type":"string"}},"required":["object","id","name"]},"ScannerDeviceRenameRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60}},"required":["name"]},"ScannerStats":{"type":"object","properties":{"object":{"type":"string","enum":["scanner_stats"]},"stats":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["checked_in"]},"checked_in":{"type":"integer"},"total":{"type":"integer"}},"required":["kind","checked_in","total"]},{"type":"object","properties":{"kind":{"type":"string","enum":["scans_today"]},"scans_today":{"type":"integer"}},"required":["kind","scans_today"]}]}},"required":["object","stats"]},"ScannerHeartbeatRequest":{"type":"object","properties":{"queued":{"type":"integer","minimum":0,"maximum":1000000,"description":"Scans the app holds locally and has not yet uploaded."},"manifest_synced_at":{"type":["string","null"],"format":"date-time","description":"When the app last finished downloading the pass manifest."},"app_version":{"type":["string","null"],"minLength":1,"maxLength":32}},"required":["queued"]},"ScannerManifest":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/ScannerManifestPass"}},"next_cursor":{"type":["string","null"],"description":"Cursor of the last pass returned, even on the final page. Store it and send it to fetch only later changes."},"has_more":{"type":"boolean"},"total":{"type":"integer","description":"Passes in the device's scope on the first page; -1 when a cursor is sent."}},"required":["object","data","next_cursor","has_more","total"]},"ScannerManifestPass":{"type":"object","properties":{"id":{"type":"string"},"serial_number":{"type":"string"},"barcodes":{"type":"array","items":{"type":"string"},"description":"Every barcode value the pass has had, current and historical."},"holder_name":{"type":["string","null"]},"holder_email":{"type":["string","null"]},"template_id":{"type":"string"},"template_name":{"type":"string"},"policy":{"type":"object","properties":{"mode":{"type":"string","enum":["single_use","reusable","count"]},"maxUses":{"type":"integer"}},"required":["mode"]},"redeemed_count":{"type":"integer"},"first_redeemed_at":{"type":["string","null"]},"voided":{"type":"boolean"},"updated_at":{"type":"string"}},"required":["id","serial_number","barcodes","holder_name","holder_email","template_id","template_name","policy","redeemed_count","first_redeemed_at","voided","updated_at"]},"ScannerPassSearch":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/ScannerManifestPass"}}},"required":["object","data"]},"ScanBatch":{"type":"object","properties":{"object":{"type":"string","enum":["scan_batch"]},"results":{"type":"array","items":{"type":"object","properties":{"decision":{"type":"string","enum":["accepted","rejected"]},"reason":{"type":["string","null"],"enum":["already_redeemed","count_exhausted","voided","not_found","out_of_scope","wrong_mode","ambiguous","override",null],"description":"Why a scan was rejected, or `override` on an accepted scan an operator forced through. Null on a normal accept, and on an uploaded offline rejection the server would have accepted."},"client_scan_id":{"type":["string","null"]},"pass":{"type":["object","null"],"properties":{"id":{"type":"string"},"holder_name":{"type":["string","null"]},"template_name":{"type":"string"}},"required":["id","holder_name","template_name"]},"policy":{"type":["object","null"],"properties":{"mode":{"type":"string","enum":["single_use","reusable","count"]},"maxUses":{"type":"integer"}},"required":["mode"]},"scans_used":{"type":["integer","null"],"description":"Same as `redeemed_count`; kept for older scanner clients."},"redeemed_count":{"type":["integer","null"]},"max_uses":{"type":["integer","null"]},"first_redeemed_at":{"type":["string","null"]},"last_redemption":{"type":["object","null"],"properties":{"scanned_at":{"type":"string"},"device_name":{"type":["string","null"]}},"required":["scanned_at","device_name"],"description":"The pass's most recent accepted scan before this one."},"stats":{"oneOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["checked_in"]},"checked_in":{"type":"integer"},"total":{"type":"integer"}},"required":["kind","checked_in","total"]},{"type":"object","properties":{"kind":{"type":"string","enum":["scans_today"]},"scans_today":{"type":"integer"}},"required":["kind","scans_today"]},{"type":"null"}]}},"required":["decision","reason","client_scan_id","pass","policy","scans_used","redeemed_count","max_uses","first_redeemed_at","last_redemption","stats"]},"description":"One result per uploaded scan, in the order they were sent."}},"required":["object","results"]},"ScanBatchRequest":{"type":"object","properties":{"scans":{"type":"array","items":{"type":"object","properties":{"client_scan_id":{"type":"string","minLength":1,"maxLength":64,"description":"The id the scan was given when it was read. Re-uploading it returns the recorded result without counting again."},"code":{"type":"string","minLength":1,"maxLength":512},"scanned_at":{"type":"string","format":"date-time","description":"When the device scanned it. A time in the future is recorded as the upload time."},"offline_decision":{"type":"string","enum":["accepted","rejected"],"description":"What the device did at the door. An offline admit is always counted; a disagreement with the server is flagged, not undone."},"override":{"type":["boolean","null"],"description":"The operator forced the admit past the pass's redemption policy. Recorded only when the device's setup allows overrides."}},"required":["client_scan_id","code","scanned_at","offline_decision"]},"minItems":1,"maxItems":200}},"required":["scans"]},"Account":{"type":"object","properties":{"object":{"type":"string","enum":["account"]},"organization_id":{"type":"string"},"organization_name":{"type":"string"},"organization_slug":{"type":["string","null"]},"mode":{"type":"string","enum":["test","live"]},"plan":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]},"usage":{"type":"object","properties":{"period_start":{"type":["string","null"]},"api_calls":{"type":"object","properties":{"used":{"type":"integer"},"quota":{"type":["integer","null"]},"grace_ceiling":{"type":["integer","null"]}},"required":["used","quota","grace_ceiling"]},"active_passes":{"type":"object","properties":{"used":{"type":"integer"},"included":{"type":"integer"},"ceiling":{"type":"integer"}},"required":["used","included","ceiling"]}},"required":["period_start","api_calls","active_passes"],"description":"Live-mode usage in the current billing period (a rolling 30 days on plans without one). Pass issuance stops at api_calls.quota; other live writes continue to api_calls.grace_ceiling."},"credentials":{"type":"object","properties":{"apple_certificates":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"pass_type_identifier":{"type":["string","null"]},"status":{"type":"string","enum":["pending_certificate","active","revoked"]},"expires_at":{"type":["string","null"]}},"required":["id","name","pass_type_identifier","status","expires_at"]}},"google_issuers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"issuer_id":{"type":"string"},"status":{"type":"string","enum":["pending","active","revoked"]}},"required":["id","name","issuer_id","status"]}}},"required":["apple_certificates","google_issuers"],"description":"The organization's own signing credentials. Live passes are only signed with these, never with Passmint's shared test credentials."}},"required":["object","organization_id","organization_name","organization_slug","mode","plan","usage","credentials"]},"EventList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"has_more":{"type":"boolean"}},"required":["object","data","has_more"]},"Event":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["event"]},"type":{"type":"string","enum":["pass.issued","pass.add_intent","pass.added_to_wallet","pass.update_pushed","pass.update_delivered","pass.update_failed","pass.removed","pass.voided","pass.redeemed","template.republished"]},"api_version":{"type":"string"},"created_at":{"type":"string"},"idempotency_key":{"type":"string"},"livemode":{"type":"boolean"},"data":{"type":"object","properties":{"object":{"type":"object","properties":{"pass":{"$ref":"#/components/schemas/EventPassSnapshot"},"redemption":{"$ref":"#/components/schemas/EventRedemption"},"delivery_failure":{"$ref":"#/components/schemas/EventDeliveryFailure"}},"required":["pass"]}},"required":["object"]},"source":{"type":"object","properties":{"platform":{"type":["string","null"],"enum":["apple","google",null]},"unit":{"type":["string","null"],"enum":["device","object",null]},"confidence":{"type":"string","enum":["exact","best_effort","unconfirmed"]}},"required":["platform","unit","confidence"]},"previous_attributes":{"type":"null"}},"required":["id","object","type","api_version","created_at","idempotency_key","livemode","data","source","previous_attributes"]},"Funnel":{"type":"object","properties":{"object":{"type":"string","enum":["funnel"]},"group_by":{"type":"string","enum":["total","template","platform","date","mode"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/FunnelSummary"}},"confidence":{"$ref":"#/components/schemas/FunnelConfidence"}},"required":["object","group_by","data","confidence"]},"FunnelSummary":{"type":"object","properties":{"key":{"type":"string"},"issued":{"type":"number"},"add_intent":{"type":"number"},"added":{"type":"number"},"active":{"type":"number"},"removed":{"type":"number"},"update_pushed":{"type":"number"},"update_delivered":{"type":"number"},"install_rate":{"type":["number","null"]},"removal_rate":{"type":["number","null"]},"update_delivery_rate":{"type":["number","null"]}},"required":["key","issued","add_intent","added","active","removed","update_pushed","update_delivered","install_rate","removal_rate","update_delivery_rate"]},"FunnelConfidence":{"type":"object","properties":{"removed":{"type":"string"},"update_delivery_rate":{"type":"string"},"active":{"type":"string"}},"required":["removed","update_delivery_rate","active"]},"TemplateList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Template"}},"has_more":{"type":"boolean"}},"required":["object","data","has_more"]},"Template":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["template"]},"name":{"type":"string"},"type":{"type":"string"},"apple_style":{"type":"string"},"starter_template_id":{"type":["string","null"]},"design":{"$ref":"#/components/schemas/TemplateDesign"},"archived":{"type":"boolean"},"platforms":{"type":"array","items":{"type":"string","enum":["apple","google"]}},"certificate_set_id":{"type":["string","null"]},"google_issuer_id":{"type":["string","null"]},"require_download_link":{"type":"boolean"},"redemption_policy":{"$ref":"#/components/schemas/RedemptionPolicy"},"warnings":{"type":"array","items":{"type":"string"},"description":"Present only when the saved design breaks a recommended rule (an Apple field limit, a duplicate field key, an unknown barcode placeholder, an image the pass style cannot show). The template is saved; fix these before they surprise you at issuance."},"image_variants":{"type":"array","items":{"type":"string"},"description":"The template's image variant names that hold at least one image, sorted. A pass selects one with `image_variant`.","example":["0","1","2","reward"]},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","object","name","type","apple_style","starter_template_id","design","archived","platforms","certificate_set_id","google_issuer_id","require_download_link","redemption_policy","image_variants","created_at","updated_at"]},"TemplateDesign":{"type":"object","properties":{"description":{"type":["string","null"]},"logoText":{"anyOf":[{"type":"string"},{"type":"object","properties":{"default":{"type":"string"},"translations":{"type":"object","additionalProperties":{"type":"string"}}},"required":["default"]},{"type":"null"}]},"foregroundColor":{"type":"string"},"backgroundColor":{"type":"string"},"labelColor":{"type":"string"},"headerFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"label":{"anyOf":[{"type":"string"},{"type":"object","properties":{"default":{"type":"string"},"translations":{"type":"object","additionalProperties":{"type":"string"}}},"required":["default"]},{"type":"null"}]},"defaultValue":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}]},"textAlignment":{"type":"string"},"changeMessage":{"type":["string","null"]}},"required":["key"],"additionalProperties":{}}},"primaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"label":{"anyOf":[{"type":"string"},{"type":"object","properties":{"default":{"type":"string"},"translations":{"type":"object","additionalProperties":{"type":"string"}}},"required":["default"]},{"type":"null"}]},"defaultValue":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}]},"textAlignment":{"type":"string"},"changeMessage":{"type":["string","null"]}},"required":["key"],"additionalProperties":{}}},"secondaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"label":{"anyOf":[{"type":"string"},{"type":"object","properties":{"default":{"type":"string"},"translations":{"type":"object","additionalProperties":{"type":"string"}}},"required":["default"]},{"type":"null"}]},"defaultValue":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}]},"textAlignment":{"type":"string"},"changeMessage":{"type":["string","null"]}},"required":["key"],"additionalProperties":{}}},"auxiliaryFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"label":{"anyOf":[{"type":"string"},{"type":"object","properties":{"default":{"type":"string"},"translations":{"type":"object","additionalProperties":{"type":"string"}}},"required":["default"]},{"type":"null"}]},"defaultValue":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}]},"textAlignment":{"type":"string"},"changeMessage":{"type":["string","null"]}},"required":["key"],"additionalProperties":{}}},"backFields":{"type":["array","null"],"items":{"type":"object","properties":{"key":{"type":"string"},"label":{"anyOf":[{"type":"string"},{"type":"object","properties":{"default":{"type":"string"},"translations":{"type":"object","additionalProperties":{"type":"string"}}},"required":["default"]},{"type":"null"}]},"defaultValue":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}]},"textAlignment":{"type":"string"},"changeMessage":{"type":["string","null"]}},"required":["key"],"additionalProperties":{}}},"barcodeFormat":{"type":["string","null"]},"barcodeMessageTemplate":{"type":["string","null"]},"issuerName":{"type":["string","null"]},"locations":{"type":["array","null"],"items":{"type":"object","additionalProperties":{}}},"relevantDate":{"type":["string","null"]},"google":{"type":["object","null"],"properties":{"loyaltyPoints":{"type":["object","null"],"properties":{"fieldKey":{"type":"string"},"label":{"type":"string"}},"required":["fieldKey","label"]},"secondaryLoyaltyPoints":{"type":["object","null"],"properties":{"fieldKey":{"type":"string"},"label":{"type":"string"}},"required":["fieldKey","label"]},"accountNameFieldKey":{"type":["string","null"]}},"additionalProperties":{}}},"additionalProperties":{},"description":"The template's design as stored. See CreateTemplateBody.design for the write contract."},"RedemptionPolicy":{"type":"object","properties":{"mode":{"type":"string","enum":["single_use","reusable","count"]},"maxUses":{"type":"integer"}},"required":["mode"]},"DeletedTemplate":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","enum":[true]}},"required":["id","deleted"]},"TemplateImage":{"type":"object","properties":{"object":{"type":"string","enum":["template_image"]},"template_id":{"type":"string"},"slot":{"type":"string"},"variant":{"type":["string","null"]}},"required":["object","template_id","slot","variant"]},"DeletedTemplateImage":{"allOf":[{"$ref":"#/components/schemas/TemplateImage"},{"type":"object","properties":{"deleted":{"type":"boolean","enum":[true]}},"required":["deleted"]}]},"WebhookList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}},"has_more":{"type":"boolean"}},"required":["object","data","has_more"]},"Webhook":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["webhook"]},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"secret":{"type":"string"},"created_at":{"type":"string"}},"required":["id","object","url","events","description","enabled","created_at"]},"DeletedWebhook":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","enum":[true]}},"required":["id","deleted"]},"WebhookDeliveryList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"has_more":{"type":"boolean"}},"required":["object","data","has_more"]},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["webhook_delivery"]},"webhook_id":{"type":"string"},"event_type":{"type":"string"},"status":{"type":"string"},"attempts":{"type":"number"},"last_attempt_at":{"type":["string","null"]},"next_attempt_at":{"type":["string","null"]},"response_status":{"type":["number","null"]},"response_body":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","object","webhook_id","event_type","status","attempts","last_attempt_at","next_attempt_at","response_status","response_body","created_at"]},"WebhookBackfill":{"type":"object","properties":{"object":{"type":"string","enum":["backfill"]},"enqueued":{"type":"number"},"capped":{"type":"boolean"},"window":{"type":"object","properties":{"since":{"type":"string"},"until":{"type":"string"}},"required":["since","until"]}},"required":["object","enqueued","capped","window"]},"PassList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Pass"}},"has_more":{"type":"boolean"}},"required":["object","data","has_more"]},"Pass":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["pass"]},"short_id":{"type":"string"},"template_id":{"type":"string"},"certificate_set_id":{"type":["string","null"]},"serial_number":{"type":"string"},"mode":{"type":"string"},"holder_email":{"type":["string","null"]},"holder_name":{"type":["string","null"]},"field_values":{"type":"object","additionalProperties":{},"description":"The pass's field values by field key. Normally strings; any JSON value sent is stored and returned as-is."},"voided":{"type":"boolean"},"voided_at":{"type":["string","null"]},"redeemed_count":{"type":"integer"},"first_redeemed_at":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{},"description":"Free-form key/value data you attached to the pass, or null."},"image_variant":{"type":["string","null"],"description":"The template image variant this pass renders with, or null for the template's own images."},"images":{"type":"object","additionalProperties":{"type":"object","properties":{"source":{"type":"string","enum":["pass","variant","template"]}},"required":["source"]},"description":"Every image slot the pass renders, keyed by Apple slot name, with the layer it comes from: `pass` (this pass's own image, `PUT /v1/passes/{id}/images/{slot}`), `variant` (its `image_variant`) or `template`. Carries no URLs.","example":{"icon":{"source":"template"},"logo":{"source":"template"},"thumbnail":{"source":"pass"}}},"created_via_api":{"type":"boolean"},"platforms":{"type":"array","items":{"type":"string","enum":["apple","google"]},"description":"The wallets this pass was issued for."},"platform_status":{"type":["object","null"],"properties":{"apple":{"type":"string","enum":["delivered","skipped_no_credential","failed"]},"google":{"type":"string","enum":["delivered","skipped_no_credential","failed"]}},"description":"Per-wallet delivery outcome. A wallet is absent when the pass was not issued for it."},"url":{"type":"string"},"download_url":{"type":["string","null"]},"google_wallet_url":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","object","short_id","template_id","certificate_set_id","serial_number","mode","holder_email","holder_name","field_values","voided","voided_at","redeemed_count","first_redeemed_at","metadata","image_variant","images","created_via_api","platforms","platform_status","url","download_url","google_wallet_url","created_at"]},"PassCreateResponse":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["pass"]},"short_id":{"type":"string"},"template_id":{"type":"string"},"certificate_set_id":{"type":["string","null"]},"serial_number":{"type":"string"},"mode":{"type":"string"},"holder_email":{"type":["string","null"]},"holder_name":{"type":["string","null"]},"field_values":{"type":"object","additionalProperties":{},"description":"The pass's field values by field key. Normally strings; any JSON value sent is stored and returned as-is."},"voided":{"type":"boolean"},"voided_at":{"type":["string","null"]},"redeemed_count":{"type":"integer"},"first_redeemed_at":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{},"description":"Free-form key/value data you attached to the pass, or null."},"image_variant":{"type":["string","null"],"description":"The template image variant this pass renders with, or null for the template's own images."},"images":{"type":"object","additionalProperties":{"type":"object","properties":{"source":{"type":"string","enum":["pass","variant","template"]}},"required":["source"]},"description":"Every image slot the pass renders, keyed by Apple slot name, with the layer it comes from: `pass` (this pass's own image, `PUT /v1/passes/{id}/images/{slot}`), `variant` (its `image_variant`) or `template`. Carries no URLs.","example":{"icon":{"source":"template"},"logo":{"source":"template"},"thumbnail":{"source":"pass"}}},"created_via_api":{"type":"boolean"},"platforms":{"type":"array","items":{"type":"string","enum":["apple","google"]},"description":"The wallets this pass was issued for."},"platform_status":{"type":["object","null"],"properties":{"apple":{"type":"string","enum":["delivered","skipped_no_credential","failed"]},"google":{"type":"string","enum":["delivered","skipped_no_credential","failed"]}},"description":"Per-wallet delivery outcome. A wallet is absent when the pass was not issued for it."},"url":{"type":"string"},"download_url":{"type":["string","null"]},"google_wallet_url":{"type":["string","null"]},"created_at":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}}},"required":["id","object","short_id","template_id","certificate_set_id","serial_number","mode","holder_email","holder_name","field_values","voided","voided_at","redeemed_count","first_redeemed_at","metadata","image_variant","images","created_via_api","platforms","platform_status","url","download_url","google_wallet_url","created_at","warnings"]},"PassUpdateResponse":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["pass"]},"short_id":{"type":"string"},"template_id":{"type":"string"},"certificate_set_id":{"type":["string","null"]},"serial_number":{"type":"string"},"mode":{"type":"string"},"holder_email":{"type":["string","null"]},"holder_name":{"type":["string","null"]},"field_values":{"type":"object","additionalProperties":{},"description":"The pass's field values by field key. Normally strings; any JSON value sent is stored and returned as-is."},"voided":{"type":"boolean"},"voided_at":{"type":["string","null"]},"redeemed_count":{"type":"integer"},"first_redeemed_at":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{},"description":"Free-form key/value data you attached to the pass, or null."},"image_variant":{"type":["string","null"],"description":"The template image variant this pass renders with, or null for the template's own images."},"images":{"type":"object","additionalProperties":{"type":"object","properties":{"source":{"type":"string","enum":["pass","variant","template"]}},"required":["source"]},"description":"Every image slot the pass renders, keyed by Apple slot name, with the layer it comes from: `pass` (this pass's own image, `PUT /v1/passes/{id}/images/{slot}`), `variant` (its `image_variant`) or `template`. Carries no URLs.","example":{"icon":{"source":"template"},"logo":{"source":"template"},"thumbnail":{"source":"pass"}}},"created_via_api":{"type":"boolean"},"platforms":{"type":"array","items":{"type":"string","enum":["apple","google"]},"description":"The wallets this pass was issued for."},"platform_status":{"type":["object","null"],"properties":{"apple":{"type":"string","enum":["delivered","skipped_no_credential","failed"]},"google":{"type":"string","enum":["delivered","skipped_no_credential","failed"]}},"description":"Per-wallet delivery outcome. A wallet is absent when the pass was not issued for it."},"url":{"type":"string"},"download_url":{"type":["string","null"]},"google_wallet_url":{"type":["string","null"]},"created_at":{"type":"string"},"delivery":{"$ref":"#/components/schemas/PassDelivery"},"warnings":{"type":"array","items":{"type":"string"}}},"required":["id","object","short_id","template_id","certificate_set_id","serial_number","mode","holder_email","holder_name","field_values","voided","voided_at","redeemed_count","first_redeemed_at","metadata","image_variant","images","created_via_api","platforms","platform_status","url","download_url","google_wallet_url","created_at","delivery","warnings"]},"PassDelivery":{"type":"object","properties":{"apple":{"type":["object","null"],"properties":{"devices":{"type":"integer"},"pushed":{"type":"integer"},"failed":{"type":"integer"},"unregistered":{"type":"integer"},"retrying":{"type":"boolean","description":"Present and true when some pushes failed for a reason that may clear (Apple busy or unreachable) and Passmint queued an automatic retry. Absent otherwise."}},"required":["devices","pushed","failed","unregistered"],"description":"Null when the pass was not delivered to Apple Wallet. `failed` excludes dead tokens (`unregistered`), which mean the holder deleted the pass."},"google":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["updated","not_saved","failed","skipped"]},"error":{"type":"string"},"retrying":{"type":"boolean","description":"Present and true when the Google update failed for a reason that may clear (a Google 5xx, 409 or 429, or a network error) and Passmint queued an automatic retry."}},"required":["status"],"description":"Null when the pass has no Google Wallet object. `not_saved`: no holder has saved it yet. `skipped`: Google delivery was skipped at issue."}},"required":["apple","google"]},"PassVoidResponse":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["pass"]},"short_id":{"type":"string"},"template_id":{"type":"string"},"certificate_set_id":{"type":["string","null"]},"serial_number":{"type":"string"},"mode":{"type":"string"},"holder_email":{"type":["string","null"]},"holder_name":{"type":["string","null"]},"field_values":{"type":"object","additionalProperties":{},"description":"The pass's field values by field key. Normally strings; any JSON value sent is stored and returned as-is."},"voided":{"type":"boolean"},"voided_at":{"type":["string","null"]},"redeemed_count":{"type":"integer"},"first_redeemed_at":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{},"description":"Free-form key/value data you attached to the pass, or null."},"image_variant":{"type":["string","null"],"description":"The template image variant this pass renders with, or null for the template's own images."},"images":{"type":"object","additionalProperties":{"type":"object","properties":{"source":{"type":"string","enum":["pass","variant","template"]}},"required":["source"]},"description":"Every image slot the pass renders, keyed by Apple slot name, with the layer it comes from: `pass` (this pass's own image, `PUT /v1/passes/{id}/images/{slot}`), `variant` (its `image_variant`) or `template`. Carries no URLs.","example":{"icon":{"source":"template"},"logo":{"source":"template"},"thumbnail":{"source":"pass"}}},"created_via_api":{"type":"boolean"},"platforms":{"type":"array","items":{"type":"string","enum":["apple","google"]},"description":"The wallets this pass was issued for."},"platform_status":{"type":["object","null"],"properties":{"apple":{"type":"string","enum":["delivered","skipped_no_credential","failed"]},"google":{"type":"string","enum":["delivered","skipped_no_credential","failed"]}},"description":"Per-wallet delivery outcome. A wallet is absent when the pass was not issued for it."},"url":{"type":"string"},"download_url":{"type":["string","null"]},"google_wallet_url":{"type":["string","null"]},"created_at":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}}},"required":["id","object","short_id","template_id","certificate_set_id","serial_number","mode","holder_email","holder_name","field_values","voided","voided_at","redeemed_count","first_redeemed_at","metadata","image_variant","images","created_via_api","platforms","platform_status","url","download_url","google_wallet_url","created_at","warnings"]},"PassEventList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/PassEvent"}},"has_more":{"type":"boolean"}},"required":["object","data","has_more"]},"PassEvent":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["pass_event"]},"pass_id":{"type":"string"},"type":{"type":"string"},"metadata":{"type":["object","null"],"additionalProperties":{},"description":"Event-specific detail, such as the platform or a redemption's scanner. Shape varies by `type`; null when the event carries none."},"created_at":{"type":"string"}},"required":["id","object","pass_id","type","metadata","created_at"]},"RedemptionList":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Redemption"}},"has_more":{"type":"boolean"}},"required":["object","data","has_more"]},"Redemption":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["redemption"]},"decision":{"type":"string","enum":["accepted","rejected"]},"reason":{"type":["string","null"],"enum":["already_redeemed","count_exhausted","voided","not_found","out_of_scope","wrong_mode","ambiguous","override",null]},"scanner_name":{"type":["string","null"]},"scanned_at":{"type":"string"}},"required":["id","object","decision","reason","scanner_name","scanned_at"]},"PassDownloadLink":{"type":"object","properties":{"object":{"type":"string","enum":["pass.download_link"]},"pass_id":{"type":"string"},"url":{"type":"string"},"expires_in":{"type":"number"},"expires_at":{"type":"string"},"created_at":{"type":"string"}},"required":["object","pass_id","url","expires_in","expires_at","created_at"]},"PassImageResponse":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["pass"]},"short_id":{"type":"string"},"template_id":{"type":"string"},"certificate_set_id":{"type":["string","null"]},"serial_number":{"type":"string"},"mode":{"type":"string"},"holder_email":{"type":["string","null"]},"holder_name":{"type":["string","null"]},"field_values":{"type":"object","additionalProperties":{},"description":"The pass's field values by field key. Normally strings; any JSON value sent is stored and returned as-is."},"voided":{"type":"boolean"},"voided_at":{"type":["string","null"]},"redeemed_count":{"type":"integer"},"first_redeemed_at":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":{},"description":"Free-form key/value data you attached to the pass, or null."},"image_variant":{"type":["string","null"],"description":"The template image variant this pass renders with, or null for the template's own images."},"images":{"type":"object","additionalProperties":{"type":"object","properties":{"source":{"type":"string","enum":["pass","variant","template"]}},"required":["source"]},"description":"Every image slot the pass renders, keyed by Apple slot name, with the layer it comes from: `pass` (this pass's own image, `PUT /v1/passes/{id}/images/{slot}`), `variant` (its `image_variant`) or `template`. Carries no URLs.","example":{"icon":{"source":"template"},"logo":{"source":"template"},"thumbnail":{"source":"pass"}}},"created_via_api":{"type":"boolean"},"platforms":{"type":"array","items":{"type":"string","enum":["apple","google"]},"description":"The wallets this pass was issued for."},"platform_status":{"type":["object","null"],"properties":{"apple":{"type":"string","enum":["delivered","skipped_no_credential","failed"]},"google":{"type":"string","enum":["delivered","skipped_no_credential","failed"]}},"description":"Per-wallet delivery outcome. A wallet is absent when the pass was not issued for it."},"url":{"type":"string"},"download_url":{"type":["string","null"]},"google_wallet_url":{"type":["string","null"]},"created_at":{"type":"string"},"warnings":{"type":"array","items":{"type":"string"}}},"required":["id","object","short_id","template_id","certificate_set_id","serial_number","mode","holder_email","holder_name","field_values","voided","voided_at","redeemed_count","first_redeemed_at","metadata","image_variant","images","created_via_api","platforms","platform_status","url","download_url","google_wallet_url","created_at","warnings"]}},"parameters":{}},"paths":{"/v1/scanners/pair":{"post":{"tags":["Scanning"],"summary":"Exchange a pairing code for a scanner token","description":"Unauthenticated: the single-use pairing code is the credential. Rate limited by client IP.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanCodeRequest"}}}},"responses":{"200":{"description":"The scanner token, shown once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScannerPairing"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/scan":{"post":{"tags":["Scanning"],"summary":"Scan a pass barcode","description":"A well-formed scan is always HTTP 200; the accept/reject outcome is in the body.","security":[{"scannerToken":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanRequest"}}}},"responses":{"200":{"description":"The scan outcome","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/scanner/device":{"patch":{"tags":["Scanning"],"summary":"Rename this scanner device","security":[{"scannerToken":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScannerDeviceRenameRequest"}}}},"responses":{"200":{"description":"The renamed device","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScannerDevice"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/scanner/stats":{"get":{"tags":["Scanning"],"summary":"The scanner's door counter","description":"`checked_in` of `total` for a device scoped to a single-use template, otherwise the scans accepted today in the device's scope.","security":[{"scannerToken":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":64,"description":"IANA time zone for the day boundary. Invalid or absent means UTC."},"required":false,"description":"IANA time zone for the day boundary. Invalid or absent means UTC.","name":"tz","in":"query"}],"responses":{"200":{"description":"The counter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScannerStats"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/scanner/heartbeat":{"post":{"tags":["Scanning"],"summary":"Report that this scanner is online","description":"Sent about every 30 seconds. Shows the device as online, with its upload queue, on the dashboard.","security":[{"scannerToken":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScannerHeartbeatRequest"}}}},"responses":{"204":{"description":"Recorded"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/scanner/manifest":{"get":{"tags":["Scanning"],"summary":"Download the passes this scanner can validate offline","description":"Pages through the passes in the device's scope in (updated_at, id) order, voided ones included. Send the previous `next_cursor` to receive only passes changed since. Rate limited separately from scanning.","security":[{"scannerToken":[]}],"parameters":[{"schema":{"type":"string","maxLength":512},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","description":"Page size, default 1000, at most 2000."},"required":false,"description":"Page size, default 1000, at most 2000.","name":"limit","in":"query"}],"responses":{"200":{"description":"A page of the manifest","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScannerManifest"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/scanner/passes":{"get":{"tags":["Scanning"],"summary":"Search passes in this scanner's scope","description":"For devices without a local list. Matches the holder name or any word of it, or the holder email, by prefix, or the serial number exactly. At most 50 results.","security":[{"scannerToken":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"q","in":"query"}],"responses":{"200":{"description":"Matching passes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScannerPassSearch"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/scans/batch":{"post":{"tags":["Scanning"],"summary":"Upload scans made offline","description":"Records up to 200 queued offline scans, in order. Idempotent per `client_scan_id`. A well-formed batch is always HTTP 200; one invalid item rejects the whole batch with a 400 naming it (`scans.N.field`).","security":[{"scannerToken":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanBatchRequest"}}}},"responses":{"200":{"description":"The recorded outcome of each scan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanBatch"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me":{"get":{"tags":["Account"],"summary":"Retrieve the authenticated account","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The organization the API key belongs to","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/events":{"get":{"tags":["Events"],"summary":"List events","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"type","in":"query"},{"schema":{"type":"string"},"required":false,"name":"pass_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"template_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"since","in":"query"},{"schema":{"type":"string"},"required":false,"name":"until","in":"query"},{"schema":{"type":"string"},"required":false,"name":"starting_after","in":"query"},{"schema":{"type":["number","null"]},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"A list of canonical events, most recent first","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/metrics/funnel":{"get":{"tags":["Metrics"],"summary":"Retrieve the pass funnel","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"template_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"platform","in":"query"},{"schema":{"type":"string"},"required":false,"name":"since","in":"query"},{"schema":{"type":"string"},"required":false,"name":"until","in":"query"},{"schema":{"type":"string"},"required":false,"name":"group_by","in":"query"}],"responses":{"200":{"description":"Funnel metrics for the authenticated organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Funnel"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/templates":{"get":{"tags":["Templates"],"summary":"List templates","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"Include archived templates. Defaults to false."},"required":false,"description":"Include archived templates. Defaults to false.","name":"include_archived","in":"query"},{"schema":{"type":"string","description":"Return items after this template id (the last item of the previous page)."},"required":false,"description":"Return items after this template id (the last item of the previous page).","name":"starting_after","in":"query"}],"responses":{"200":{"description":"A list of the organization's templates — active only, unless include_archived=true","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Templates"],"summary":"Create a template","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateBody"}}}},"responses":{"201":{"description":"The created template","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/templates/{id}":{"get":{"tags":["Templates"],"summary":"Retrieve a template","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The requested template","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Templates"],"summary":"Update a template","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTemplateBody"}}}},"responses":{"200":{"description":"The updated template","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Template"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Templates"],"summary":"Archive a template","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The template was archived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedTemplate"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/templates/{id}/images/{slot}":{"put":{"tags":["Templates"],"summary":"Upload a template image","description":"Writes one image slot of the template — or, with `variant`, of one of its image variants. Passes pick up a change the next time they are issued or updated.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"An Apple image slot the template's style has: icon, logo, strip, thumbnail, background or footer (generic: icon, logo, thumbnail; storeCard and coupon: icon, logo, strip; eventTicket: icon, logo, strip, thumbnail, background; boardingPass: icon, logo, footer). With a variant, only the style's strip, thumbnail or background.","example":"strip"},"required":true,"description":"An Apple image slot the template's style has: icon, logo, strip, thumbnail, background or footer (generic: icon, logo, thumbnail; storeCard and coupon: icon, logo, strip; eventTicket: icon, logo, strip, thumbnail, background; boardingPass: icon, logo, footer). With a variant, only the style's strip, thumbnail or background.","name":"slot","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"The image, base64-encoded: PNG or JPEG (WebP is also accepted). Any resolution — it is resized to the slot's 1x and @2x sizes. 8 MB limit."},"variant":{"type":["string","null"],"description":"Write this image variant's copy of the slot instead of the template's own. 1-32 characters: lowercase letters, digits, - and _, starting with a letter or digit.","example":"3"}}}}}},"responses":{"200":{"description":"The image was stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateImage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Templates"],"summary":"Delete a template image","description":"Removes one image slot of the template — or, with `?variant=`, of one of its image variants. A variant with no images left no longer appears in the template's `image_variants`. Any slot can be removed, including one the template's style does not use.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"An Apple image slot the template's style has: icon, logo, strip, thumbnail, background or footer (generic: icon, logo, thumbnail; storeCard and coupon: icon, logo, strip; eventTicket: icon, logo, strip, thumbnail, background; boardingPass: icon, logo, footer). With a variant, only the style's strip, thumbnail or background.","example":"strip"},"required":true,"description":"An Apple image slot the template's style has: icon, logo, strip, thumbnail, background or footer (generic: icon, logo, thumbnail; storeCard and coupon: icon, logo, strip; eventTicket: icon, logo, strip, thumbnail, background; boardingPass: icon, logo, footer). With a variant, only the style's strip, thumbnail or background.","name":"slot","in":"path"},{"schema":{"type":"string","description":"Remove this image variant's copy of the slot. Omit it to remove the template's own."},"required":false,"description":"Remove this image variant's copy of the slot. Omit it to remove the template's own.","name":"variant","in":"query"}],"responses":{"200":{"description":"The image was removed (or was already absent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedTemplateImage"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/templates/{id}/republish":{"post":{"tags":["Templates"],"summary":"Push template changes to issued passes","description":"Publishes the template's current design to the passes already issued from it, in this key's mode. Google Wallet gets one class update (issuer name, logo, hero) plus per-pass object updates when fields, colours or the barcode changed; Apple Wallet passes with an installed device are re-signed and pushed. Saving a template never does this on its own — call it once your edits are done. Returns 202 with the new republish, or 200 with the one already running; in that case another runs when it finishes, so the latest design reaches every pass. Archived templates can be republished too: their passes are still in wallets.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"A republish of this template was already running; it is returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateRepublish"}}}},"202":{"description":"The republish was queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateRepublish"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/templates/{id}/republishes/{rid}":{"get":{"tags":["Templates"],"summary":"Retrieve a template republish","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"rid","in":"path"}],"responses":{"200":{"description":"The republish, with live counts while it runs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateRepublish"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints","description":"Every endpoint, newest first. Send limit or starting_after to page instead.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"100"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Return items after this id (the last item of the previous page)."},"required":false,"description":"Return items after this id (the last item of the previous page).","name":"starting_after","in":"query"}],"responses":{"200":{"description":"The organization's webhook endpoints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook endpoint","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookBody"}}}},"responses":{"201":{"description":"The created endpoint, including its signing secret (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}":{"get":{"tags":["Webhooks"],"summary":"Retrieve a webhook endpoint","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The webhook endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Webhooks"],"summary":"Update a webhook endpoint","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookBody"}}}},"responses":{"200":{"description":"The updated webhook endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook endpoint","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Confirmation the endpoint was deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedWebhook"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"List recent deliveries for a webhook endpoint","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"100"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Return items after this id (the last item of the previous page)."},"required":false,"description":"Return items after this id (the last item of the previous page).","name":"starting_after","in":"query"}],"responses":{"200":{"description":"The endpoint's most recent deliveries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/deliveries/{deliveryId}/replay":{"post":{"tags":["Webhooks"],"summary":"Replay a webhook delivery","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string"},"required":true,"name":"deliveryId","in":"path"}],"responses":{"200":{"description":"The delivery after being re-queued and flushed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/{id}/backfill":{"post":{"tags":["Webhooks"],"summary":"Backfill historical events to a webhook endpoint","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackfillBody"}}}},"responses":{"200":{"description":"How many canonical deliveries were enqueued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookBackfill"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/passes":{"get":{"tags":["Passes"],"summary":"List passes","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"tmpl_123"},"required":false,"name":"template_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"holder_email","in":"query"},{"schema":{"type":"string","example":"50"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Return items after this pass id (the last item of the previous page)."},"required":false,"description":"Return items after this pass id (the last item of the previous page).","name":"starting_after","in":"query"}],"responses":{"200":{"description":"A list of passes for the authenticated organization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Passes"],"summary":"Create a pass","security":[{"bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"template_id":{"type":"string"},"certificate_set_id":{"type":["string","null"]},"holder_email":{"type":["string","null"]},"holder_name":{"type":["string","null"]},"field_values":{"type":"object","additionalProperties":{}},"metadata":{"type":["object","null"],"additionalProperties":{}},"platforms":{"type":"array","items":{"type":"string"}},"image_variant":{"type":["string","null"],"description":"Render the pass with this template image variant (see the template's `image_variants`). Omit or null for the template's own images."}}}}}},"responses":{"201":{"description":"The created pass","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassCreateResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/passes/{id}":{"get":{"tags":["Passes"],"summary":"Retrieve a pass","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"pass_123"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The requested pass","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pass"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Passes"],"summary":"Update a pass","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"pass_123"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"field_values":{"type":"object","additionalProperties":{}},"metadata":{"type":["object","null"],"additionalProperties":{}},"image_variant":{"type":["string","null"],"description":"Switch the pass to this template image variant; null switches it back to the template's own images; omit to leave it unchanged. Re-signs and pushes like any other update."}}}}}},"responses":{"200":{"description":"The updated pass","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassUpdateResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Passes"],"summary":"Void a pass","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"pass_123"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"The voided pass","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassVoidResponse"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/passes/{id}/events":{"get":{"tags":["Passes"],"summary":"List a pass's events","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"pass_123"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"100"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Return events after this event id (the last item of the previous page)."},"required":false,"description":"Return events after this event id (the last item of the previous page).","name":"starting_after","in":"query"}],"responses":{"200":{"description":"A list of events for the pass","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassEventList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/passes/{id}/redemptions":{"get":{"tags":["Passes"],"summary":"List a pass's scans","description":"Every scan of the pass, accepted or rejected, most recent first. A rejected scan carries its reason and did not change the pass.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"pass_123"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","example":"100"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"The pass's scan log","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RedemptionList"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/passes/{id}/download-links":{"post":{"tags":["Passes"],"summary":"Create an expiring download link","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"pass_123"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"expires_in":{"type":"number"}}}}}},"responses":{"201":{"description":"A tokenized link to the pass page that stops resolving after expires_in seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassDownloadLink"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/passes/{id}/images/{slot}":{"put":{"tags":["Passes"],"summary":"Upload a pass image","description":"Sets this pass's own image of one slot, over its image variant's and its template's. The pass is re-rendered, re-signed and pushed to installed devices, like any update. On Google Wallet a pass strip is the object's hero image; a pass thumbnail is the object's logo on generic passes and an image module on every other type; background is Apple only. Replacing an image retires the public URL Google fetched the old one from. A voided pass is a 409 (pass_voided). If the Google Wallet object could not be updated, the request still succeeds and `warnings` says why.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"pass_123"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"The image slot, by its Apple name: strip, thumbnail or background — whichever of those the template's style has (storeCard and coupon: strip; generic: thumbnail; eventTicket: strip, thumbnail, background; boardingPass: none).","example":"thumbnail"},"required":true,"description":"The image slot, by its Apple name: strip, thumbnail or background — whichever of those the template's style has (storeCard and coupon: strip; generic: thumbnail; eventTicket: strip, thumbnail, background; boardingPass: none).","name":"slot","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","description":"The image, base64-encoded: PNG or JPEG (WebP is also accepted). Any resolution — it is resized to the slot's 1x and @2x sizes. 8 MB limit."}}}}}},"responses":{"200":{"description":"The updated pass, with any non-fatal warnings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassImageResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Passes"],"summary":"Delete a pass image","description":"Removes this pass's own image of one slot, so the slot falls back to the pass's image variant or its template. The stored image is deleted and its public URL stops resolving: this is also how to erase a pass image (a member photo, say), and it works on a voided pass (which is not re-rendered). Otherwise the pass is re-rendered and pushed. Deleting a slot the pass has no image of changes nothing and returns the pass.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"pass_123"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","description":"The image slot, by its Apple name: strip, thumbnail or background — whichever of those the template's style has (storeCard and coupon: strip; generic: thumbnail; eventTicket: strip, thumbnail, background; boardingPass: none).","example":"thumbnail"},"required":true,"description":"The image slot, by its Apple name: strip, thumbnail or background — whichever of those the template's style has (storeCard and coupon: strip; generic: thumbnail; eventTicket: strip, thumbnail, background; boardingPass: none).","name":"slot","in":"path"}],"responses":{"200":{"description":"The updated pass, with any non-fatal warnings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassImageResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden (API key scope, plan or account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"pass.issued":{"post":{"tags":["Webhooks"],"summary":"pass.issued event","description":"Sent to your webhook endpoint when a `pass.issued` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassIssuedEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"pass.add_intent":{"post":{"tags":["Webhooks"],"summary":"pass.add_intent event","description":"Sent to your webhook endpoint when a `pass.add_intent` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassAddIntentEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"pass.added_to_wallet":{"post":{"tags":["Webhooks"],"summary":"pass.added_to_wallet event","description":"Sent to your webhook endpoint when a `pass.added_to_wallet` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassAddedToWalletEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"pass.update_pushed":{"post":{"tags":["Webhooks"],"summary":"pass.update_pushed event","description":"Sent to your webhook endpoint when a `pass.update_pushed` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassUpdatePushedEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"pass.update_delivered":{"post":{"tags":["Webhooks"],"summary":"pass.update_delivered event","description":"Sent to your webhook endpoint when a `pass.update_delivered` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassUpdateDeliveredEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"pass.update_failed":{"post":{"tags":["Webhooks"],"summary":"pass.update_failed event","description":"Sent to your webhook endpoint when a `pass.update_failed` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassUpdateFailedEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"pass.removed":{"post":{"tags":["Webhooks"],"summary":"pass.removed event","description":"Sent to your webhook endpoint when a `pass.removed` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassRemovedEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"pass.voided":{"post":{"tags":["Webhooks"],"summary":"pass.voided event","description":"Sent to your webhook endpoint when a `pass.voided` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassVoidedEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"pass.redeemed":{"post":{"tags":["Webhooks"],"summary":"pass.redeemed event","description":"Sent to your webhook endpoint when a `pass.redeemed` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PassRedeemedEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}},"template.republished":{"post":{"tags":["Webhooks"],"summary":"template.republished event","description":"Sent to your webhook endpoint when a `template.republished` event occurs. Verify the signature, then return any 2xx to acknowledge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateRepublishedEvent"}}}},"responses":{"200":{"description":"Return any 2xx to acknowledge"}}}}}}