FusionWA/Documentation

Documentation

Quickstart

FusionWA provides WhatsApp Business Cloud API infrastructure for SaaS companies and software houses. Your customers connect their own WhatsApp Business accounts through Meta Embedded Signup — you get the API and webhooks.

Step 1 — Create an account and application

Register at fusionwa.com/register. Then go to Applications and create your first App. Copy the API Key and API Secret.

Step 2 — Embed the connection widget

Add the SDK to your frontend. The widget renders a "Connect WhatsApp" button for each of your customers.

html
<script src="https://fusionwa.com/sdk/v1.js"></script>
<div id="fusionwa-widget"></div>
<script>
  FusionWA.init({
    apiKey: "fwa_live_...",      // from your FusionWA dashboard (safe to expose client-side)
    customerId: currentUser.id, // your internal customer ID
    containerId: "fusionwa-widget",
  });
</script>

The SDK renders a secure iframe hosted by fusionwa.com, so you do not need to register your own domain with Meta. If your site uses a Content Security Policy, allow https://fusionwa.com in both script-src andframe-src.

Step 3 — Customer connects through Meta Embedded Signup

Your customer clicks "Connect WhatsApp". Meta Embedded Signup opens in a popup. They authorize their WhatsApp Business account. FusionWA receives and stores the connection securely.

For eligible WhatsApp Business App numbers, Meta may offer the Coexistence flow — see the Coexistence section for details.

Step 4 — Configure your webhook

In the dashboard under Applications, set a webhook URL. FusionWA will forward every incoming message and status update to your endpoint in real time.

Step 5 — Send your first message

bash
curl -X POST https://fusionwa.com/api/v1/messages/send \
  -H "X-FusionWA-API-Key: fwa_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+39 02 1234567",
    "templateName": "hello_world",
    "languageCode": "it"
  }'

# Response: { "messageId": "wamid.abc123..." }

SDK Widget

The fastest way to integrate FusionWA. Paste the snippet into your software: the widget manages the full Meta Embedded Signup flow and WhatsApp Business connection on behalf of your customer.

Initialization

javascript
FusionWA.init({
  apiKey: "fwa_live_abc123",     // public — from your FusionWA dashboard
  customerId: currentUser.id,   // unique string per customer in YOUR system
  containerId: "fusionwa-widget", // id of the div to render into
});

Widget states

NOT_SUBSCRIBEDCustomer not yet activated. Shows "Activate" button.
SUBSCRIBED_UNCONNECTEDActivated but not yet connected. Shows "Connect WhatsApp" button.
CONNECTEDWhatsApp Business connected. Shows number and status.

customerId

Use your internal customer identifier — any unique string per App. AppUsers are created automatically on first SDK init. The same customerId is used in API calls to reference that customer's connection.

The SDK apiKey is intentionally public — it only looks up connection status. Keep the API Secret server-side.

WhatsApp Business App Coexistence

Coexistence is a Meta feature that allows a WhatsApp Business App number to be connected to the WhatsApp Business Cloud API simultaneously. When active, the customer continues receiving messages on their phone while the Cloud API (FusionWA) can also send and receive on the same number.

Who it applies to

Coexistence applies to eligible customers who already have an active WhatsApp Business App installation on a mobile device. Not every account is eligible — Meta determines eligibility during the Embedded Signup flow.

The Coexistence flow

When a customer connects via FusionWA and Meta offers Coexistence:

  1. Customer clicks "Connect WhatsApp" in your software.
  2. Meta Embedded Signup popup opens.
  3. Customer selects their existing WhatsApp Business account.
  4. Meta may prompt the customer to scan a QR code on their phone (this is Meta's process, not FusionWA's).
  5. Customer scans the QR in their WhatsApp Business App when requested.
  6. Connection completes — the number is now live on both the phone app and the Cloud API.
The QR code appears only during Meta's Coexistence onboarding, when Meta requests it. It is part of Meta Embedded Signup — FusionWA does not generate QR codes independently. Not all connections use Coexistence; some accounts connect via the standard Cloud API path without a QR scan.

After connecting with Coexistence

The customer continues using WhatsApp Business on their phone normally — sending and receiving from the app as before. The Cloud API (your software via FusionWA) can also send messages and receives all incoming messages via webhook simultaneously.

Coexistence heartbeat

FusionWA automatically manages the Coexistence heartbeat with Meta. No additional configuration is required on your end.

javascript
// No extra configuration needed.
// FusionWA automatically manages the Coexistence
// heartbeat with Meta.
//
// The number stays active on both the mobile app
// and the Cloud API simultaneously.

REST API

Full machine-readable spec: /openapi.yaml (OpenAPI 3.1 — import into Postman or Insomnia).

Widget endpoints (called from the browser) require only x-fusionwa-api-key. Server-to-server endpoints also require x-fusionwa-api-secret.

Send a template message

bash
POST /api/v1/messages/send
x-fusionwa-api-key: fwa_live_...
x-fusionwa-api-secret: <your-secret>

{
  "externalCustomerId": "user_123",
  "toPhoneNumber": "+393331234567",
  "template": {
    "name": "booking_confirmation",
    "language": "it",
    "bodyParams": ["Mario Rossi", "15 set 10:00"]
  }
}

