---
title: Recurring payments
description: Ask a customer once to approve future debits, then charge them without a prompt each time.
---

A **pre-approval** is a customer's standing approval for your collection account to debit them. Once they approve it, payments you request under it go through without asking them again. Use it for subscriptions, memberships and instalments.

:::note
MTN enables pre-approvals per merchant contract. If yours doesn't include them, the request fails with a `NOT_ALLOWED` reason.
:::

## 1. Request the pre-approval

```bash
curl -X POST https://api.razpay.razonetix.com/v1/preapprovals \
  -H "Authorization: Bearer $RAZPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_reference": "gym-membership-sipho",
    "provider": "momo",
    "phone_number": "76123456",
    "currency": "SZL",
    "message": "Monthly gym membership",
    "validity_seconds": 31536000
  }'
```

The customer gets a prompt to approve it. `validity_seconds` is how long the approval lasts once given (here, a year).

RazPay appends a short tag such as ` Ref 11377CBE` to your message. MTN doesn't return your reference in its own records, so the tag is how RazPay matches the approval later, for example to cancel it.

## 2. Wait for approval

You get `preapproval.approved`, or `preapproval.failed` if the customer rejects it. If they don't answer within 24 hours it becomes `expired`. Check it any time with [`GET /preapprovals/{reference}`](/docs/api/get-preapproval).

## 3. Charge under it

Collect as usual, adding `preapproval_reference`:

```bash
curl -X POST https://api.razpay.razonetix.com/v1/payments/collect \
  -H "Authorization: Bearer $RAZPAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_reference": "gym-2026-11-sipho",
    "provider": "momo",
    "amount": 350.00,
    "currency": "SZL",
    "phone_number": "76123456",
    "preapproval_reference": "gym-membership-sipho"
  }'
```

RazPay only charges under a pre-approval that is `approved`, not past its expiry, and given by the **same number** in the **same currency**. Anything else is rejected before a request reaches the customer. You decide when to charge; RazPay doesn't schedule charges for you.

## Cancelling

Cancel an approved pre-approval with [`DELETE /preapprovals/{reference}`](/docs/api/cancel-preapproval), or from **Pre-approvals** in the dashboard. It's cancelled at MTN too, and you get `preapproval.cancelled`.

Customers can also cancel from their phone. RazPay re-checks approved pre-approvals about once an hour, and marks one `cancelled` (with `failure_reason: cancelled by the payer`) when it's gone. A charge under a cancelled pre-approval is rejected.

## Statuses

| Status | Meaning |
| --- | --- |
| `pending` | Waiting for the customer. |
| `approved` | You can charge under it. |
| `failed` | Rejected or failed. See `failure_reason`. |
| `cancelled` | Cancelled by you or the customer. |
| `expired` | Past its validity, or never answered. |
