Client Invitations
Audience: Sales / Agency-success · Where in app: /agency/client-invitations (list, create) · Plan availability: Agency tier (verify specifics)
Client invitations are white-label marketing/outreach emails an agency sends to prospective clients to pitch Knock Knock under the agency's own brand. Each invitation is a small campaign (up to 20 recipients) with a subject, a personalized note, an optional demo video, a PDF brochure, a price, and a booking/CTA link. The emails go out branded as the agency (logo, primary color, reply-to). This is not the staff-invitation flow (Staff Management) and it does not create accounts.
Despite the name, this is a prospecting email tool, not a magic-link account-onboarding flow. Sending an invitation queues branded emails; it does not provision a client company or a login. To actually create a client account, use Managing Companies.
What it does
- Compose a branded pitch email: subject (with suggestions), personal note (supports a
[First Name]token), demo video URL, PDF attachment, booking link, price, tagline. - Add recipients by pasting/typing emails or importing a CSV — max 20 per campaign.
- Preview the rendered email before sending.
- Send — queues one white-label email per recipient via the platform mail queue.
- List past campaigns with recipient counts and per-recipient status.
How it works
On create (POST /client-invitations, store), the controller:
- Verifies the caller is an agency user and resolves the agency.
- Enforces 1–20 recipients.
- Derives a first name per recipient from the email local-part (
sarah.j@…→ "Sarah") for the[First Name]token. - Creates a
client_invitationsrecord (status: 'sending'). - Builds template data from agency branding (logo,
theme_colors.primary,reply_emailor owner email) and the invitation content. Demo video falls back to an admin default video for theclient_invitationcategory if none is provided. - Queues a white-label email per recipient (
emailQueue.add, templateagency/client-invitation.html,white_label: true,sender_name = agency.name,reply_to = agency reply email). - Flips the record to
status: 'sent'.
Preview (POST /client-invitations/preview) renders the same template with a mock invitation and returns HTML — nothing is sent or stored.
Source: frontend/src/views/agency/client-invitations/{Create,List}.vue, frontend/src/repositories/agency/clientInvitations.js, backend/app/controllers/ClientInvitationController.js.
Configuration & options
Compose form (client-invitations/Create.vue)
| Field | Default | Notes |
|---|---|---|
subject | a suggested line | Three quick-pick suggestions provided |
personal_note | a starter note | [First Name] is replaced per recipient; newlines → <br> |
demo_video_url | '' | Falls back to admin default client_invitation video if empty |
pdf_attachment_file | null | Uploaded via streamUpload('/files', …), max 10MB; stores file id |
booking_link | '' | CTA target; falls back to mailto:<reply email> if empty |
price | $97/mo | Free-text string shown in the email |
tagline | Your Digital Growth Partner | Shown under the agency name |
| Recipients | — | Pasted text or CSV; split on commas/newlines; only valid-looking emails kept; max 20 |
Endpoints (clientInvitations.js)
| Action | Repository fn | Endpoint |
|---|---|---|
| List campaigns | getClientInvitations(params) | GET /client-invitations (paginated, populates PDF) |
| Get one | getClientInvitation(id) | GET /client-invitations/:id |
| Create + send | createClientInvitation(data) | POST /client-invitations |
| Preview HTML | previewClientInvitation(data) | POST /client-invitations/preview |
ClientInvitationModel (collection client_invitations)
| Field | Default | Notes |
|---|---|---|
agency_id, user_id | — | Owning agency + sender |
subject, personal_note | required | Campaign content |
demo_video_url | null | Optional |
pdf_attachment_file | null | files ref |
booking_link | null | CTA |
price | $97/mo | — |
tagline | Your Digital Growth Partner | — |
recipients[] | [] | Each: email, first_name, status (queued/sent/failed) |
total_recipients | 0 | Count |
status | sending | Campaign status: draft / sending / sent / partial_failure |
Lifecycle & states
- Campaign status:
draft→sending→sent, orpartial_failureif some recipients fail. The currentstoreflow creates assendingand flips tosentonce all emails are queued. - Recipient status:
queued→sent→ (failedon delivery error). Recipients startqueuedat creation. - Campaigns are immutable after send in the UI (list + preview only; no edit/resend button in this cluster — verify if resend is expected).
Behaviors & edge cases
- Hard cap of 20 recipients. Both UI and backend enforce it; >20 returns "Maximum 20 recipients per campaign".
- Invalid emails are dropped client-side before submit (regex filter); a campaign with zero valid recipients is rejected ("At least one recipient is required").
- Branding comes from the agency record — logo (
logo_file),theme_colors.primary, andreply_email(falling back to the owner's email). White-label send usesagency.nameas the sender name. - Default demo video fallback. If no
demo_video_url, the platform tries the admin default video for theclient_invitationcategory (default-flagged first, else newest active). - No account is created. This tool only emails; client provisioning is separate.
- Permission: the controller checks
isAgencyUser(agency owner or staff); there is no dedicated per-permission gate for this tool in the controller (verify whether staff should be restricted).
Plan & limits
- 20 recipients per campaign (code-enforced). No documented per-agency campaign cap (verify).
- PDF attachment ≤ 10MB (client-enforced).
- Part of the agency tier (verify plan specifics).
Technical implementation
- Views:
frontend/src/views/agency/client-invitations/{Create,List}.vue - Routes:
frontend/src/router/agency.js(agency-client-invitations,agency-client-invitation-create) - Repository:
frontend/src/repositories/agency/clientInvitations.js - Controller:
backend/app/controllers/ClientInvitationController.js— see backend service - Model:
backend/app/models/ClientInvitationModel.js - Email: white-label send via the platform email queue, template
agency/client-invitation.html; branding fromAgencyModel
Related
- Agency Portal — Overview
- Managing Companies — actually creating a client account
- Staff Management — the other (internal) invite flow
- White-Label — branding used in these emails