# Response
{ "status": "success", "messageId": "wamid.abc123..." }

Send a free-form text message

bash
POST /api/v1/messages/send
x-fusionwa-api-key: fwa_live_...
x-fusionwa-api-secret: <your-secret>

{
  "externalCustomerId": "user_123",
  "toPhoneNumber": "+393331234567",
  "message": "La tua prenotazione è confermata."
}

# Only valid within a 24-hour customer-initiated window

Check connection status

bash
GET /api/v1/widget/status?customerId=user_123
x-fusionwa-api-key: fwa_live_...

# Response — one of:
{ "status": "NOT_SUBSCRIBED" }
{ "status": "SUBSCRIBED_UNCONNECTED", "facebookAppId": "...", "facebookConfigId": "..." }
{ "status": "CONNECTED", "phoneNumber": "+39 333 123 4567", "wabaId": "...", "phoneNumberId": "..." }

List approved templates

bash
GET /api/v1/templates?externalCustomerId=user_123
x-fusionwa-api-key: fwa_live_...
x-fusionwa-api-secret: <your-secret>

# Response
{
  "status": "success",
  "templates": [
    { "name": "booking_confirmation", "status": "APPROVED", "language": "it", "category": "UTILITY", "variableCount": 2 }
  ]
}

Download received images

Call GET /api/v1/media/{mediaId}?externalCustomerId=YOUR_CUSTOMER_ID from your backend with both x-fusionwa-api-key and x-fusionwa-api-secret. Store image.id from incoming, echo or history payloads when available; the message ID is not a media ID.

The endpoint returns JPEG, PNG or WebP bytes (maximum 5 MiB), after checking the application, customer and connected phone. Serve these bytes through your own authenticated, tenant-scoped endpoint. Never expose the secret in frontend code. Responses are private and not cached.

Media can expire or become unavailable; this endpoint is not a permanent archive and cannot recover old messages whose media ID was not saved. Limit: 120 requests per minute per application. See the OpenAPI specification for error responses.

Webhooks

FusionWA forwards every WhatsApp event to your endpoint in real time. Configure the URL in Applications → Webhook in the dashboard.

Zero storage: payloads are forwarded only, never stored.

Payload structure

json
{
  "type": "message",
  "from": "+39 02 1234567",
  "customerId": "user_123",
  "timestamp": "2025-01-15T10:30:00Z",
  "message": {
    "id": "wamid.abc...",
    "type": "text",
    "text": { "body": "Hello" }
  }
}

Event types

messageIncoming message from a customer
statusMessage delivery status update (sent / delivered / read)
template_statusMeta template approval status change

Receive events in your backend

javascript
// Express
app.post("/webhook/whatsapp", express.json(), (req, res) => {
  const { type, from, customerId, message } = req.body;

  if (type === "message" && message?.type === "text") {
    console.log(`[${customerId}] ${from}: ${message.text.body}`);
    // store, process, reply...
  }

  res.sendStatus(200); // respond 200 within 10s or the webhook is retried
});
Failed deliveries are retried with exponential backoff. Permanently failed events are moved to a dead-letter queue.

WhatsApp Templates

Templates enable proactive outbound messages (notifications, reminders, confirmations). They must be approved by Meta before use.

Create and submit a template

bash
POST /api/v1/templates

{
  "customerId": "user_123",
  "name": "order_confirmed",
  "category": "UTILITY",
  "language": "it",
  "components": [
    {
      "type": "BODY",
      "text": "Your order {{1}} is confirmed. Delivery: {{2}}."
    }
  ]
}

The template is submitted to Meta for review. Status becomes APPROVED typically within a few hours. You receive a template_status webhook event when the status changes.

Error Reference

200Success
400Invalid request body
401Missing or invalid API Key
403App revoked or customerId not authorized
404Customer not found or not connected
422Validation error (see response body)
429Rate limit exceeded
500Internal error — retry with backoff

For AI Coding Assistants

Use this block as initial context in your prompt when integrating FusionWA with Claude Code, Codex, Cursor, or GitHub Copilot:

markdown
# FusionWA Integration Context

Read https://fusionwa.com/llms.txt for the full machine-readable specification.

## SDK Widget
<script src="https://fusionwa.com/sdk/v1.js"></script>
<div id="fusionwa-widget"></div>
<script>
  FusionWA.init({ apiKey, customerId, containerId })
</script>

## REST API
Base URL: https://fusionwa.com/api/v1
Auth: X-FusionWA-API-Key: fwa_live_...

POST /api/v1/messages/send
  body: { to, templateName, languageCode, components[] }
  returns: { messageId }

GET /api/v1/widget/status?customerId=
  returns: { status: "INACTIVE"|"CONNECTED", phoneNumber }

GET /api/v1/templates?customerId=
  returns: [{ name, status, language, category }]

## Webhooks
Configure URL in dashboard. Payload: { type, from, customerId, timestamp, message }
Respond 200 within 10s. type: "message" | "status" | "template_status"

## Security rules
- apiKey: client-safe (SDK only)
- API Secret: server-only (never expose)
- customerId: your internal ID, any unique string
- Do NOT store messages — forward to your own DB if needed
- Do NOT invent endpoints — use only the documented ones above

Download the machine-readable version: /llms.txt