WhatsApp Profile Sync is an independent integration product that turns structured WhatsApp messages—and attached photos or PDFs—into create-or-update profile operations on your backend.
It was originally built for SafeWork Global worker onboarding and is now maintained as a standalone, config-driven plugin for agencies, integrators, and product teams. No AI, OCR, or RPA.
| Product | WhatsApp → profile upsert connector |
| Origin | SafeWork Global (workforce onboarding POC) |
| Status | POC validated · production enhancements planned |
| Model | Authorized deployment only (see licensing) |
Contents: Overview · Who it's for · How it works · Setup · Access control · API contract · Commands · Troubleshooting · SafeWork preset · License
Staff and field teams already share candidate or customer details on WhatsApp. This product captures that flow in a controlled, repeatable way:
- A trusted sender posts a fixed template (
PROFILE,WORKER,LEAD, …). - The plugin parses fields deterministically and upserts by phone.
- Optional media slots attach photos, certificates, or PDFs.
- Data lands in your API—or a local store during POC.
Product-specific rules live in YAML config, not in forked code. SafeWork is one preset; CRM leads, clinic intake, or membership onboarding are others.
| Audience | Use case |
|---|---|
| Consulting / integration agencies | White-label WhatsApp intake for client CRMs, HR, or marketplaces |
| Workforce & recruitment platforms | Worker or candidate profiles from WhatsApp (SafeWork-style) |
| Operations teams | Centre staff → server profiles without manual data entry |
| Product engineers | Embed webhook + sync logic via npm package |
Not a public self-serve SaaS today. Deployment, resale, and multi-client hosting require explicit authorization from the maintainer.
WhatsApp (allowlisted sender)
│
▼
Meta Cloud API webhook
│
▼
WhatsApp Profile Sync ──► parse template + download media
│
├──► Local store (POC / demo)
└──► Your HTTP API (production)
| Layer | Responsibility |
|---|---|
| Ingress | Meta WhatsApp Cloud API |
| Parsing | Configured TEMPLATE + key: value lines |
| Identity | Match on phone (configurable) |
| Media | Caption-based slots (photo, certificate, …) |
| Upsert | Find by phone → update; else create |
| Governance | Sender allowlist + webhook signature verification |
Access is enforced at two levels:
Use of this software in production, client projects, agency resale, or hosted multi-tenant offerings requires written approval from the maintainer. Cloning or deploying without authorization is not permitted.
→ See Licensing & authorized use.
Only WhatsApp numbers in whatsapp.allowlist may create or update profiles:
whatsapp:
allowlist:
- "919549230227" # E.164 / digits; empty = allow all (dev only)Combine with Meta recipient allowlists in development mode. Production should always use a tight allowlist.
- Node.js 20+
- Meta WhatsApp Cloud API app (developers.facebook.com)
- HTTPS webhook URL (tunnel for local dev; reverse proxy in production)
git clone https://github.com/Kailash-dev/whatsapp-profile-sync.git
cd whatsapp-profile-sync
npm installcp config/default.example.yaml config/local.yaml| Preset | Path | Typical use |
|---|---|---|
| Generic | config/default.example.yaml |
Any profile entity |
| CRM leads | config/presets/crm-lead.example.yaml |
Sales / lead intake |
| SafeWork workers | config/presets/safework.example.yaml |
Workforce onboarding |
Edit config/local.yaml (gitignored). Secrets can also live in .env (see .env.example).
Minimum WhatsApp block:
whatsapp:
verify_token: <you-invent-this>
app_secret: <meta-app-secret>
access_token: <meta-access-token>
phone_number_id: "<meta-phone-number-id>"
allowlist:
- "91XXXXXXXXXX"Template example:
entity: customer
templates:
CUSTOMER:
required: [name, phone]
optional: [email, city]
map:
name: full_name
phone: mobile
email: email
city: cityStaff send:
CUSTOMER
name: Priya Sharma
phone: 9876543210
email: priya@example.com
city: Pune
CONFIG_PATH=./config/local.yaml npm run dev- Health:
GET http://localhost:8787/health - Webhook:
GET|POST http://localhost:8787/webhooks/whatsapp
- Create app → WhatsApp → Integrate with API.
- Step 1. Try it out — token, phone number ID, add test recipients.
- Tunnel locally:
cloudflared tunnel --url http://localhost:8787 - Webhook → Callback URL:
https://<host>/webhooks/whatsapp, verify token = config value. - Subscribe webhook field
messages. - Subscribe app to WABA:
POST /v21.0/{WABA_ID}/subscribed_apps
Message the business/test number from the WhatsApp app (not Meta's "Send message" demo):
CUSTOMER
name: Test User
phone: 9000000001
Offline:
npm run parse:demo
npm run test:e2eWhen api.enabled: true:
| Action | Method | Path | Notes |
|---|---|---|---|
| Find | GET |
find_path ({phone}) |
Return object with id, or empty / 404 |
| Create | POST |
create_path |
Body: mapped fields + phone + source: "whatsapp" |
| Update | PATCH |
update_path ({id}) |
Body: mapped fields |
| Upload | POST multipart |
upload_path ({id}) |
slot, field, file |
Default auth: Authorization: Bearer <token> (configurable).
| Command | Description |
|---|---|
npm run dev |
Webhook server with hot reload |
npm start |
Run compiled server |
npm run build |
Compile src/ → dist/ |
npm run typecheck |
Typecheck src/ + scripts/ |
npm run parse:demo |
Offline parse + storage demo |
npm run test:e2e |
Offline webhook e2e suite |
import { loadConfig, ProfileSyncService, startServer } from "whatsapp-profile-sync";
const config = loadConfig("./config/local.yaml");
startServer(config);
// or embed:
const sync = new ProfileSyncService(config);
await sync.handleMessage(incomingMessage);Authorized npm distribution and commercial embedding are subject to the same licensing terms.
SafeWork Global was the first production intent for this product: staff and centres send worker details on WhatsApp; the platform upserts worker profiles and documents.
cp config/presets/safework.example.yaml config/local.yaml
CONFIG_PATH=./config/local.yaml npm run dev| Item | Value |
|---|---|
| Entity | worker |
| Template | WORKER |
| Media slots | passport_photo, trade_certificate, resume, … |
SafeWork remains a reference customer and preset, not the owner of the product. The core plugin is entity-agnostic.
Text
<TEMPLATE>
field: value
Media caption — must match a configured slot:
certificate
or document:certificate. Full template text can appear in a media caption to create + attach in one message.
| Issue | Fix |
|---|---|
| Webhook verify fails | URL must include /webhooks/whatsapp; token must match config |
| Inbound messages ignored | Subscribe messages; subscribe app to WABA; keep tunnel + server running |
#131030 recipient error |
Add number in Meta test recipients + allowlist |
invalid_signature |
Meta sends signed payloads when app_secret is set |
| Token expired | Refresh from Meta API setup or use System User token |
| Unauthorized sender | Number not in whatsapp.allowlist |
- Tight
whatsapp.allowlistin production - Secrets in env, not git (
config/local.yamlis gitignored) - HTTPS webhook only
- HMAC signature verification enabled (real
app_secret) - Authorized deployment agreement for client / agency use
config/
default.example.yaml
presets/ # safework, crm-lead, …
src/ # product-agnostic core
scripts/ # parse-demo, webhook-e2e
Planned enhancements for agency and production use:
- Managed hosting and stable webhook URLs
- Multi-tenant config per client
- Long-lived Meta token / Business verification playbook
- Admin audit UI and deployment tooling
- Commercial support tiers for integrators
POC scope is complete; contact the maintainer for production rollout.
Copyright © 2026 Kailash-dev. All rights reserved.
This repository documents a validated proof of concept. The software is not open for unauthorized commercial use, redistribution, resale, or client deployment without written permission from the maintainer.
| Permitted | Requires authorization |
|---|---|
| Reviewing this repo with maintainer approval | Production deployment for a client |
| POC / evaluation agreed in writing | Agency resale or white-label offering |
| SafeWork Global reference deployment | Multi-tenant hosted service |
| Contributions by invitation | Publishing forks as competing products |
To request a license (agency, integrator, or enterprise deployment):
- Open an issue on GitHub describing your use case, or
- Contact via SafeWork Global for workforce-related deployments.
Unauthorized use may violate applicable copyright and contract law.
Technical details: LICENSE
Contributions are welcome by invitation or after maintainer approval. See CONTRIBUTING.md.