How to Build a WhatsApp API System for Restaurant Order Confirmations

·9 min read
How to Build a WhatsApp API System for Restaurant Order Confirmations

If you run a restaurant or manage the tech stack for one in Pakistan or India, you know the pain of SMS. High failure rates, DLT registration headaches, and the sheer cost of sending a simple text message make it a frustrating channel. When a customer orders a hot Biryani or a pizza, they want to know immediately that their order is received, paid for, and on the way. If your SMS fails, your phone rings with anxious customers asking, "Did you get my order?"

The WhatsApp Business API solves this. But setting it up is not as simple as downloading an app. It requires a specific sequence of API calls, template approvals, and webhook configurations. This guide walks you through the exact setup from scratch, based on real deployments.

What You Need Before You Write Code

Do not write a single line of code until you have these four assets ready. If you try to skip these, Meta will halt your setup halfway through.

  • A Meta Developer Account: You need to register at developers.facebook.com using your personal Facebook profile. Make sure your profile name matches your legal ID, or identity verification will fail later.
  • A Clean Phone Number: This number must not have an active WhatsApp App or WhatsApp Business App account. If it does, you must delete that account in the app settings first. Once a number is migrated to the Cloud API, you cannot use it on a regular phone app anymore.
  • A Registered Business: In India, you need your GSTIN or business registration documents. In Pakistan, you need your NTN (National Tax Number) or partnership deed. Meta will use these to verify your Business Portfolio (formerly Business Manager).
  • An International Payment Card: Meta bills you directly for conversations. In Pakistan, use a bank card with international transactions explicitly enabled (like Meezan Bank or Nayapay). In India, ensure your card supports RBI-compliant recurring international e-mandates, or Meta will pause your account within 30 days due to payment failures.

Step 1: Create the Meta App and Link Your Number

Go to your Meta Developer Dashboard and click Create App. Select Other as your use case, then choose Business as your app type. Give it a clear name like "Restaurant Notifications" and link it to your Business Portfolio.

Once the app is created, scroll down on the left menu and click on WhatsApp, then select API Setup. Meta will automatically generate a temporary access token and a test phone number for you to try out.

To add your real restaurant phone number, scroll down on that same API Setup page to Step 5: Add a phone number. Enter your display name (e.g., "Khyber Charcoal Grill"), select your time zone, and enter the phone number. Meta will send a 6-digit verification code via SMS or voice call. Enter that code to complete the linking process.

What to do if verification fails: If you do not receive the SMS code, check if your number has a block on international SMS. If you are using a virtual or VoIP number, Meta will reject it. Use a standard SIM card from local carriers like Jazz, Zong, Airtel, or Jio.

Step 2: Get a Permanent System User Access Token

The temporary token Meta gives you on the dashboard expires in 24 hours. If you hardcode this into your restaurant's POS or ordering system, your notifications will stop working tomorrow.

To get a permanent token:

  1. Go to your Business Settings (business.facebook.com/settings).
  2. Under Users, click on System Users.
  3. Click Add, name the user "POS_Integration", and set the role to Admin.
  4. Click Generate New Token, select your WhatsApp-enabled app, and check the boxes for whatsapp_business_messaging and whatsapp_business_management.
  5. Copy the generated token immediately. Meta will never show it to you again. Store it in your environment variables as WHATSAPP_ACCESS_TOKEN.

Step 3: Create and Approve Your Order Confirmation Template

Meta does not allow you to send free-form text messages to customers unless they messaged you first within the last 24 hours. To initiate an order confirmation, you must use a pre-approved Utility Template.

Navigate to your WhatsApp Manager, click on Message Templates, and click Create Template.

Choose the Utility category. Do not choose Marketing. Utility templates are cheaper to send, but Meta's automated AI will reject them if they contain any promotional language like "Use code PIZZA10 for your next order". Keep it strictly transactional.

The Template Structure

Use this exact body text structure to ensure fast approval:

