Blog/Use Cases

How to Send WhatsApp Invoices and Payment Reminders via API

Automatically send WhatsApp invoices, payment reminders, and overdue notices to customers using Rapiwa API. Full code examples in Python, Node.js, and PHP. No per-message fees.

by Ismail
How to Send WhatsApp Invoices and Payment Reminders via API

You can send WhatsApp invoices and payment reminders using Rapiwa API by calling POST https://app.rapiwa.com/send-message with the invoice details in the message body. WhatsApp invoices have a 98% open rate versus 20% for email — customers pay 2–3x faster when reminders arrive on WhatsApp. Rapiwa costs $5/month flat with no per-message fees.

Why WhatsApp Beats Email for Invoices

ChannelOpen rateAverage pay timeRead within 5 min
WhatsApp98%1–3 days85%
Email20%7–14 days12%
SMS90%3–5 days68%

Rapiwa is the cheapest WhatsApp API for invoicing: $5/month flat. No per-message fees. Compare this to SMS gateways that charge $0.01–$0.10 per message — for 500 invoices/month that's $5–$50 in SMS fees alone.

Invoice Automation Workflows

Use case 1: Invoice on order completion New WooCommerce/Shopify order → generate PDF invoice → send via WhatsApp

Use case 2: Payment reminder sequence Invoice unpaid after 3 days → WhatsApp reminder Invoice unpaid after 7 days → Second reminder with urgency Invoice unpaid after 14 days → Final notice

Use case 3: Recurring invoice notification Monthly subscription renews → WhatsApp invoice link

Step 1: Send an Invoice Message (Text Format)

cURL

curl -X POST https://app.rapiwa.com/send-message \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "8801234567890",
    "message": "Invoice #INV-2026-001\n\nDear Sarah Johnson,\n\nYour invoice for June services is ready.\n\n*Services:* Web Development\n*Period:* June 1–30, 2026\n*Amount Due:* $1,500.00\n*Due Date:* July 10, 2026\n\nPay online: https://pay.yourcompany.com/INV-2026-001\n\nThank you for your business!\n— YourCompany"
  }'

Expected response:

{
  "status": "success",
  "messageId": "msg_invoice_abc123",
  "timestamp": "2026-07-02T10:30:00Z"
}

Step 2: Send Invoice as PDF Attachment

For PDF invoices, host the PDF and send via /send-document:

curl -X POST https://app.rapiwa.com/send-document \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "number": "8801234567890",
    "documentUrl": "https://yoursite.com/invoices/INV-2026-001.pdf",
    "filename": "Invoice-INV-2026-001.pdf",
    "caption": "Invoice #INV-2026-001 — $1,500 due by July 10, 2026. Pay at: https://pay.yourcompany.com/INV-2026-001"
  }'

Step 3: Invoice + Payment Reminder System in Python

# invoice_notifier.py
# pip install requests schedule psycopg2-binary

import requests
import schedule
import time
import psycopg2
from datetime import datetime, date

RAPIWA_API_KEY = 'YOUR_API_KEY'


def send_whatsapp(phone: str, message: str) -> dict:
    """Send a WhatsApp message via Rapiwa."""
    response = requests.post(
        'https://app.rapiwa.com/send-message',
        headers={'Authorization': f'Bearer {RAPIWA_API_KEY}'},
        json={'number': phone, 'message': message},
        timeout=10
    )
    return response.json()


def send_invoice_notification(phone: str, name: str, invoice_num: str, 
                              amount: float, due_date: str, pay_url: str) -> dict:
    """Send initial invoice notification."""
    message = (
        f"Invoice #{invoice_num}\n\n"
        f"Hi {name}!\n\n"
        f"Your invoice is ready:\n"
        f"*Amount Due:* ${amount:,.2f}\n"
        f"*Due Date:* {due_date}\n\n"
        f"💳 Pay now: {pay_url}\n\n"
        f"Reply with any questions — we're happy to help!"
    )
    return send_whatsapp(phone, message)


def send_payment_reminder(phone: str, name: str, invoice_num: str,
                          amount: float, due_date: str, days_overdue: int,
                          pay_url: str) -> dict:
    """Send a payment reminder (overdue)."""
    if days_overdue <= 0:
        # Pre-due reminder (3 days before)
        urgency = "friendly"
        prefix = f"Quick reminder 😊"
        suffix = "No action needed if you've already paid!"
    elif days_overdue <= 7:
        urgency = "moderate"
        prefix = f"Invoice #{invoice_num} is now *{days_overdue} days overdue*"
        suffix = "Please pay as soon as possible to avoid any late fees."
    else:
        urgency = "urgent"
        prefix = f"⚠️ URGENT: Invoice #{invoice_num} is *{days_overdue} days overdue*"
        suffix = "Please pay immediately or contact us to arrange a payment plan."
    
    message = (
        f"{prefix}\n\n"
        f"Hi {name},\n\n"
        f"*Invoice:* #{invoice_num}\n"
        f"*Amount Due:* ${amount:,.2f}\n"
        f"*Original Due Date:* {due_date}\n\n"
        f"💳 Pay now: {pay_url}\n\n"
        f"{suffix}"
    )
    
    return send_whatsapp(phone, message)


