Skip to main content

Customer Hub

Customer Hub is the platform identity plane for people your apps talk to (guests, patients, clients). Your app keeps domain documents in ctx.storage; Hub holds shared customer identity when enabled.

Mental model

WhatsApp / widget message
→ runtime / ACS
→ your /qefro tool
→ ctx.customer.resolve({ phone }) # optional binding
→ ctx.storage.* # your appointments / orders / …
ConcernWhere
Display name, phone, tags, consentCustomer Hub (when enabled)
Reservations, picks, invoicesYour ctx.storage collections
Timeline notes (optional)ctx.timeline.append when Hub + binding exist

Use it in the SDK

Starter pattern (soft-fail if Hub is off):

async function resolveCustomer(ctx, phone) {
if (!phone || typeof ctx.customer?.resolve !== 'function') return null;
try {
return await ctx.customer.resolve({ phone_number: phone });
} catch (err) {
ctx.logger?.warn?.('customer resolve skipped', err?.message || err);
return null;
}
}

When creating a domain record, attach customer_id if resolve succeeded. Never require Hub for core booking/ops paths — pilots often run Hub-off.

Platform inject

ACS / tool invoker injects platform.customer (and related bindings) when Customer Hub is configured for the workspace. Your SDK maps that to ctx.customer.

Ops flags (deployment-specific): Hub URL, enable/optional toggles on the managed app environment. If Hub is optional and down, tools should still succeed.

What not to do

  • Do not store a parallel “customers” SoR that duplicates Hub as source of truth for identity (local CRM tables for app-specific attributes are fine).
  • Do not put WhatsApp Business numbers in install settings — workspace Customer channels owns the number; booking links use ?n= from ctx.platform.channels.whatsapp.
  • Do not call Hub HTTP APIs from the browser; stay inside ctx.*.