Hi {{1}}, 

Your order {{2}} at {{3}} has been confirmed! 

Total Amount: {{4}}
Delivery Address: {{5}}

We are preparing your food now. You can track your order here: {{6}}

In this template, the numbers in double curly braces are variables that your system will populate dynamically when sending the API request.

Confirmation of approval: Meta usually approves utility templates within two to ten minutes. You will see the status change from "In Review" to "Active" (green indicator) in your WhatsApp Manager. If it is rejected, check your variables. Every variable must have a realistic sample value provided during the submission process.

Step 4: Write the Code to Send the Confirmation

Now that your template is active, you can trigger the notification from your online ordering system or POS. Here is a raw cURL request showing the payload structure. Note the use of the template parameter and the components array where we pass our variable values in order.

curl -X POST "https://graph.facebook.com/v18.0/YOUR_PHONE_NUMBER_ID/messages" \
  -H "Authorization: Bearer YOUR_PERMANENT_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "923001234567",
    "type": "template",
    "template": {
      "name": "order_confirmation_utility",
      "language": {
        "code": "en"
      },
      "components": [
        {
          "type": "body",
          "parameters": [
            { "type": "text", "text": "Ali" },
            { "type": "text", "text": "#ORD-8821" },
            { "type": "text", "text": "Khyber Charcoal Grill" },
            { "type": "text", "text": "Rs. 2,450" },
            { "type": "text", "text": "House 12, Street 4, F-8, Islamabad" },
            { "type": "text", "text": "https://restaurant.com/track/8821" }
          ]
        }
      ]
    }
  }'

Replace YOUR_PHONE_NUMBER_ID with the actual ID found on your Meta Developer Dashboard (this is different from your phone number itself). Replace the country code in the to field. For Pakistan, use 92; for India, use 91. Do not include leading zeros or plus signs.

How to Handle API Responses

If the request is successful, Meta will return a 200 OK status with a JSON body containing a message ID:

{
  "messaging_product": "whatsapp",
  "contacts": [{ "input": "923001234567", "wa_id": "923001234567" }],
  "messages": [{ "id": "wamid.HBgLOTIzMDAxMjM0NTY3FQIAERgSM0E0QzVDOUU1M0QzQzRDN0REAA==" }]
}

Log this message ID (starting with wamid.) in your database alongside your order ID. You will need it to track delivery status via webhooks.

Step 5: Set Up Webhooks to Confirm Delivery

Just because you received a 200 OK from the API does not mean the customer received the message. The customer’s phone might be switched off, they might have no internet connection, or they may have blocked your number. To know if the message actually landed, you must configure a Webhook.