def process_invoice_reminders():
    """
    Query database for invoices needing reminders and send them.
    Run this daily.
    """
    conn = psycopg2.connect("postgresql://user:pass@localhost/billing")
    cursor = conn.cursor()
    
    today = date.today()
    
    # Query unpaid invoices that need reminders
    cursor.execute("""
        SELECT 
            i.id, i.invoice_number, i.amount, i.due_date,
            i.pay_url, i.last_reminder_sent,
            c.phone, c.name
        FROM invoices i
        JOIN customers c ON i.customer_id = c.id
        WHERE i.status = 'unpaid'
          AND c.phone IS NOT NULL
          AND (
            -- 3 days before due (pre-reminder)
            i.due_date = %s + INTERVAL '3 days'
            -- Due today
            OR i.due_date = %s
            -- 3 days overdue (first reminder)
            OR (i.due_date = %s - INTERVAL '3 days' 
                AND (i.last_reminder_sent IS NULL 
                     OR i.last_reminder_sent < %s - INTERVAL '3 days'))
            -- 7 days overdue
            OR (i.due_date = %s - INTERVAL '7 days'
                AND (i.last_reminder_sent IS NULL
                     OR i.last_reminder_sent < %s - INTERVAL '7 days'))
            -- 14 days overdue (final notice)
            OR (i.due_date = %s - INTERVAL '14 days'
                AND (i.last_reminder_sent IS NULL
                     OR i.last_reminder_sent < %s - INTERVAL '14 days'))
          )
    """, [today] * 8)
    
    invoices = cursor.fetchall()
    print(f"Sending {len(invoices)} invoice reminders")
    
    for row in invoices:
        (inv_id, inv_num, amount, due_date, pay_url, 
         last_reminder, phone, name) = row
        
        days_overdue = (today - due_date).days
        
        result = send_payment_reminder(
            phone=phone,
            name=name,
            invoice_num=inv_num,
            amount=float(amount),
            due_date=due_date.strftime('%B %d, %Y'),
            days_overdue=days_overdue,
            pay_url=pay_url
        )
        
        if result.get('status') == 'success':
            cursor.execute(
                "UPDATE invoices SET last_reminder_sent = %s WHERE id = %s",
                [today, inv_id]
            )
    
    conn.commit()
    cursor.close()
    conn.close()


# Schedule: run every day at 9 AM
schedule.every().day.at("09:00").do(process_invoice_reminders)

if __name__ == "__main__":
    print("Invoice reminder service started...")
    process_invoice_reminders()  # Run once immediately
    while True:
        schedule.run_pending()
        time.sleep(60)

Step 4: Node.js Invoice Sender

// invoiceSender.js
// npm install node-fetch

const fetch = require('node-fetch');

const RAPIWA_API_KEY = 'YOUR_API_KEY';

async function sendInvoiceWhatsApp(invoice) {
  const { customerPhone, customerName, invoiceNumber, amount, dueDate, paymentUrl } = invoice;

  const message = `Invoice #${invoiceNumber}\n\n` +
    `Hi ${customerName}! 🧾\n\n` +
    `Your invoice is ready:\n` +
    `*Amount:* $${amount.toFixed(2)}\n` +
    `*Due:* ${dueDate}\n\n` +
    `💳 Pay now: ${paymentUrl}\n\n` +
    `Questions? Just reply here!`;

  const response = await fetch('https://app.rapiwa.com/send-message', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${RAPIWA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ number: customerPhone, message })
  });

  return response.json();
}

// Usage
sendInvoiceWhatsApp({
  customerPhone: '8801234567890',
  customerName: 'Sarah Johnson',
  invoiceNumber: 'INV-2026-001',
  amount: 1500,
  dueDate: 'July 10, 2026',
  paymentUrl: 'https://pay.yourcompany.com/INV-2026-001'
}).then(result => console.log(result));

Payment Reminder Sequence Best Practices

TimingToneMessage focus
3 days before dueFriendly"Just a reminder"
Due dateNeutral"Invoice is due today"
3 days overduePolite urgency"Please pay when convenient"
7 days overdueDirect"Payment needed ASAP"
14 days overdueFirm"Final notice — contact us"
30+ days overdueStop automatingEscalate to human/collections

Common Errors and Fixes

  • Customers not responding: WhatsApp messages require an active number. Verify phone numbers are in international format and active
  • 401 from Rapiwa: API key expired — regenerate in Dashboard → API Keys
  • PDF not opening on WhatsApp mobile: Ensure the PDF URL is publicly accessible and the Content-Type header is application/pdf
  • Duplicate reminders sent: Add a last_reminder_sent check in your database before sending

FAQ

Is WhatsApp legal for sending invoices and payment reminders? Yes, with consent. Customers who provide their WhatsApp number for order/billing purposes have implicitly consented to business communications. For colder outreach, add an explicit opt-in at checkout.

Does Rapiwa charge per invoice message? No. Rapiwa charges $5/month flat with no per-message fees. Send 100 or 10,000 invoices at the same monthly cost.

Can I attach a payment button to the WhatsApp message? WhatsApp's official API supports interactive buttons (payment, quick reply) but only through Meta's official WhatsApp Business Platform. With Rapiwa (unofficial API), you can include a payment link in text — customers click it to pay.

How do I handle customers who pay by cheque and not online? Add a "Reply PAID if you've paid by cheque/bank transfer" option. When they reply PAID, your webhook processor updates the invoice status.

Can I integrate this with Xero, QuickBooks, or FreshBooks? Yes. These tools have webhook APIs — when an invoice is created in Xero/QuickBooks, trigger the WhatsApp notification via n8n or a custom webhook handler.