Send Zoho Books Payment Reminders Automatically with Deluge

Auto-Generate Zoho Books Invoices and Payment Reminders from Creator

Chasing invoices is the job nobody wants and everybody forgets. This scheduled function asks Zoho Books each morning which invoices are overdue and sends a reminder — but only at 7, 14 and 30 days, so your customers get a nudge rather than a daily email.

Updated for the current Books tasks. Zoho retired legacy authtokens entirely — deprecation was announced in December 2020 and every existing token stopped working on 1 April 2021. Any script still passing ?authtoken= has been failing for years. Everything now goes through OAuth 2.0 with a named Zoho connection. The legacy getUrl() and postUrl() tasks go with it — use invokeurl or the native integration tasks. This script was one of the newer ones and was structurally sound; the change is that every zoho.books.* task now takes a mandatory connection argument, which the original omitted. The reminder call itself has no native task at all and has to go through invokeurl.

Before you start

  • A Zoho OAuth connection named zoho_books_connection with ZohoBooks.invoices.READ and ZohoBooks.invoices.CREATE.
  • Your Books organization ID.
  • A scheduled function in Creator set to run once daily. Do not attach this to a form workflow.

Deluge function

// ============================================
// SCHEDULED FUNCTION — runs daily
// Send Zoho Books payment reminders on overdue invoices
// ============================================

void Books.sendOverdueReminders()
{
    ORG_ID = "YOUR_BOOKS_ORG_ID";
    CONN   = "zoho_books_connection";

    // 1. Ask Books for overdue invoices only
    criteria = Map();
    criteria.put("status","overdue");

    resp = zoho.books.getRecords("invoices",ORG_ID,criteria,CONN);
    invoices = resp.get("invoices");

    if(invoices == null || invoices.size() == 0)
    {
        info "No overdue invoices today.";
        return;
    }

    sent = 0;
    for each inv in invoices
    {
        invoiceId  = inv.get("invoice_id");
        daysOver   = inv.get("days_overdue").toLong();

        // 2. Only nudge on a schedule: 7, 14 and 30 days
        if(daysOver == 7 || daysOver == 14 || daysOver == 30)
        {
            // No native task for reminders - call the endpoint directly
            reminderResp = invokeurl
            [
                url  : "https://www.zohoapis.com/books/v3/invoices/" + invoiceId
                       + "/paymentreminder?organization_id=" + ORG_ID
                type : POST
                connection : CONN
            ];

            info "Reminder for " + inv.get("invoice_number")
                 + " (" + daysOver + " days): " + reminderResp.toString();
            sent = sent + 1;
        }
    }
    info "Reminders sent: " + sent;
}

Notes

  • Filter server-side. Passing status: overdue lets Books do the work. Fetching every invoice and filtering in Deluge burns API calls and will time out on a real ledger.
  • The day gate is what makes this humane. Without the daysOver check, every overdue customer gets an email every single day until they pay. That is how a helpful automation becomes a complaint.
  • Reminders have their own endpoints. POST .../paymentreminder sends one, GET the same path previews the email body, and there is a bulk variant at /invoices/paymentreminder. None have native Deluge tasks.
  • Paginate on real data. Books pages its list endpoints. Past a couple of hundred overdue invoices you need to walk page until page_context.has_more_page is false.

This script is part of the free Creator Scripts Deluge Library.

All 39 Deluge scripts, the full Zoho Creator course, and every downloadable asset are now free. Get free access →