Building a Native WhatsApp Forms Engine on PrismWA
A visual builder and runtime for Meta's WhatsApp Flows - letting teams design multi-screen forms, power them with live data, and collect structured responses without a single Meta dashboard visit.
Platform
Web & WhatsApp
Duration
6 weeks
The Challenge
Teams running WhatsApp-based surveys, lead capture, or bookings had two bad options: build a web form and paste a link into the chat (which breaks the point of being "in WhatsApp" and loses a chunk of respondents at the tap-out), or hand-author raw WhatsApp Flow JSON and manage it through Meta's Flow Builder and Graph API directly - a process with no visual preview, a strict component schema, and a public-key encryption protocol that has to be implemented correctly before Meta will even let you publish.
- Sending a plain link instead of a native form loses respondents at the app-switch
- Meta's raw Flow JSON format has no visual editor and fails validation on small mistakes
- Every dynamic screen (a dropdown fed by an API, a personalized message) requires implementing Meta's Data Exchange encryption protocol from scratch
- Republishing a flow for a trivial config change re-triggers Meta's full validation and review pipeline unless you specifically avoid it
- Submitted responses arrive back as a WhatsApp webhook payload, not structured data - someone still has to wire that into a CRM or spreadsheet
Project Goals
How We Built It
Visual Flow Builder with Live Phone Preview
Built a screen-by-screen editor with a drag-and-drop component palette covering 14 field types - headings, text inputs, dropdowns, radio and checkbox groups, date pickers, opt-ins, photo/document pickers, plus If/Switch branching and a footer action - alongside a phone-frame preview that renders the screen exactly as it will appear in WhatsApp as it's being built.
Meta's Data Exchange Encryption Handshake
Every WhatsApp Flow with dynamic screens needs a public/private RSA key pair: PrismWA generates a 2048-bit RSA key pair per flow, uploads the public key to Meta, and keeps the private key server-side. When a user's phone requests a screen, Meta encrypts the request with a fresh AES-128-GCM key wrapped in our RSA public key; PrismWA unwraps it, decrypts the payload, computes the response, and re-encrypts it with the same AES key under a flipped initialization vector, exactly as Meta's protocol requires.
Three Ways to Power a Dynamic Screen
A screen's live data can come from three sources, configured per-screen with no code: a static list, an external API call (with input field mapping and a JMESPath expression to reshape the response), or a sandboxed custom JavaScript function with access to the user's phone number, form data, and encrypted secrets. Functions run through a safe fetch with SSRF protection (blocking private IPs and cloud metadata endpoints) and a hard timeout.
Smart Publish, Submission Capture, and Forwarding
Publishing hashes the transformed flow JSON and skips the Meta round-trip entirely if nothing actually changed (e.g., only a data-source URL was edited) - so config tweaks don't re-trigger Meta's validation and asset upload pipeline unless the form itself changed. Completed forms arrive as a WhatsApp webhook (nfm_reply), get de-duplicated by flow token, stored as structured submissions (with any uploaded photos/documents downloaded automatically), and optionally forwarded to an external API with configurable field-name mapping and per-submission resend.
Challenge: Getting the Encryption Handshake Byte-Exact
Problem: Meta's Data Exchange protocol fails silently on the device ("Something went wrong") if the AES-GCM auth tag handling or IV-flip is even slightly off, with almost no error detail returned.
Challenge: Routing Between Screens When routing_model Goes Missing
Problem: Meta's publish step transforms our stored flow JSON for its own copy without writing the transformed routing_model back to our database, so the stored flow often has an empty routing model - which broke "next screen" navigation during data exchange.
Challenge: Running User-Authored Functions Safely
Problem: Letting admins write custom JavaScript to power a screen means running arbitrary code inside the same process as the API - a real sandbox escape risk if function authorship were ever opened beyond trusted roles.
The Outcome
PrismWA now ships a complete native WhatsApp Forms feature: a visual builder, Meta's encrypted Data Exchange handshake, three ways to power live screens, and automatic, de-duplicated submission capture - with no hand-written Flow JSON and no manual data wiring.
Impact & Results
Key Takeaways
Meta's Data Exchange protocol is well-documented but unforgiving - get the encryption handshake exactly right or debug blind
Hashing the transformed output before republishing avoids needless Meta API calls and keeps config tweaks fast
Giving admins a custom-function escape hatch (not just static config) covers the long tail of "one more API" requests without new engineering work each time
Server-authored code execution is only safe with an explicit trust boundary - restricting it to trusted roles is a stopgap, not a permanent answer
Conclusion & Impact
"This project showed that Meta's WhatsApp Flows platform is genuinely capable - multi-screen native forms with conditional logic, live data, and media capture - but the protocol underneath (encrypted data exchange, strict JSON schema, opaque validation errors) is unforgiving to build against directly. Wrapping it in a visual builder and a runtime that owns the crypto handshake turned a protocol only a backend engineer could touch into something any workspace admin can design."
Technology Stack

Ready to achieve similar results?
Let our dedicated engineers bring your vision to life with cutting-edge technology and unparalleled expertise.