Retrieve a card template
Retrieve a single card template by id. Returns the full Card object including design, pass_fields, mechanics, form_builder, referral configuration, issuer details, terms, registration URLs (with per-location variants), and live issued_count. Returns 404 if the card does not exist or is archived in another organization. Useful for verifying a card’s configuration before enrolling customers via POST /v1/customers.
Authorizations
Your secret API key as a Bearer token: Authorization: Bearer vxn_sk_.... Keys are created and scoped in the dashboard - see Authentication.
Headers
Path Parameters
Response
Card template.
A card template defines the loyalty program a merchant offers. The template controls visual design, mechanics (stamps/points/discount/etc.), the customer signup form, wallet pass content, and behavioral defaults. Customers are enrolled in exactly one card via POST /v1/customers. Cards are immutable on type after creation.
Card mechanics type. Immutable after creation. Drives which mechanics block applies, which initial_state overrides are valid on POST /v1/customers, and which wallet pass layout is used. 'custom' is partner-driven and has no built-in mechanics. Notifications reach every card type, including custom.
stamp, reward, discount, coupon, membership, gift_card, custom "stamp"
REQUIRED. Brief customer-facing description of the card/loyalty program. Required by Apple PKPass (description field, used for accessibility/voice-over) and Google LoyaltyClass (programName description for review approval). Can be a string OR per-language object for multi-language passes. Min 1, max 500 chars per language.
1 - 500Visual design of the wallet pass. Required: design_mode, bg_color, text_color, icon_url (logo_url is optional; the pass falls back to text when omitted).
VISUAL LAYOUT by mode + type:
- design_mode=standard + stamp: mechanics.stamp_icon_url + (optional custom_background_image_url)
- design_mode=individual + stamp: mechanics.stamp_count_images (N+1 per-position images; image_url accepts a plain URL or an OPTIONAL per-language map - every position must share the same language set; each customer sees the variant in their language, else sk, else en, else the first one)
- design_mode=standard + non-stamp: pattern_type + pattern_icon_urls + (optional custom_background_image_url) Server AUTO-GENERATES the final pattern image per supported language: pass a per-language object as card description and each language gets its own image; single-language cards (or a plain-string description) get one image. Each customer is served the image matching the language they picked at signup (fallback sk, then en, then the first one). No image URLs are needed for the standard pattern.
- design_mode=individual + non-stamp: individual_background_image_url REQUIRED (accepts a plain URL or an OPTIONAL per-language map; each customer sees the variant in their language, else sk, else en, else the first one)
TIER OVERRIDES: tiered reward/discount cards use mechanics.tiers[i].background_image_urls (per-language) which overrides any card-level background for customers at that tier.
Your stable reference for this card template (e.g., your internal product SKU). Useful for syncing with external systems. Persisted on the card template and returned on reads (null when unset). Not unique: two templates may share a reference, so GET /v1/cards?external_id= filters and can return more than one row. Send null to clear it.
255"loyalty-coffee-stamp-2026"
Barcode format rendered on the wallet pass to identify customers at POS. QR/Aztec/PDF417/Code128 work on both Apple and Google Wallet; others are Google Wallet only.
QR, Aztec, PDF417, Code128, Code39, EAN8, EAN13, ITF14, UPCA, DataMatrix, Codabar "QR"
Scanner UX flag. When true, staff MUST enter a purchase amount before they can record a transaction against this card. When false, the amount field is optional (staff can record visit-only / quick-redeem transactions). Affects scanner behavior across all card types.
false
The wallet pass layout - three front slots + back rows, identical model on Apple and Google (the same shape the platform's partner integrations have used in production):
The PRIMARY front area (the big number - stamps, points, balance) is owned by the card's mechanics and never configurable here. Typed values ({{custom.<key>}} of type date/number/currency/boolean) render locale-formatted on both platforms automatically.
PATCH replaces this object as a WHOLE, it does not merge per slot. Any slot you omit is REMOVED from the card. Sending {"pass_fields": {"header": {...}}} on a card that also had front_left, front_right, back or barcode_alt_text clears those. To change one slot, send the full pass_fields object including every slot you want to keep, or read the card first and send it back with your edit applied. This differs from metadata and custom on other resources, which ARE JSON Merge Patch (a per-key merge where null deletes one key).
Optional terms and conditions shown on the wallet pass back side. text supports per-language (string OR object {sk, cs, en, de}) - the pass renders the customer's own language variant when present, falling back to the card's default-language text otherwise. full_url is a single URL only (no per-language variant).
Public signup URL where customers self-enroll. Pattern: https://vexioncards.one/signup/?id={card_id}. Share via QR code, flyer, or email. Append ?loc={location_id} for per-location attribution (signup_location_id on the resulting customer). For per-location URLs of every location with this card enabled, call GET /v1/locations and check enabled_card_ids for this card's id (or read each location's cards[] (GET /v1/locations) - every entry carries its location-scoped signup_url). We previously had registration_urls_per_location on this response, but it duplicated data that lives on Location and forced an extra refresh whenever a location toggled the card on/off.
"https://vexioncards.one/signup/?id=crd_sophcrprtvpmmnwxah2lomnkee"
Free-form key-value map for partner-internal IDs and integration markers. NOT rendered on the wallet pass. Shape IS enforced (422 validation_failed): max 50 keys, key must match ^[a-zA-Z0-9_]{1,40}$, values must be strings of at most 500 chars. The platform never interprets the contents.
Persisted on the card template and returned on reads. Omitted entirely when empty rather than sent as null. On PATCH the map is merged per key, so sending one key never clears the others. (Distinct from Customer.metadata, which is built and live.)
Template lifecycle. draft (created but never launched - not issuable, its public signup page turns customers away), active (issuable), paused (temporarily closed to NEW signups; existing passes keep working and keep earning), archived (retired - existing customer passes keep working, no new signups). A card created through this API is born active. DELETE archives, never destroys, and historical references stay resolvable forever.
draft, active, paused, archived "active"
Server-side pass-image generation state. Standard-design cards get their wallet pass images (the per-stamp-state strip images, or the single pattern strip) rendered automatically after create and after design edits. The card is returned immediately and images render in the background, typically within seconds. processing: rendering in progress - the pass already works and images appear as soon as they are ready. completed: all images are live. failed: rendering hit an error and is retried automatically; the card itself is unaffected. not_applicable: individual-design cards (you supply the images) and cards with no generated imagery.
The business currency of this card. A business has one currency, so it is the same on every card. Set from the country of the first location and locked after the first transaction, customer balance or gift card purchase. See Money and currency.
EUR, CZK, GBP, HUF, PLN, RON, CHF, USD