Custom Guest Invitations
Build your own guest invitation experience: invite guests, share links, accept invitations on your site, and track them
Members can invite guests to your venue before a visit. Tiquo offers three ways to do this, all driven by the same Guest Flow:
- Embed the ready-made Guest Pre-Registration form (Copy embed code).
- Link to the hosted form (Copy guest flow URL).
- Build your own interface with the DOM Package, the Hosted Package or the Customer API. This page covers that option.
The DOM Package (1.9.1 or newer) and the Hosted Package (window.Tiquo) use
the same method names. Every method needs a signed-in customer with a
completed profile, and the session decides the organisation and customer.
1. Set up the Guest Flow
- In Settings > Registration, under Guest Pre-Registration, create and save a Guest Flow. See Guest Passes for allowances and locations.
- Under Guest invitation destination, choose where guests land: a Customer portal, or My own website with your HTTPS page URL (see step 4).
- Open the flow's menu and choose Copy Guest Flow ID. The flow editor's Custom UI · DOM or hosted package section also has the ID and a starter snippet.
- Allow your website's domain under Settings > Website SDK.
2. Invite guests
// After OTP sign-in and profile completion.
const flow = await tiquo.getGuestFlow('GUEST_FLOW_ID');
if (!flow) throw new Error('This Guest Flow is unavailable.');
// How many guests can be invited right now.
const guestLimit = flow.requiresGuestPass
? flow.availableGuestPassQuantity
: flow.maxGuestsPerSubmission;
// Disable the form when guestLimit is 0.
// Build this once per submission and reuse it exactly on retry.
const submission = {
flowId: flow.id,
locationId: selectedLocationId, // from flow.locations; needed when there are several
visitDate: selectedVisitDate, // YYYY-MM-DD in the location's timezone
guests: guestFirstNames.map((guestFirstName) => ({
token: crypto.randomUUID(),
guestFirstName,
})),
};
const { invitations } = await tiquo.createGuestInvitations(submission);
// Store invitation.token and invitation.inviteUrl to track and re-share later.
await navigator.clipboard.writeText(invitations[0].shareText);- Show a location selector when
flow.locationshas more than one entry. - All guests in a submission are created together, or none are.
- In limited mode each invitation reserves one of the member's Guest Passes until it's used, expires or is revoked.
- Creation returns links and messages only; it doesn't email the guest.
Validation rules, retries and errors are listed in Guest Invitations and Passes.
3. Show the member's invitations
getGuestPasses() lists the member's live invitations: ones they sent
(status: 'assigned') and ones they received and accepted
(status: 'accepted'). Each entry is one invitation, not a count. To show how
many Guest Passes the member has left, use
getPassBalances().
It doesn't include share tokens or links, and it shows a sent invitation as
assigned whether or not the guest has accepted yet. To show "waiting for
your guest" or a Share again button, keep the tokens you stored at
creation and read each one:
const invitation = await tiquo.getGuestInvitation(storedToken);
// invitation.status: 'pending' | 'accepted' | 'revoked' | 'expired'
// invitation.inviteUrl: the link to share againWith the Hosted Package you can render the list without code:
<div data-tiquo-guest-passes data-tiquo-guest-pass-status="assigned" data-tiquo-limit="20">
<article data-tiquo-guest-pass-item>
<h3 data-tiquo-guest-pass="personName"></h3>
<time data-tiquo-guest-pass="visitDate"></time>
<p data-tiquo-guest-pass="venueName"></p>
</article>
<p data-tiquo-empty>No upcoming guests.</p>
</div>4. Accept on your own page
With My own website, each invitation link is your page URL plus
?invitation=<token>. On that page:
- Keep the
invitationparameter in the URL through sign-in. - Sign the guest in with the same organisation's public key, and complete their profile.
- Call
acceptGuestInvitation(token), then remove the parameter. - Optionally show their invitations with
getGuestPasses(), filtered tostatus === 'accepted'. Accepting adds nothing to the guest's own pass balance; the Guest Pass stays with the host.
const url = new URL(window.location.href);
const token = url.searchParams.get('invitation');
tiquo.onAuthStateChange(async (session) => {
if (!token || !session?.customer?.id) return;
try {
await tiquo.acceptGuestInvitation(token);
url.searchParams.delete('invitation');
history.replaceState({}, '', url.pathname + url.search + url.hash);
} catch (error) {
// Keep the token so the guest can retry. Show expired, already-accepted
// and own-invitation errors from error.message.
}
});An invitation can't be read before the guest signs in, so show a general
welcome until then. With a Customer portal destination, Tiquo hosts this
page at /invite/<token> on the portal.
5. At reception
Staff register accepted guests from the host's registration modal or through See Upcoming Guests. Registration uses the reserved Guest Pass. See Customer Registration.
Limitations
- Members can't cancel an invitation they sent. Staff can revoke pending invitations in Settings > Registration under Guest Flow invitations. An unaccepted invitation expires at the end of its visit date.
- Invitations can't be edited. Create a new one with a new token.
- The member's invitation list has no tokens, links or history. Store tokens yourself to track or re-share.
- In the Hosted Package,
availableGuestsLabelon a guest flow reads "N Guest Passes available" even for unlimited flows. UsemaxGuestsLabelwhenrequiresGuestPassis false. - Booking attendees (guests added to a booking at checkout) are a separate feature and don't use Guest Flows or Guest Passes.
Errors
DOM Package methods throw a TiquoAuthError with code
GUEST_PRE_REGISTRATION_FAILED and the server's message, for example
This guest invitation has expired. Hosted Package methods reject with an
Error carrying the same message.