Create an endpoint on your server (e.g., https://yourdomain.com/api/whatsapp-webhook). This endpoint must handle two types of requests from Meta:

  1. GET Request (Verification): Meta sends a challenge token when you first register the webhook to prove you own the server.
  2. POST Request (Data Payload): Meta sends real-time updates when a message is sent, delivered, read, or failed.

Here is a simple Node.js/Express snippet to handle the GET verification and POST payloads:

const express = require('express');
const app = express();
app.use(express.json());

// Webhook verification
app.get('/api/whatsapp-webhook', (req, res) => {
    const verifyToken = "your_chosen_secret_verify_token";
    const mode = req.query['hub.mode'];
    const token = req.query['hub.verify_token'];
    const challenge = req.query['hub.challenge'];

    if (mode === 'subscribe' && token === verifyToken) {
        return res.status(200).send(challenge);
    }
    return res.sendStatus(403);
});

// Webhook event receiver
app.post('/api/whatsapp-webhook', (req, res) => {
    const entry = req.body.entry;
    if (entry && entry[0].changes && entry[0].changes[0].value.statuses) {
        const statusUpdate = entry[0].changes[0].value.statuses[0];
        const messageId = statusUpdate.id;
        const status = statusUpdate.status; // "sent", "delivered", or "read"
        
        console.log(`Message ${messageId} updated to status: ${status}`);
        
        // Update your database here with the delivery status
    }
    res.sendStatus(200); // Always return 200 quickly to Meta
});

app.listen(3000, () => console.log('Webhook listening on port 3000'));

Once this code is live on your SSL-secured server, go to your Meta Developer Dashboard, click on Webhooks under the WhatsApp menu, enter your URL, and input your verify token. Under Webhook Fields, subscribe to messages.

What to Do When Things Go Wrong

When running a restaurant, a delayed notification means cold food and angry customers. Here are the specific errors you will encounter and how to fix them immediately.

Error 131026: Cloud API Message Deliverability Rate is Low

This happens when you send messages to numbers that do not exist or are not active on WhatsApp. If your system triggers notifications to landline numbers or typos entered by customers, Meta will temporarily limit your sending capacity. The Fix: Implement regex validation on your frontend checkout form to ensure only valid mobile numbers (e.g., starting with 03 or 9 for Pakistan, 6, 7, 8, 9 for India) can submit the order form.

Error 100: Invalid Parameter

This error usually means your template variables do not match what you defined in the Meta dashboard. If your approved template has 6 variables and you only pass 5 in your API call, Meta will reject the request outright. The Fix: Always write a unit test in your code to verify that the array length of your parameters matches your template structure exactly.

Payments Declined / Account Disabled

If your credit card fails to process Meta's monthly invoice, your API access is cut off instantly. The Fix: Do not use standard consumer debit cards. Use enterprise-grade credit cards or dedicated virtual business cards. Always keep a backup card linked in your Meta Business Payment settings.

What to Do Next

Once your order confirmations are running smoothly, you should look at optimizing costs and handling customer replies. When you send an order confirmation, customers will often reply with messages like "Please add extra raita" or "Deliver it to the back gate".

If you don't want to build the webhook handler, routing logic, and live-chat interface yourself, you can use a service like WA Link to manage customer replies and route them to your kitchen or support staff. Note that WA Link won't host your restaurant menu database—you still need your own POS or ordering system to trigger the initial API calls, but it simplifies the two-way conversation management.

To keep costs low, make sure your customer support team replies to user messages within 24 hours. When a user replies to your order confirmation, it opens a "Service Conversation" window. Any messages you send within that 24-hour window are priced at a much lower rate than business-initiated template messages, allowing you to coordinate delivery details for free.

Frequently Asked Questions

Can I use my existing personal or business WhatsApp app number for the API?

No. You cannot use the same phone number on both the standard mobile app and the WhatsApp Cloud API simultaneously. If you register your current restaurant number to the API, your physical WhatsApp app will log out, and you will lose your local chat history. If you want to keep using your phone app for manual orders, buy a new dedicated SIM card solely for your automated API notifications.

How much does it cost to send an order confirmation message?

Meta charges per 24-hour conversation, not per message. An order confirmation falls under the "Utility" category. For India, a utility conversation costs approximately INR 0.1129. For Pakistan, it costs approximately USD 0.0176. These rates fluctuate slightly based on Meta's official pricing tables. You also get 1,000 free service (user-initiated) conversations per month, but business-initiated utility templates do not count toward this free tier.

Do I need to verify my Meta Business Portfolio before sending messages?

You can start sending messages in "Sandbox Mode" immediately without verification, but you will be restricted to sending messages only to verified test numbers (up to 50 unique numbers). To send order confirmations to actual customers, you must complete the business verification process by uploading your business registration documents in the Meta Business Suite.

What happens if the customer does not have WhatsApp?

If you attempt to send a message to a non-WhatsApp number, Meta's API will return a success response (since the payload was valid), but your webhook will shortly receive a status update of failed with error code 131026. To handle this, your backend code should listen for this failure webhook and automatically fall back to sending a standard SMS after 2 minutes if no delivered status is received.

Read the API documentation