WhatsApp Business
Each school connects its own WhatsApp Business Account (WABA). Kinderpedia never proxies through a shared number — every outbound goes from the school's number, every reply lands on the school's webhook.
Two ways to connect
Embedded Signup (recommended)
If your Kinderpedia instance has Embedded Signup enabled, Integrations → WhatsApp → Continue with WhatsApp opens Meta's hosted flow. You:
- Log in to Facebook (the personal account that's an admin on the WABA).
- Pick (or create) the Business Manager.
- Pick (or create) the WABA.
- Pick (or create) the phone number — Meta verifies it via SMS/call right there.
- Accept the Kinderpedia app's permissions.
Meta hands us back the WABA ID + phone number ID + a system-user access token, and we auto-subscribe the WABA to our webhook. The whole flow takes ~3 minutes for someone who already has a Business Manager.
Manual paste
For schools whose Kinderpedia instance doesn't have Embedded Signup enabled (or who prefer to manage their own app), there's a manual fallback. You'll need to paste:
- Phone Number ID — from
business.facebook.com/wa/manage/phone-numbers - WABA ID — from the same page
- System User Access Token — generated in Meta Business Manager
Kinderpedia validates by reading the phone-number resource from Meta and refusing if the token can't be exchanged.
In either case the resulting credentials are encrypted at rest. Only the connection flow sees them in plaintext; the UI only ever sees non-sensitive metadata (e.g. whether you connected via Embedded Signup or manual paste, useful for support).
Webhook subscription
The webhook URL is /api/integrations/whatsapp/webhook on your Kinderpedia domain. Embedded Signup auto-subscribes the WABA via POST /{waba_id}/subscribed_apps. If subscription fails, the integration is saved in a pending state and the modal shows a Retry subscription button.
Inbound webhook signature is validated server-side via X-Hub-Signature-256 HMAC against the Kinderpedia-level WhatsApp app secret. Mismatched signatures are 401'd silently — no row is written.
24-hour customer-care window
Meta's rule: outside an inbound-initiated 24-hour window, you can only send pre-approved template messages. Inside the window, free-form is allowed.
The inbox enforces this client-side. If the customer hasn't messaged in >24h:
- The free-form composer is hidden.
- The template picker takes its place with a banner: "Outside the 24-hour window — pick a template."
Server-side, the window check runs on every reply attempt regardless of UI state. Outside the window, the server rejects the send and the UI swaps to template mode.
Templates
Authored on business.facebook.com/wa/manage/message-templates. Each one goes through Meta's approval queue (24h–7d). Approved templates are pulled into Kinderpedia by clicking Sync templates on the Integrations row.
Variables use positional placeholders: {{1}}, {{2}}, {{3}}. When picking a template, the inbox renders one input per placeholder with the surrounding template body as context. Auto-substitution from the linked parent/lead is supported for name, child_name, school_name, appointment_date (see Templates).
Sending media
WhatsApp supports image, video, document, audio, sticker. The inbox composer accepts drag-and-drop or paperclip-pick. Size caps (Meta-enforced):
- Image / video: 16 MB
- Documents: 100 MB
- Stickers: 5 MB
- Voice notes (audio/ogg): 16 MB
Media is uploaded to your school's private chat-media storage first, then handed to Meta's /v18.0/{phone_number_id}/messages endpoint as a hosted-media reference.
Bulk send
For broadcasts to multiple leads, use Bulk Actions → Bulk WhatsApp on the roster:
- Select up to 100 leads per batch.
- Pick a template + fill variables.
- Dry-run preview shows which leads will receive what, and which are skipped (no phone, opted out, blocklisted).
- Confirm to send.
Bulk WhatsApp is always template-route (per Meta rules), regardless of any individual window state.
Inbound deduplication
Meta retries the same webhook event up to 24h if your endpoint doesn't 200. We dedupe by message id so retries don't double-write. If your tunnel is down for a few hours, you'll get the missed inbounds when it comes back up.
Common errors
| Symptom | Likely cause |
|---|---|
| Modal says "Token expired" | System User token revoked / rotated in Meta. Re-connect. |
| Webhook events stop arriving | WABA dropped subscription. Hit "Retry subscription". |
| Template picker is empty | No approved templates, or sync hasn't run. Click "Sync templates". |
| Send returns "outside window" | More than 24h since last inbound — switch to template. |
| Bulk dry-run shows lots of skipped | Phone numbers missing on parent profiles, or not E.164-normalised. |
Per-school cost / pricing
Meta charges the school directly (per-conversation pricing). Kinderpedia does not mark up or collect WhatsApp fees. The Business Manager → Billing tab is where invoices show up.