# Duesly

> Collect recurring payments on WhatsApp — customers on a cycle, automatic reminders, payment links that settle themselves, and a chase that stops after two follow-ups.

Source: https://docs.amomic.in/apps/duesly

---

Duesly is for a business with customers who pay it on a cycle and who currently chases them by hand. Veloria Home uses it for customers who pay their annual maintenance contract in monthly or quarterly instalments.

You add each customer once: name, WhatsApp number, amount and how often. Duesly raises each payment when the cycle comes around, reminds the customer on WhatsApp, follows up if it isn't paid, and stops asking after two follow-ups.

It's an [app](/apps/overview) inside Campaigns, so it needs the Growth or Enterprise plan, and every message it sends obeys your [sending rules](/campaigns/sending-rules). Setting it up and every action in it are for admins; members can read it.

## Setting it up

::: steps
::: step Install it
Open **Campaigns** and press **Set up Duesly** on the **Recurring collections** card. You need a connected WhatsApp number; reminders go from the workspace's default number.
:::
::: step Choose how customers pay
On the **Settings** tab, under **1. How customers pay**: your own UPI or QR, or a connected Razorpay account. This decides more than convenience; see [How you get paid](#how-you-get-paid).
:::
::: step Choose what customers receive
Under **2. What customers receive**, pick an approved reminder template and map its placeholders. See [Choosing the messages](#choosing-the-messages).
:::
::: step Save
**Save and finish setup**. It's enabled once both status chips at the top read **Ready** and **Template selected**.
:::
::: step Add your customers
On the **Customers** tab, **Add customer**, one at a time.
:::
:::

![Duesly before it is installed: Stop rebuilding the same payment list every month, Start setup, and the daily workflow](https://docs.amomic.in/screens/apps/duesly-start.light.webp)

*Before setup: Start setup installs Duesly and opens its Settings.*

## The four tabs

| Tab | What it's for |
|---|---|
| **Today** | What needs attention: the collection snapshot, overdue payments, and what's coming up. |
| **Payments** | Every payment: overdue, open, upcoming and paid, with how hard each has been chased. |
| **Customers** | Who pays you, how much, on what cycle, what they've paid, and what's outstanding. |
| **Settings** | How customers pay, and what the reminders say. |

The header shows Duesly's state: **Collecting**, **Setup needed** or **Paused**, with **Pause reminders** (or **Resume**) beside it.

### Today

![Duesly Today: Outstanding ₹38,412, Overdue 5, Due this week ₹27,986, Collected this month ₹1,42,318, Needs your attention and Coming up](https://docs.amomic.in/screens/apps/duesly-today.light.webp)

*Start the day here.*

- **Collection snapshot**: **Outstanding** (still expected), **Overdue** (need a decision), **Due this week**, and **Collected this month**. The line above it gives the number of active customers and their monthly value.
- **Needs your attention** lists overdue payments with **Record paid**, and **Send follow-up** (or **Send reminder**) while the chase allows another message.
- **Coming up** lists the next payments and what will happen next.
- The card at the bottom shows the collection mode, with **Change collection settings**.

## Adding a customer

**Customers → Add customer**:

![The Add a customer dialog filled in for Sneha Kulkarni, ₹1,249 every month on the 5th](https://docs.amomic.in/screens/apps/duesly-add-customer.light.webp)

*One customer, one cycle.*

| Field | Notes |
|---|---|
| **Name** | Required. Appears in the reminder. |
| **WhatsApp number** | Required. With a country code, or written as a local number in your workspace's country. |
| **Email (optional)** | Used on the payment receipt, if you send one. |
| **What they pay for** | Free text, such as *Comprehensive AMC — split AC*. Appears in the reminder. |
| **Amount (₹)** | Required, in rupees. |
| **How often** | Every week, month, 3 months, 6 months or year, or **Custom**, which asks **Every how many days?** |
| **Day of the month** | For monthly and longer cycles. Left empty, it follows the start date. See [Billing cycles](#billing-cycles). |
| **First payment due** | Leave empty to start today. |
| **Notes (optional)** | Only your team sees these. |

Every customer you add also becomes a **contact**, so their conversations sit in one place. If that link fails, the customer is still saved and reminders still go out; the row says **Not linked to a contact — retry**.

The customer list has **All**, **Active**, **Paused** and **Cancelled** views and a search. Each row has:

- the edit button;
- **Pause** (*No new payments will be raised for them*) or **Activate**;
- remove, which cancels their open payments and stops the reminders. Everything they already paid is kept.

![Duesly Customers: plans, amounts, next payment, collected and outstanding, with Add customer](https://docs.amomic.in/screens/apps/duesly-customers.light.webp)

*Every customer's plan, next payment and balance.*

There's no bulk import, in the console or the API. To add many customers from code, create them one at a time with the [Duesly API](/api/apps-duesly).

::: tip Changing an amount
A new amount applies to payments raised from now on. Payments are raised two cycles ahead, so the next one or two are usually raised already, and they keep the amount your customer was actually asked for.
:::

## Billing cycles

Calendar cycles are calendar-correct. A customer billed on the 31st is billed on **28 February**, not the 3rd of March; rolling into the next month would slide every later cycle forward.

Set **Day of the month** if you want the preferred day to come back after a short month: with it set to 31, March is billed on the 31st again. Left empty, each payment follows the previous one, so after February the customer stays on the 28th.

Payments are raised two cycles ahead, so you can see each customer's next payment date.

## How you get paid

This is the decision everything else follows from. Choose under **Settings → 1. How customers pay**.

### Option A: your own UPI or QR

![How customers pay with Your own UPI or QR selected: UPI ID, Payable to, QR code image URL and the no automatic follow-up note](https://docs.amomic.in/screens/apps/duesly-settings-upi.light.webp)

*Your own UPI: you record what arrives.*

| Field | What it does |
|---|---|
| **UPI ID** | Looks like `name@bank`. Goes into the reminder. |
| **Payable to** | The name your customer sees in their UPI app. |
| **QR code image URL** | A link to your QR image, from your website or storage. The reminder attaches it. |
| **Anything to add to the reminder?** | A line such as *please share the UPI reference once you have paid*. |

Your customer pays you directly; nothing passes through Amomic-AI. There is **no automatic follow-up** in this mode. Instead, **Payments** lists every unpaid payment with a one-tap **Paid** and a **Follow up** you send when you know the money hasn't arrived.

### Why manual mode has no auto follow-up

This is deliberate. A UPI transfer into your bank leaves no signal Duesly can read, so it can't know a payment happened. An automatic follow-up in this mode would routinely chase people who have **already paid**, and being chased for money you've already sent is one of the fastest ways to lose a customer's trust.

Automatic follow-ups exist only where a gateway can say whether the money arrived. **Follow up automatically** is switched off and can't be turned on in UPI mode.

### Option B: connect Razorpay

Each reminder carries a hosted Razorpay payment link. When it's paid:

- the payment closes itself;
- the remaining follow-ups are cancelled;
- a receipt goes out, if you turned receipts on;
- the link is cancelled so nobody can pay twice.

Because the gateway reports payments, the follow-ups can run on their own.

::: info What we can and cannot see
We never see a card number. Your customer pays on Razorpay's own page. Your API keys are stored encrypted and never shown again, including to you.
:::

## Connecting Razorpay

Choose **Connect Razorpay**, then enter:

| Field | Where it comes from |
|---|---|
| **Key ID** | Razorpay dashboard → Account & Settings → API Keys |
| **Key secret** | Shown once when you generate the key pair. Stored encrypted. |
| **Webhook secret** | **You choose it**: at least 16 characters. Use the same value when you add Duesly's webhook in Razorpay (below). |

The keys are checked with Razorpay before they're saved, so a typo fails straight away. Once connected, the panel reads **Connected as** your key id, with **Disconnect**.

![Razorpay connected: Connected as rzp_live_…, Disconnect, and the webhook URL to add in the Razorpay dashboard](https://docs.amomic.in/screens/apps/duesly-settings-razorpay.light.webp)

*Connected. One more step happens in Razorpay.*

### Razorpay webhook

One step happens in Razorpay's dashboard, and it's the step people miss.

::: steps
::: step Copy the URL
Under **One more step in your Razorpay dashboard**, copy the webhook URL. It's specific to your workspace.
:::
::: step Add it in Razorpay
In the Razorpay dashboard, **Settings → Webhooks**, add the URL and subscribe it to **`payment_link.paid`**.
:::
::: step Use the same secret
Enter the webhook secret you chose in Duesly.
:::
:::

Without it, a paid link doesn't close its payment: the money arrives and Duesly keeps chasing. Until the secret is set, the connection shows **Webhook not set up**.

::: warning Disconnecting
**Disconnect** forgets the API key and switches new payments to manual UPI, which you collect and mark paid yourself. No new payment links are created. It also turns **Follow up automatically** off; turn it back on if you reconnect.

Links already sent stay payable, and their payments are still recorded automatically: Duesly keeps the webhook secret they were sent under and keeps checking Razorpay's notifications against it. Leave the webhook in your Razorpay dashboard until those links have expired. If no webhook secret was set when you disconnected, there is nothing to check against: record those payments with **Paid**.
:::

## Choosing the messages

Under **Settings → 2. What customers receive**:

![What customers receive: Reminder, Follow-up and Payment received templates, days early, Define template variables, the customer preview, and the follow-up and receipt switches](https://docs.amomic.in/screens/apps/duesly-settings-messages.light.webp)

*Three templates, their placeholders, and the two switches.*

| Setting | What it does |
|---|---|
| **Reminder** | Required. The approved template sent when a payment is due. |
| **Follow-up** | Optional. Left empty, the reminder template is reused. |
| **Payment received** | Optional thank-you once a payment is recorded. |
| **Send the reminder this many days early** | 0 to 14. 0 sends it on the due date. |
| **Define template variables** | Tells Duesly what fills each `{{n}}` in the chosen template: **Customer name**, **Amount**, **Plan or billing period**, **Due date**, or **Payment link or UPI**. A template can have at most five placeholders. |
| **Follow up automatically** | One follow-up a day, twice, then the payment is marked stopped. Razorpay only; on by default. |
| **Send a receipt** | Sends the **Payment received** template when a payment is recorded. Needs that template. |

**Customer preview** shows the chosen template filled with example values, and **Payment value** shows what fills a *Payment link or UPI* placeholder. **Create or generate** opens the template composer if you need a new template; it still needs Meta's approval.

By default the placeholders run in this order, most essential first, so a shorter template loses the least important detail:

| Placeholder | Value |
|---|---|
| `{{1}}` | Customer name |
| `{{2}}` | Amount, formatted (`₹1,249.00`) |
| `{{3}}` | What it's for, and the period |
| `{{4}}` | The due date |
| `{{5}}` | A payment link, or your UPI ID |

## The reminder ladder

Three messages, then it stops.

```text
  Upcoming ──(due date)──▶ Reminder ──(+1 day)──▶ Follow-up ──(+1 day)──▶ Second
  follow-up ──(+1 day)──▶ Stopped chasing

  At any point:  paid ──▶ Paid      (follow-ups cancelled, link cancelled)
                 waived ──▶ Waived  (your decision)
```

- **One reminder**, on the due date, or up to 14 days earlier.
- **At most two follow-ups**, one a day, with Razorpay and **Follow up automatically** on.
- Then the payment is marked **Stopped chasing** and left for you.

**Stopped chasing doesn't mean the customer refused.** It means Duesly has stopped asking. The payment stays on **Payments** for you to handle in person: a call, a conversation, a waiver.

A **Paid late?** button appears on these payments, but recording a payment on one fails today: only open payments can be marked paid. If a customer pays after the chase ended, keep the reference in your own records for now.

You can also step in early. On **Payments**, **Remind now** sends the reminder for an upcoming payment straight away, and **Follow up** sends the next follow-up. **Follow up** is disabled once a reminder and two follow-ups have gone out.

::: danger The limit is fixed
A reminder and two follow-ups is the maximum, and no setting, plan or API call raises it. A payment reminder must not be able to become harassment.
:::

## Payments

![The Duesly payment register on the Overdue view, with statuses, the 3-dot chase indicator, next step, payment links and Paid, Follow up and Waive](https://docs.amomic.in/screens/apps/duesly-payments.light.webp)

*The payment register: overdue first.*

The **Payment register** has **Overdue**, **Open**, **Upcoming** and **Paid** views. Each row shows the customer and due date, the amount and period, the status with dots for how many of the three messages have gone out, the next step, and the payment link. **See the message that went out** opens the campaign the reminder was sent in, with its per-recipient outcome.

| Status | Meaning |
|---|---|
| **Upcoming** | Raised, not yet reminded. |
| **Reminded** | The reminder went out. |
| **Followed up** / **Followed up twice** | One or two follow-ups went out. |
| **Paid** | Recorded as paid, by the gateway or by you. |
| **Stopped chasing** | The ladder ended unpaid. |
| **Waived** | You stopped collecting it on purpose. |
| **Cancelled** | The customer was removed or their plan changed. |

## Recording a payment

**Paid** (on **Payments**) or **Record paid** (on **Today**) opens **Record payment from** the customer. Used constantly in UPI mode, and now and then with Razorpay for cash, a bank transfer or a cheque.

![Record payment from Rahul Verma: ₹500 received against ₹899, today's date and a UPI reference](https://docs.amomic.in/screens/apps/duesly-record-payment.light.webp)

*A partial payment, recorded as it happened.*

| Field | Notes |
|---|---|
| **Amount received (₹)** | You can record less than was asked for. It's recorded as it happened. |
| **When** | The payment date; today by default. |
| **Reference (optional)** | A UPI transaction id or cheque number. |
| **Note (optional)** | Anything else. |

**Mark as paid** stops all further reminders for that payment, and cancels its payment link so nobody pays twice.

**Waive** stops collecting a payment on purpose: *Duesly stops every reminder for this payment and it is never counted as collected.* From the console the reason recorded is *Waived from the console*; the [Duesly API](/api/apps-duesly) accepts your own.

## Troubleshooting

::: accordion
::: details Nothing is being sent
Check the header doesn't say **Paused**, and that setup is finished: a **Finish setup before adding customers** banner names the one thing missing. Reminders go out once a day inside your [sending hours](/campaigns/scheduling#quiet-hours), and never to someone who opted out or is over the weekly limit.
:::
::: details A payment was paid but is still being chased
In UPI mode Duesly can't see it: record it as paid. With Razorpay, the webhook isn't set up or its secret doesn't match; see [Razorpay webhook](#razorpay-webhook).
:::
::: details Reminders have no payment link
Either you're in UPI mode, or a link couldn't be created; the payment row shows why. The usual cause is an API key without payment-link permission.
:::
::: details Razorpay rejected the keys
`gateway_invalid_credentials`. Check the secret belongs to the same key id, and that the key may create payment links. Use live keys for real payments.
:::
::: details A customer is marked as not linked to a contact
The contact lookup failed, or the details match two different contacts. Press **retry**. If it keeps failing, look in **Contacts** for a duplicate and merge it; Duesly won't guess which one is right.
:::
::: details A reminder wasn't delivered
It went out as a campaign, so it has a per-recipient outcome. Press **See the message that went out** on the payment row and read the reason: usually an opt-out, the weekly limit, or a template problem. The reason also shows on the payment row.
:::
:::

## From your own code

Customers, payments and recording payments are all on the API, and `payment.paid` and `payment.declined` webhooks fire as they happen. See [Duesly API](/api/apps-duesly).
