Wakato Pass

Space MCP tools in the Wakato Pass scope (pass). Reach these with a wks_live_ key over space-mcp or space-api.

Tools in the pass scope, callable over space-mcp (tools/call) or space-api (REST) with a wks_live_* key that grants pass.

adjust_pass_balance

Scope: pass:write

Add or deduct on a customer's card. balance: 'points' (points or stamps, the default) or 'gift_value' (money — load it with a positive delta, spend with a negative one). Target by install_id, or by template_id + contact_email/contact_id. Never below zero. Lands in the pass ledger like every other change; a points change fires 'balance reaches' automations.

ParameterTypeRequiredDescription
install_idstring
template_idstring
contact_emailstring
contact_idstring
deltanumberyes
balancepoints | gift_valueWhich balance (default points — points or stamps).
reasonstring

cancel_pass_entry

Scope: pass:write

Take back an entry a holder has (entry_id from list_pass_holders).

ParameterTypeRequiredDescription
entry_idstringyes

create_pass_template

Scope: pass:write

Create a Wakato Pass — ONE card a customer adds to their account via the returned /card/<code> link (or is given with grant_pass_card, or by an automation's enroll_in_pass step). Say what it does — any combination, changeable later with update_pass_template: earn (points or stamps), membership, gift_value, next_booking — or nothing yet (a name and a description is a pass; what it unlocks can come after). Membership tiers each have their own length in config.tier_days {tier: days, 0 = never ends}; perks every holder has are config.perks [{kind:'discount', name, style:'percent'|'amount', value, applies_to} | {kind:'content', name, body}]; buttons every holder can tap (on the card page and in Apple/Google Wallet, ≤6) are config.buttons [{kind:'url'|'booking'|'listing'|'phone'|'whatsapp'|'email', label, value}] — value = the https address, a booking page id, a listing id, a phone number with country code or an email; an entry with on_join:true is given to every new holder. A salon with points, a membership and gift value is one card, not three. A pass needs no community. Earn rules: earn_per_scan awards on a staff scan at the till (a door never earns); for anything else (e.g. +10 points per booking) create an automation with the adjust_pass_balance action. Starts as draft — set status:'active' (or update later) to make it installable.

ParameterTypeRequiredDescription
namestringyese.g. "Bella's Coffee Club".
approve_holdersbooleanA card someone signs up for waits until the business approves it (review_pass_holder).
min_agenumber,nullSign-up refused under this age, read from the birthday the form asks (ask for the birthday in join_ask). null = none.
max_holdersnumber,nullSign-up closes once this many hold the pass. null = no limit.
earnpoints | stamps | noneWhat the card earns: points (a balance spent on rewards), stamps (toward one reward, e.g. 10 coffees), or none. Never both.
membershipbooleanA tier and a valid-until date, checked at the door (config: tiers[], default_tier, validity_days).
gift_valuebooleanMoney on the card — its OWN balance, never mixed with points; loaded with adjust_pass_balance {balance:'gift_value'}, spent at the till by amount (config: currency).
next_bookingbooleanShow the holder's next appointment with a Book button (config: booking_page_id).
holder_modecard_only | accountHow people get the card: card_only (default for new passes — a name and an email or phone, no Wakato account, kept in their phone's Apple/Google Wallet; nothing mentions Wakato) or account (they sign in / sign up; the card lives in their Wakato Pass too).
headlineearn | membership | gift_valueWhich one is the big number on the card when it does several. Defaults to earn, then membership, then gift value.
descriptionstring
configobjectSettings for what the card does: earn points {points_label, welcome_bonus, points_per_currency, multiplier_windows}; earn stamps {stamps_required}; membership {tiers[], default_tier, validity_days}; gift value {currency}; birthday {birthday_bonus}; points that expire {points_expire_days}; the phone's lock screen near the business {lock_screen_places: [{label, address, latitude, longitude}] — up to 10, Apple Wallet shows the card when the holder is near one}.
rewardsobject[][{title, cost, method, kind?, amount?}] — method 'staff_scan' (redeemed at the counter) or 'self_code' (customer self-redeems); kind 'free' (default), 'money_off' (amount off the bill) or 'gift_value' (amount put on the card — needs gift_value).
join_askobjectWhat sign-up asks: { photo, phone, email, birthday } each 'required' | 'optional' | 'off', plus photo_approval (a manager checks each photo before the card works). Name is always asked; email and phone can't both be off (when both are optional, one of them is needed). On update, send only what changes. A required photo makes a membership that can't be lent — staff see it big at every scan.
entriesobject[]What the card lets its holder INTO — replaces the whole list. Each: { key?, kind: 'appointment' (their next booking on a booking page: target_type 'booking_page', target_id) | 'event' (tickets) | 'classes' (a pack that counts down) | 'pass' (day/week pass) | 'place' (a room, locker, parking) | 'other', name, types?: [{name, people}] (e.g. General, VIP, Table of 4), people (per entry), uses (visits; null = unlimited, 10 = a pack of ten), reentry: 'none'|'same_day'|'always', valid: {mode:'none'|'dates'|'days'|'hours', from, to, days, open:'HH:MM', close:'HH:MM'} }. Give a holder an entry with give_pass_entry; staff let people in at an Entry place.
brandobject{ business_name, bg_color, text_color, logo_url } for the card face. business_name is what the holder sees as the name of the business — set it whenever the space is not named after the business, or the card prints the space name.
earn_per_scannumberPoints/stamps per staff scan at the till (default 1 when the card earns, 0 otherwise).
scan_cooldown_minutesnumberMinimum minutes between scans of the same card (default 1).
join_fieldsobject[]Questions asked before someone gets the card (name and email already come from their Wakato account). [{key, label, type, required, options?, maps_to?}] — type: text|textarea|email|tel|number|date|url|select|radio|checkboxes|checkbox; options[] for the choice types; maps_to writes the answer onto the contact (phone|company|location|website|line_of_work|birthday — a date question mapped to birthday powers the birthday bonus), otherwise it lands in the contact's custom fields. A required question parks a granted card as 'pending' until the holder answers.
allow_new_contactsbooleanfalse = invite-only (installer must already be a contact).
statusdraft | active

get_pass_card_design

Scope: pass:read

How a pass's card looks in Apple and Google Wallet: its design (colours, typed name or logo, the banner's layers, the scan code, what the front says), a link to the banner as it looks now, the designs you can start from, and how every part works. Read it before changing the look.

ParameterTypeRequiredDescription
template_idstringyes

get_pass_template

Scope: pass:read

Get one pass template with its config, rewards, active holder count, and the public install link (/card/<code>) customers use to add the card.

ParameterTypeRequiredDescription
template_idstringyes

give_pass_entry

Scope: pass:write

Give a card holder an ENTRY: a ticket (type_key: one of the entry's types, e.g. vip or table_of_4), a class pack, a day pass, a place. entry_key names one of the pass's entries (get_pass_template shows them). Target by install_id, or template_id + contact_email/contact_id. people/uses/valid_from/valid_until override the entry's settings for this one.

ParameterTypeRequiredDescription
install_idstring
template_idstring
contact_emailstring
contact_idstring
entry_keystringyes
type_keystring
peoplenumber
usesnumber,nullVisits; null = unlimited.
valid_fromstringISO date-time.
valid_untilstringISO date-time.

grant_pass_card

Scope: pass:write

Give someone a card — the way to enroll a person who did not scan the sign-up code themselves. On a card_only pass (holder_mode) the card is made and its link sent by email, or by a text from the space's number when there is only a phone (billed like any text); they keep it in their phone's wallet, no account needed → outcome card_sent | card_sent_again (installed/already_held when that email is already a Wakato account). On an account pass it is an offer: a Wakato account gets it as PENDING to accept; anyone else is emailed a sign-up link → pending | installed | already_held | invited | invite_already_sent. The pass must be ACTIVE.

ParameterTypeRequiredDescription
template_idstringyes
emailstringWho to give the card to (required on an account pass).
phonestringCard-only passes: a phone with its country code (+1 646 555 0142), used when there is no email.
namestringOptional — used when creating a contact for them.

list_pass_holders

Scope: pass:read

List customers holding cards in this space (joined with their contact name/email), with balance (points or stamps), stored_value (gift value), tier, validity, and their answers to the pass's joining questions. Optional template_id filter.

ParameterTypeRequiredDescription
template_idstring
limitnumber
offsetnumber

list_pass_places

Scope: pass:read

The places this space scans Wakato Pass cards at (the front counter, a door, a festival gate) and, for each, what staff see (show, in order), the stop signs (red = don't let in, amber = look twice), what staff and managers may do (limits: points_max, gift_max, override, undo_minutes) and the briefing on the scanner.

list_pass_templates

Scope: pass:read

List the space's Wakato Pass templates — the cards customers add to their account (loyalty points, stamp cards, memberships, gift value, next booking; one card can do several). Each carries earn, has_membership, has_stored_value (gift value), has_booking and headline. Call before create_pass_template to reuse an existing one.

ParameterTypeRequiredDescription
statusdraft | active | archived
limitnumber

review_pass_holder

Scope: pass:write

Approve or refuse a holder waiting on a pass that approves each one (approve_holders on; list_pass_holders shows approval 'waiting'). A waiting card doesn't work at the scan until approved.

ParameterTypeRequiredDescription
install_idstringyes
approvebooleanyes

review_pass_photo

Scope: pass:write

Approve or refuse the photo on a card, when the pass has photos checked before the card works (list_pass_holders shows photo_status 'pending'). Refusing needs a note — the holder reads it and sends a new one.

ParameterTypeRequiredDescription
install_idstringyes
approvebooleanyes
notestring

save_pass_place

Scope: pass:write

Create or change a place the space scans cards at (place_id to change one). { name, mode: 'till' (counter: points, rewards, gift value) | 'door' (membership check) | 'entry' (let in and count on an entry: entry_key names the pass's entry) | 'event' (a community event: event_id), show: [{key, on}] in order (photo, entry, tags, answers, visits, note, membership, points, gift, rewards, next_booking, birthday), stop_signs: [{key, on, age?}] (already_in, not_now, used_up, no_entry, membership_ended, frozen, photo_pending, under_age) plus your own [{key:'custom_1', on, custom:{level:'red'|'amber', title, when:{kind:'tag', tag} | {kind:'answer', question, equals?} | {kind:'gift_below', amount} | {kind:'points_above', amount}}}], limits: {staff:{override, points_max, gift_max, undo_minutes}, managers:{...}}, briefing, buttons: [{key, label, who:'everyone'|'managers', when:'always'|'stop'|'clear', ask}] — the owner's OWN buttons under every scan answer here (e.g. 'Ask for help'; up to 6; ask = a line staff type first, or null). What a button does is automations on the trigger pass_scan_button_pressed filtered by button_key; a button nothing listens to is not shown. Keep each existing button's key when you change it. }. Anything left out gets the place's defaults — except buttons, which stay as they are when left out.

ParameterTypeRequiredDescription
place_idstring
namestring
modetill | door | entry | event
entry_keystring
event_idstring
template_idsstring[]Only these passes are scanned here (empty = every pass of the space).
showobject[]
stop_signsobject[]
limitsobject
briefingstring
buttonsobject[]The owner's own scanner buttons here (replaces the list when given).

sell_pass_gift_card

Scope: pass:write

Sell the pass's gift value as a gift card of one amount (at least 5): makes a LIVE Commerce listing of the shop run from this space and the automation that, when it is paid, gives the buyer the card and puts the amount on it. stop_product_id takes one off sale instead. The pass needs gift_value on and the space a Commerce account.

ParameterTypeRequiredDescription
template_idstringyes
amountnumber
stop_product_idstring

sell_pass_unlock

Scope: pass:write

Sell a membership tier or an entry (a ticket, a class pack, a day pass…) straight from a pass: makes a LIVE Commerce listing of the shop run from this space and the automations that give it to the buyer — the card too if they don't hold it. unlock = {kind:'tier', tier} (one of config.tiers) or {kind:'entry', entry_key, type_key?} (one of the pass's entries). billing one_time | monthly | yearly (monthly/yearly only for a membership: renewals extend it, the subscription ending ends it; on_fail 'now' also ends it the moment a payment fails, 'period' (default) lets the paid time run out). stop_product_id takes one off sale instead. What is on sale is in the pass's config.sales.

ParameterTypeRequiredDescription
template_idstringyes
unlockobject
pricenumber
billingone_time | monthly | yearly
on_failperiod | now
stop_product_idstring

set_pass_card_design

Scope: pass:write

Design how a pass's card looks in Apple and Google Wallet: start from one of Wakato's designs (start_from: wellness, coffee, membership, gift, ticket, salon, neon, barber, bakery, yoga, florist, carwash, winebar, playcentre, cowork, surf, pets, books, blank — the business's name and initials go on it), then change what the business wants: colours, the typed name or an uploaded logo, a background photo (photo_url; null removes it), the banner's layers (shapes, patterns, stamps, words, pictures), the scan code (wallet's own, branded in the business's colours, or none), and what the front says (top, big, under, appointmentFirst). Each part sent is merged over the current design; send design to replace it whole. Every card already in a wallet redraws. Answers with banner_url — look at it to check your work. get_pass_card_design explains every part.

ParameterTypeRequiredDescription
template_idstringyes
start_fromstringA design key from get_pass_card_design's designs_to_start_from.
stylecard | ticketticket = Apple's ticket shape (a notch at the top, a shorter banner).
colorsobject{ bg, fg, label } as #hex: the card, its words, its small labels.
logoobject{ kind: 'word'|'image', text, sub, font, size, spacing, italic, mark, url } — the typed name (font: playfair|jost|cormorant|bebas|dmserif|inter) or an uploaded logo (https url).
photo_urlstring,nullAn https link to a photo that fills the banner (the shop, the food, the place). null removes it.
layersobject[]Replaces the banner's layers (first is the background, type fill). See get_pass_card_design how_it_works.
codeobject{ mode: 'wallet'|'branded'|'none', dot: 'round'|'soft'|'square', dotColor (dark), eyeColor, tile (light), mark, x, y, size }. Switching to branded places it where there is room.
frontobject{ top, big, under: [a, b, c], appointmentFirst } — front fact keys: earn, name, name_tier, membership, gift, next_reward, next_visit, entry, perk, card_number, expires.
designobjectA whole design, replacing the current one.

set_pass_note

Scope: pass:write

Pin the team's note on a card holder (staff see it at the scan, e.g. “Prefers the window table”). An empty note removes it.

ParameterTypeRequiredDescription
install_idstringyes
notestringyes

start_pass_grant_automation

Scope: pass:write

Grant something on a pass when something happens: makes ONE automation of the space, switched OFF, with the trigger and the steps filled in (Give Pass Card, then what it gives). unlock = {kind:'pass'} (the card itself), {kind:'tier', tier}, {kind:'entry', entry_key, type_key?}, {kind:'points'} or {kind:'gift_value'}. trigger_type one of booking_submission, form_submission, community_member_joined, commerce_order_paid, tag_added, pass_balance_reached, pass_scanned. Finish the trigger's settings (which form, which tag…) with the automation tools, then switch it on.

ParameterTypeRequiredDescription
template_idstringyes
unlockobjectyes
trigger_typestringyes

update_pass_template

Scope: pass:write

Edit a pass: what it does (earn points/stamps/none, membership, gift_value, next_booking, headline — send only what changes; switching points<->stamps is refused while anyone holds a balance, and gift_value can't be switched off while anyone holds money; switching anything else off hides nothing people hold for good), rules (earn_per_scan, scan_cooldown_minutes, config), rewards (replaces the whole array), join_fields (replaces the whole array), brand, description, or status (draft/active/archived — archived cards stop scanning).

ParameterTypeRequiredDescription
template_idstringyes
namestring
earnpoints | stamps | noneWhat the card earns: points (a balance spent on rewards), stamps (toward one reward, e.g. 10 coffees), or none. Never both.
membershipbooleanA tier and a valid-until date, checked at the door (config: tiers[], default_tier, validity_days).
gift_valuebooleanMoney on the card — its OWN balance, never mixed with points; loaded with adjust_pass_balance {balance:'gift_value'}, spent at the till by amount (config: currency).
next_bookingbooleanShow the holder's next appointment with a Book button (config: booking_page_id).
holder_modecard_only | accountHow people get the card: card_only (default for new passes — a name and an email or phone, no Wakato account, kept in their phone's Apple/Google Wallet; nothing mentions Wakato) or account (they sign in / sign up; the card lives in their Wakato Pass too).
headlineearn | membership | gift_valueWhich one is the big number on the card when it does several. Defaults to earn, then membership, then gift value.
descriptionstring
configobjectMerged into the current settings: send only the keys that change, a key as null to clear it. Keys as in create_pass (incl. lock_screen_places).
rewardsobject[]Replaces the whole array. Each: { id?, title, cost, method: 'staff_scan'|'self_code', description?, kind?: 'free' (default — something handed over) | 'money_off' (amount taken off the bill) | 'gift_value' (amount put on the card's gift balance — needs gift_value on), amount? }. description is what the HOLDER reads when they open the reward — where to go, what to ask for, an address, anything they need to actually use it.
join_askobjectWhat sign-up asks: { photo, phone, email, birthday } each 'required' | 'optional' | 'off', plus photo_approval (a manager checks each photo before the card works). Name is always asked; email and phone can't both be off (when both are optional, one of them is needed). On update, send only what changes. A required photo makes a membership that can't be lent — staff see it big at every scan.
entriesobject[]What the card lets its holder INTO — replaces the whole list. Each: { key?, kind: 'appointment' (their next booking on a booking page: target_type 'booking_page', target_id) | 'event' (tickets) | 'classes' (a pack that counts down) | 'pass' (day/week pass) | 'place' (a room, locker, parking) | 'other', name, types?: [{name, people}] (e.g. General, VIP, Table of 4), people (per entry), uses (visits; null = unlimited, 10 = a pack of ten), reentry: 'none'|'same_day'|'always', valid: {mode:'none'|'dates'|'days'|'hours', from, to, days, open:'HH:MM', close:'HH:MM'} }. Give a holder an entry with give_pass_entry; staff let people in at an Entry place.
brandobject{ business_name, bg_color, text_color, logo_url }. Merged into what is there: send only what changes. The card's full look (template, banner, photo, branded code, what the front says) is set with set_pass_card_design.
earn_per_scannumber
scan_cooldown_minutesnumber
allow_new_contactsboolean
approve_holdersbooleanA card someone signs up for waits until the business approves it (review_pass_holder).
min_agenumber,nullSign-up refused under this age, read from the birthday the form asks (ask for the birthday in join_ask). null = none.
max_holdersnumber,nullSign-up closes once this many hold the pass. null = no limit.
join_fieldsobject[]Questions asked before someone gets the card (name and email already come from their Wakato account). [{key, label, type, required, options?, maps_to?}] — type: text|textarea|email|tel|number|date|url|select|radio|checkboxes|checkbox; options[] for the choice types; maps_to writes the answer onto the contact (phone|company|location|website|line_of_work|birthday — a date question mapped to birthday powers the birthday bonus), otherwise it lands in the contact's custom fields. A required question parks a granted card as 'pending' until the holder answers.
statusdraft | active | archived

On this page